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 }