github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/apiserver/metricsender/metricsender.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package metricsender contains functions for sending 5 // metrics from a state server to a remote metric collector. 6 package metricsender 7 8 import ( 9 "time" 10 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 14 "github.com/juju/juju/apiserver/metricsender/wireformat" 15 "github.com/juju/juju/state" 16 ) 17 18 var logger = loggo.GetLogger("juju.apiserver.metricsender") 19 20 // MetricSender defines the interface used to send metrics 21 // to a collection service. 22 type MetricSender interface { 23 Send([]*wireformat.MetricBatch) (*wireformat.Response, error) 24 } 25 26 func handleResponse(mm *state.MetricsManager, st *state.State, response wireformat.Response) { 27 for _, envResp := range response.EnvResponses { 28 err := st.SetMetricBatchesSent(envResp.AcknowledgedBatches) 29 if err != nil { 30 logger.Errorf("failed to set sent on metrics %v", err) 31 } 32 for unitName, status := range envResp.UnitStatuses { 33 unit, err := st.Unit(unitName) 34 if err != nil { 35 logger.Errorf("failed to retrieve unit %q: %v", unitName, err) 36 continue 37 } 38 err = unit.SetMeterStatus(status.Status, status.Info) 39 if err != nil { 40 logger.Errorf("failed to set unit %q meter status to %v: %v", unitName, status, err) 41 } 42 } 43 } 44 if response.NewGracePeriod > 0 { 45 err := mm.SetGracePeriod(response.NewGracePeriod) 46 if err != nil { 47 logger.Errorf("failed to set new grace period %v", err) 48 } 49 } 50 } 51 52 // SendMetrics will send any unsent metrics 53 // over the MetricSender interface in batches 54 // no larger than batchSize. 55 func SendMetrics(st *state.State, sender MetricSender, batchSize int) error { 56 metricsManager, err := st.MetricsManager() 57 if err != nil { 58 return errors.Trace(err) 59 } 60 for { 61 metrics, err := st.MetricsToSend(batchSize) 62 if err != nil { 63 return errors.Trace(err) 64 } 65 if len(metrics) == 0 { 66 logger.Infof("nothing to send") 67 break 68 } 69 wireData := make([]*wireformat.MetricBatch, len(metrics)) 70 for i, m := range metrics { 71 wireData[i] = wireformat.ToWire(m) 72 } 73 response, err := sender.Send(wireData) 74 if err != nil { 75 logger.Errorf("%+v", err) 76 if incErr := metricsManager.IncrementConsecutiveErrors(); incErr != nil { 77 logger.Errorf("failed to increment error count %v", incErr) 78 return errors.Trace(errors.Wrap(err, incErr)) 79 } 80 return errors.Trace(err) 81 } 82 if response != nil { 83 // TODO (mattyw) We are currently ignoring errors during response handling. 84 handleResponse(metricsManager, st, *response) 85 if err := metricsManager.SetLastSuccessfulSend(time.Now()); err != nil { 86 err = errors.Annotate(err, "failed to set successful send time") 87 logger.Warningf("%v", err) 88 return errors.Trace(err) 89 } 90 } 91 } 92 93 unsent, err := st.CountOfUnsentMetrics() 94 if err != nil { 95 return errors.Trace(err) 96 } 97 sent, err := st.CountOfSentMetrics() 98 if err != nil { 99 return errors.Trace(err) 100 } 101 logger.Infof("metrics collection summary: sent:%d unsent:%d", sent, unsent) 102 103 return nil 104 }