func (s *sender) sendMetrics(reader spool.MetricReader) error { batches, err := reader.Read() if err != nil { return errors.Annotate(err, "failed to open the metric reader") } var sendBatches []params.MetricBatchParam for _, batch := range batches { sendBatches = append(sendBatches, spool.APIMetricBatch(batch)) } results, err := s.client.AddMetricBatches(sendBatches) if err != nil { return errors.Annotate(err, "could not send metrics") } for batchUUID, resultErr := range results { // if we fail to send any metric batch we log a warning with the assumption that // the unsent metric batches remain in the spool directory and will be sent to the // controller when the network partition is restored. if _, ok := resultErr.(*params.Error); ok || params.IsCodeAlreadyExists(resultErr) { err := reader.Remove(batchUUID) if err != nil { logger.Errorf("could not remove batch %q from spool: %v", batchUUID, err) } } else { logger.Errorf("failed to send batch %q: %v", batchUUID, resultErr) } } return nil }
// Do sends metrics from the metric spool to the // state server via an api call. func (s *sender) Do(stop <-chan struct{}) error { reader, err := s.factory.Reader() if err != nil { return errors.Trace(err) } batches, err := reader.Read() if err != nil { logger.Warningf("failed to open the metric reader: %v", err) return errors.Trace(err) } defer reader.Close() var sendBatches []params.MetricBatchParam for _, batch := range batches { sendBatches = append(sendBatches, spool.APIMetricBatch(batch)) } results, err := s.client.AddMetricBatches(sendBatches) if err != nil { logger.Warningf("could not send metrics: %v", err) return errors.Trace(err) } for batchUUID, resultErr := range results { // if we fail to send any metric batch we log a warning with the assumption that // the unsent metric batches remain in the spool directory and will be sent to the // state server when the network partition is restored. if _, ok := resultErr.(*params.Error); ok || params.IsCodeAlreadyExists(resultErr) { err = reader.Remove(batchUUID) if err != nil { logger.Warningf("could not remove batch %q from spool: %v", batchUUID, err) } } else { logger.Warningf("failed to send batch %q: %v", batchUUID, resultErr) } } return nil }
func (s *metricsBatchSuite) TestAPIMetricBatch(c *gc.C) { batches := []spool.MetricBatch{{ CharmURL: "local:trusty/test-charm", UUID: "test-uuid", Created: time.Now(), Metrics: []jujuc.Metric{ { Key: "test-key-1", Value: "test-value-1", Time: time.Now(), }, { Key: "test-key-2", Value: "test-value-2", Time: time.Now(), }, }, }, { CharmURL: "local:trusty/test-charm", UUID: "test-uuid", Created: time.Now(), Metrics: []jujuc.Metric{}, }, } for _, batch := range batches { apiBatch := spool.APIMetricBatch(batch) c.Assert(apiBatch.Batch.UUID, gc.DeepEquals, batch.UUID) c.Assert(apiBatch.Batch.CharmURL, gc.DeepEquals, batch.CharmURL) c.Assert(apiBatch.Batch.Created, gc.DeepEquals, batch.Created) c.Assert(len(apiBatch.Batch.Metrics), gc.Equals, len(batch.Metrics)) for i, metric := range batch.Metrics { c.Assert(metric.Key, gc.DeepEquals, apiBatch.Batch.Metrics[i].Key) c.Assert(metric.Value, gc.DeepEquals, apiBatch.Batch.Metrics[i].Value) c.Assert(metric.Time, gc.DeepEquals, apiBatch.Batch.Metrics[i].Time) } } }