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  }