github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/metricsender/metricsender_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package metricsender_test
     5  
     6  import (
     7  	"errors"
     8  	"time"
     9  
    10  	wireformat "github.com/juju/romulus/wireformat/metrics"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils/clock"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/apiserver/metricsender"
    16  	"github.com/juju/juju/apiserver/metricsender/testing"
    17  	jujujutesting "github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/testing/factory"
    20  	jujutesting "github.com/juju/testing"
    21  )
    22  
    23  type MetricSenderSuite struct {
    24  	jujujutesting.JujuConnSuite
    25  	meteredUnit *state.Unit
    26  	credUnit    *state.Unit
    27  	clock       clock.Clock
    28  }
    29  
    30  var _ = gc.Suite(&MetricSenderSuite{})
    31  
    32  var _ metricsender.MetricSender = (*testing.MockSender)(nil)
    33  
    34  var _ metricsender.MetricSender = (*metricsender.NopSender)(nil)
    35  
    36  func (s *MetricSenderSuite) SetUpTest(c *gc.C) {
    37  	s.JujuConnSuite.SetUpTest(c)
    38  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "cs:quantal/metered"})
    39  	// Application with metrics credentials set.
    40  	credApp := s.Factory.MakeApplication(c, &factory.ApplicationParams{Charm: meteredCharm, Name: "cred"})
    41  	err := credApp.SetMetricCredentials([]byte("something here"))
    42  	c.Assert(err, jc.ErrorIsNil)
    43  	meteredApp := s.Factory.MakeApplication(c, &factory.ApplicationParams{Charm: meteredCharm})
    44  	s.meteredUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredApp, SetCharmURL: true})
    45  	s.credUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: credApp, SetCharmURL: true})
    46  	s.clock = jujutesting.NewClock(time.Now())
    47  }
    48  
    49  func (s *MetricSenderSuite) TestToWire(c *gc.C) {
    50  	now := time.Now().Round(time.Second)
    51  	metric := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: false, Time: &now})
    52  	result := metricsender.ToWire(metric)
    53  	m := metric.Metrics()[0]
    54  	metrics := []wireformat.Metric{
    55  		{
    56  			Key:   m.Key,
    57  			Value: m.Value,
    58  			Time:  m.Time.UTC(),
    59  		},
    60  	}
    61  	expected := &wireformat.MetricBatch{
    62  		UUID:        metric.UUID(),
    63  		ModelUUID:   metric.ModelUUID(),
    64  		UnitName:    metric.Unit(),
    65  		CharmUrl:    metric.CharmURL(),
    66  		Created:     metric.Created().UTC(),
    67  		Metrics:     metrics,
    68  		Credentials: metric.Credentials(),
    69  	}
    70  	c.Assert(result, gc.DeepEquals, expected)
    71  }
    72  
    73  // TestSendMetrics creates 2 unsent metrics and a sent metric
    74  // and checks that the 2 unsent metrics get marked as sent (have their
    75  // sent field set to true).
    76  func (s *MetricSenderSuite) TestSendMetrics(c *gc.C) {
    77  	var sender testing.MockSender
    78  	now := time.Now()
    79  	unsent1 := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Time: &now})
    80  	unsent2 := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.meteredUnit, Time: &now})
    81  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: true, Time: &now})
    82  	err := metricsender.SendMetrics(s.State, &sender, s.clock, 10, true)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	c.Assert(sender.Data, gc.HasLen, 1)
    85  	c.Assert(sender.Data[0], gc.HasLen, 2)
    86  
    87  	sent1, err := s.State.MetricBatch(unsent1.UUID())
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	c.Assert(sent1.Sent(), jc.IsTrue)
    90  
    91  	sent2, err := s.State.MetricBatch(unsent2.UUID())
    92  	c.Assert(err, jc.ErrorIsNil)
    93  	c.Assert(sent2.Sent(), jc.IsTrue)
    94  }
    95  
    96  // TestSendMetricsAbort creates 7 unsent metrics and
    97  // checks that the sending stops when no more batches are ack'ed.
    98  func (s *MetricSenderSuite) TestSendMetricsAbort(c *gc.C) {
    99  	sender := &testing.MockSender{}
   100  	now := time.Now()
   101  	metrics := make([]*state.MetricBatch, 7)
   102  	for i := 0; i < 7; i++ {
   103  		metrics[i] = s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Time: &now})
   104  	}
   105  
   106  	sender.IgnoreBatches(metrics[0:2]...)
   107  
   108  	// Send 4 batches per POST.
   109  	err := metricsender.SendMetrics(s.State, sender, s.clock, 4, true)
   110  	c.Assert(err, jc.ErrorIsNil)
   111  	c.Assert(sender.Data, gc.HasLen, 4)
   112  
   113  	unsent := 0
   114  	sent := 0
   115  	for _, batch := range metrics {
   116  		b, err := s.State.MetricBatch(batch.UUID())
   117  		c.Assert(err, jc.ErrorIsNil)
   118  		if b.Sent() {
   119  			sent++
   120  		} else {
   121  			unsent++
   122  		}
   123  	}
   124  	c.Assert(sent, gc.Equals, 5)
   125  	c.Assert(unsent, gc.Equals, 2)
   126  }
   127  
   128  // TestHoldMetrics creates 2 unsent metrics and a sent metric
   129  // and checks that only the metric from the application with credentials is sent.
   130  // But both metrics are marked as sent.
   131  func (s *MetricSenderSuite) TestHoldMetrics(c *gc.C) {
   132  	var sender testing.MockSender
   133  	now := time.Now()
   134  	unsent1 := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Time: &now})
   135  	unsent2 := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.meteredUnit, Time: &now})
   136  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: true, Time: &now})
   137  	err := metricsender.SendMetrics(s.State, &sender, s.clock, 10, false)
   138  	c.Assert(err, jc.ErrorIsNil)
   139  	c.Assert(sender.Data, gc.HasLen, 1)
   140  	c.Assert(sender.Data[0], gc.HasLen, 1)
   141  	c.Assert(sender.Data[0][0].UUID, gc.Equals, unsent1.UUID())
   142  	sent1, err := s.State.MetricBatch(unsent1.UUID())
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	c.Assert(sent1.Sent(), jc.IsTrue)
   145  
   146  	sent2, err := s.State.MetricBatch(unsent2.UUID())
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	c.Assert(sent2.Sent(), jc.IsTrue)
   149  }
   150  
   151  func (s *MetricSenderSuite) TestHoldMetricsSetsMeterStatus(c *gc.C) {
   152  	var sender testing.MockSender
   153  	now := time.Now()
   154  	err := s.credUnit.SetMeterStatus("GREEN", "known starting point")
   155  	c.Assert(err, jc.ErrorIsNil)
   156  	err = s.meteredUnit.SetMeterStatus("GREEN", "known starting point")
   157  	c.Assert(err, jc.ErrorIsNil)
   158  	unsent1 := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Time: &now})
   159  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.meteredUnit, Time: &now})
   160  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: true, Time: &now})
   161  	err = metricsender.SendMetrics(s.State, &sender, s.clock, 10, false)
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	c.Assert(sender.Data, gc.HasLen, 1)
   164  	c.Assert(sender.Data[0], gc.HasLen, 1)
   165  	c.Assert(sender.Data[0][0].UUID, gc.Equals, unsent1.UUID())
   166  	msCred, err := s.credUnit.GetMeterStatus()
   167  	c.Assert(msCred.Code, gc.Equals, state.MeterGreen)
   168  	c.Assert(msCred.Info, gc.Equals, "known starting point")
   169  	msMetered, err := s.meteredUnit.GetMeterStatus()
   170  	c.Assert(msMetered.Code, gc.Equals, state.MeterRed)
   171  	c.Assert(msMetered.Info, gc.Equals, "transmit-vendor-metrics turned off")
   172  }
   173  
   174  // TestSendBulkMetrics tests the logic of splitting sends
   175  // into batches is done correctly. The batch size is changed
   176  // to send batches of 10 metrics. If we create 100 metrics 10 calls
   177  // will be made to the sender
   178  func (s *MetricSenderSuite) TestSendBulkMetrics(c *gc.C) {
   179  	var sender testing.MockSender
   180  	now := time.Now()
   181  	for i := 0; i < 100; i++ {
   182  		s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Time: &now})
   183  	}
   184  	err := metricsender.SendMetrics(s.State, &sender, s.clock, 10, true)
   185  	c.Assert(err, jc.ErrorIsNil)
   186  
   187  	c.Assert(sender.Data, gc.HasLen, 10)
   188  	for _, d := range sender.Data {
   189  		c.Assert(d, gc.HasLen, 10)
   190  	}
   191  }
   192  
   193  // TestDontSendWithNopSender check that if the default sender
   194  // is nil we don't send anything, but still mark the items as sent
   195  func (s *MetricSenderSuite) TestDontSendWithNopSender(c *gc.C) {
   196  	now := time.Now()
   197  	for i := 0; i < 3; i++ {
   198  		s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: false, Time: &now})
   199  	}
   200  	err := metricsender.SendMetrics(s.State, metricsender.NopSender{}, s.clock, 10, true)
   201  	c.Assert(err, jc.ErrorIsNil)
   202  	sent, err := s.State.CountOfSentMetrics()
   203  	c.Assert(err, jc.ErrorIsNil)
   204  	c.Assert(sent, gc.Equals, 3)
   205  }
   206  
   207  func (s *MetricSenderSuite) TestFailureIncrementsConsecutiveFailures(c *gc.C) {
   208  	sender := &testing.ErrorSender{Err: errors.New("something went wrong")}
   209  	now := time.Now()
   210  	for i := 0; i < 3; i++ {
   211  		s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: false, Time: &now})
   212  	}
   213  	err := metricsender.SendMetrics(s.State, sender, s.clock, 1, true)
   214  	c.Assert(err, gc.ErrorMatches, "something went wrong")
   215  	mm, err := s.State.MetricsManager()
   216  	c.Assert(err, jc.ErrorIsNil)
   217  	c.Assert(mm.ConsecutiveErrors(), gc.Equals, 1)
   218  }
   219  
   220  func (s *MetricSenderSuite) TestFailuresResetOnSuccessfulSend(c *gc.C) {
   221  	mm, err := s.State.MetricsManager()
   222  	c.Assert(err, jc.ErrorIsNil)
   223  	err = mm.IncrementConsecutiveErrors()
   224  	c.Assert(err, jc.ErrorIsNil)
   225  	now := time.Now()
   226  	for i := 0; i < 3; i++ {
   227  		s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.credUnit, Sent: false, Time: &now})
   228  	}
   229  	err = metricsender.SendMetrics(s.State, metricsender.NopSender{}, s.clock, 10, true)
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	mm, err = s.State.MetricsManager()
   232  	c.Assert(err, jc.ErrorIsNil)
   233  	c.Assert(mm.ConsecutiveErrors(), gc.Equals, 0)
   234  }