github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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  var (
    27  	defaultMaxBatchesPerSend              = 10
    28  	defaultSender            MetricSender = &NopSender{}
    29  )
    30  
    31  func handleResponse(mm *state.MetricsManager, st *state.State, response wireformat.Response) {
    32  	for _, envResp := range response.EnvResponses {
    33  		err := st.SetMetricBatchesSent(envResp.AcknowledgedBatches)
    34  		if err != nil {
    35  			logger.Errorf("failed to set sent on metrics %v", err)
    36  		}
    37  		for unitName, status := range envResp.UnitStatuses {
    38  			unit, err := st.Unit(unitName)
    39  			if err != nil {
    40  				logger.Errorf("failed to retrieve unit %q: %v", unitName, err)
    41  				continue
    42  			}
    43  			err = unit.SetMeterStatus(status.Status, status.Info)
    44  			if err != nil {
    45  				logger.Errorf("failed to set unit %q meter status to %v: %v", unitName, status, err)
    46  			}
    47  		}
    48  	}
    49  	if response.NewGracePeriod > 0 {
    50  		err := mm.SetGracePeriod(response.NewGracePeriod)
    51  		if err != nil {
    52  			logger.Errorf("failed to set new grace period %v", err)
    53  		}
    54  	}
    55  }
    56  
    57  // SendMetrics will send any unsent metrics
    58  // over the MetricSender interface in batches
    59  // no larger than batchSize.
    60  func SendMetrics(st *state.State, sender MetricSender, batchSize int) error {
    61  	metricsManager, err := st.MetricsManager()
    62  	if err != nil {
    63  		return errors.Trace(err)
    64  	}
    65  	sent := 0
    66  	for {
    67  		metrics, err := st.MetricsToSend(batchSize)
    68  		if err != nil {
    69  			return errors.Trace(err)
    70  		}
    71  		lenM := len(metrics)
    72  		if lenM == 0 {
    73  			if sent == 0 {
    74  				logger.Infof("nothing to send")
    75  			} else {
    76  				logger.Infof("done sending")
    77  			}
    78  			break
    79  		}
    80  		wireData := make([]*wireformat.MetricBatch, lenM)
    81  		for i, m := range metrics {
    82  			wireData[i] = wireformat.ToWire(m)
    83  		}
    84  		response, err := sender.Send(wireData)
    85  		if err != nil {
    86  			logger.Errorf("%+v", err)
    87  			if incErr := metricsManager.IncrementConsecutiveErrors(); incErr != nil {
    88  				logger.Errorf("failed to increment error count %v", incErr)
    89  				return errors.Trace(errors.Wrap(err, incErr))
    90  			}
    91  			return errors.Trace(err)
    92  		}
    93  		if response != nil {
    94  			// TODO (mattyw) We are currently ignoring errors during response handling.
    95  			handleResponse(metricsManager, st, *response)
    96  			if err := metricsManager.SetLastSuccessfulSend(time.Now()); err != nil {
    97  				err = errors.Annotate(err, "failed to set successful send time")
    98  				logger.Warningf("%v", err)
    99  				return errors.Trace(err)
   100  			}
   101  		}
   102  		sent += lenM
   103  	}
   104  
   105  	unsent, err := st.CountOfUnsentMetrics()
   106  	if err != nil {
   107  		return errors.Trace(err)
   108  	}
   109  	sentStored, err := st.CountOfSentMetrics()
   110  	if err != nil {
   111  		return errors.Trace(err)
   112  	}
   113  	logger.Infof("metrics collection summary: sent:%d unsent:%d (%d sent metrics stored)", sent, unsent, sentStored)
   114  
   115  	return nil
   116  }
   117  
   118  // DefaultMaxBatchesPerSend returns the default number of batches per send.
   119  func DefaultMaxBatchesPerSend() int {
   120  	return defaultMaxBatchesPerSend
   121  }
   122  
   123  // DefaultMetricSender returns the default metric sender.
   124  func DefaultMetricSender() MetricSender {
   125  	return defaultSender
   126  }