// SendMetrics will send any unsent metrics // over the MetricSender interface in batches // no larger than batchSize. func SendMetrics(st *state.State, sender MetricSender, batchSize int) error { metricsManager, err := st.MetricsManager() if err != nil { return errors.Trace(err) } sent := 0 for { metrics, err := st.MetricsToSend(batchSize) if err != nil { return errors.Trace(err) } lenM := len(metrics) if lenM == 0 { if sent == 0 { logger.Infof("nothing to send") } else { logger.Infof("done sending") } break } wireData := make([]*wireformat.MetricBatch, lenM) for i, m := range metrics { wireData[i] = ToWire(m) } response, err := sender.Send(wireData) if err != nil { logger.Errorf("%+v", err) if incErr := metricsManager.IncrementConsecutiveErrors(); incErr != nil { logger.Errorf("failed to increment error count %v", incErr) return errors.Trace(errors.Wrap(err, incErr)) } return errors.Trace(err) } if response != nil { // TODO (mattyw) We are currently ignoring errors during response handling. handleResponse(metricsManager, st, *response) // TODO(fwereade): 2016-03-17 lp:1558657 if err := metricsManager.SetLastSuccessfulSend(time.Now()); err != nil { err = errors.Annotate(err, "failed to set successful send time") logger.Warningf("%v", err) return errors.Trace(err) } } sent += lenM } unsent, err := st.CountOfUnsentMetrics() if err != nil { return errors.Trace(err) } sentStored, err := st.CountOfSentMetrics() if err != nil { return errors.Trace(err) } logger.Infof("metrics collection summary: sent:%d unsent:%d (%d sent metrics stored)", sent, unsent, sentStored) return nil }