github.com/lulzWill/go-agent@v2.1.2+incompatible/internal/metrics_test.go (about) 1 package internal 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "testing" 7 "time" 8 ) 9 10 var ( 11 start = time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC) 12 end = time.Date(2014, time.November, 28, 1, 2, 0, 0, time.UTC) 13 ) 14 15 func TestEmptyMetrics(t *testing.T) { 16 mt := newMetricTable(20, start) 17 js, err := mt.CollectorJSON(`12345`, end) 18 if nil != err { 19 t.Fatal(err) 20 } 21 if nil != js { 22 t.Error(string(js)) 23 } 24 } 25 26 func isValidJSON(data []byte) error { 27 var v interface{} 28 29 return json.Unmarshal(data, &v) 30 } 31 32 func TestMetrics(t *testing.T) { 33 mt := newMetricTable(20, start) 34 35 mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 36 mt.addDuration("two", "my_scope", 4*time.Second, 2*time.Second, unforced) 37 mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced) 38 mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 39 40 mt.addApdex("apdex satisfied", "", 9*time.Second, ApdexSatisfying, unforced) 41 mt.addApdex("apdex satisfied", "", 8*time.Second, ApdexSatisfying, unforced) 42 mt.addApdex("apdex tolerated", "", 7*time.Second, ApdexTolerating, unforced) 43 mt.addApdex("apdex tolerated", "", 8*time.Second, ApdexTolerating, unforced) 44 mt.addApdex("apdex failed", "my_scope", 1*time.Second, ApdexFailing, unforced) 45 46 mt.addCount("count 123", float64(123), unforced) 47 mt.addSingleCount("count 1", unforced) 48 49 ExpectMetrics(t, mt, []WantMetric{ 50 {"apdex satisfied", "", false, []float64{2, 0, 0, 8, 9, 0}}, 51 {"apdex tolerated", "", false, []float64{0, 2, 0, 7, 8, 0}}, 52 {"one", "", false, []float64{2, 4, 2, 2, 2, 8}}, 53 {"apdex failed", "my_scope", false, []float64{0, 0, 1, 1, 1, 0}}, 54 {"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}}, 55 {"two", "my_scope", false, []float64{1, 4, 2, 4, 4, 16}}, 56 {"count 123", "", false, []float64{123, 0, 0, 0, 0, 0}}, 57 {"count 1", "", false, []float64{1, 0, 0, 0, 0, 0}}, 58 }) 59 60 js, err := mt.Data("12345", end) 61 if nil != err { 62 t.Error(err) 63 } 64 // The JSON metric order is not deterministic, so we merely test that it 65 // is valid JSON. 66 if err := isValidJSON(js); nil != err { 67 t.Error(err, string(js)) 68 } 69 } 70 71 func TestApplyRules(t *testing.T) { 72 js := `[ 73 { 74 "ignore":false, 75 "each_segment":false, 76 "terminate_chain":true, 77 "replacement":"been_renamed", 78 "replace_all":false, 79 "match_expression":"one$", 80 "eval_order":1 81 }, 82 { 83 "ignore":true, 84 "each_segment":false, 85 "terminate_chain":true, 86 "replace_all":false, 87 "match_expression":"ignore_me", 88 "eval_order":1 89 }, 90 { 91 "ignore":false, 92 "each_segment":false, 93 "terminate_chain":true, 94 "replacement":"merge_me", 95 "replace_all":false, 96 "match_expression":"merge_me[0-9]+$", 97 "eval_order":1 98 } 99 ]` 100 var rules metricRules 101 err := json.Unmarshal([]byte(js), &rules) 102 if nil != err { 103 t.Fatal(err) 104 } 105 106 mt := newMetricTable(20, start) 107 mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 108 mt.addDuration("one", "scope1", 2*time.Second, 1*time.Second, unforced) 109 mt.addDuration("one", "scope2", 2*time.Second, 1*time.Second, unforced) 110 mt.addDuration("ignore_me", "", 2*time.Second, 1*time.Second, unforced) 111 mt.addDuration("ignore_me", "scope1", 2*time.Second, 1*time.Second, unforced) 112 mt.addDuration("ignore_me", "scope2", 2*time.Second, 1*time.Second, unforced) 113 mt.addDuration("merge_me1", "", 2*time.Second, 1*time.Second, unforced) 114 mt.addDuration("merge_me2", "", 2*time.Second, 1*time.Second, unforced) 115 116 applied := mt.ApplyRules(rules) 117 ExpectMetrics(t, applied, []WantMetric{ 118 {"been_renamed", "", false, []float64{1, 2, 1, 2, 2, 4}}, 119 {"been_renamed", "scope1", false, []float64{1, 2, 1, 2, 2, 4}}, 120 {"been_renamed", "scope2", false, []float64{1, 2, 1, 2, 2, 4}}, 121 {"merge_me", "", false, []float64{2, 4, 2, 2, 2, 8}}, 122 }) 123 } 124 125 func TestApplyEmptyRules(t *testing.T) { 126 js := `[]` 127 var rules metricRules 128 err := json.Unmarshal([]byte(js), &rules) 129 if nil != err { 130 t.Fatal(err) 131 } 132 mt := newMetricTable(20, start) 133 mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 134 mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced) 135 applied := mt.ApplyRules(rules) 136 ExpectMetrics(t, applied, []WantMetric{ 137 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 138 {"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}}, 139 }) 140 } 141 142 func TestApplyNilRules(t *testing.T) { 143 var rules metricRules 144 145 mt := newMetricTable(20, start) 146 mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 147 mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced) 148 applied := mt.ApplyRules(rules) 149 ExpectMetrics(t, applied, []WantMetric{ 150 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 151 {"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}}, 152 }) 153 } 154 155 func TestForced(t *testing.T) { 156 mt := newMetricTable(0, start) 157 158 if mt.numDropped != 0 { 159 t.Fatal(mt.numDropped) 160 } 161 162 mt.addDuration("unforced", "", 1*time.Second, 1*time.Second, unforced) 163 mt.addDuration("forced", "", 2*time.Second, 2*time.Second, forced) 164 165 if mt.numDropped != 1 { 166 t.Fatal(mt.numDropped) 167 } 168 169 ExpectMetrics(t, mt, []WantMetric{ 170 {"forced", "", true, []float64{1, 2, 2, 2, 2, 4}}, 171 }) 172 173 } 174 175 func TestMetricsMergeIntoEmpty(t *testing.T) { 176 src := newMetricTable(20, start) 177 src.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 178 src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 179 dest := newMetricTable(20, start) 180 dest.merge(src, "") 181 182 ExpectMetrics(t, dest, []WantMetric{ 183 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 184 {"two", "", false, []float64{1, 2, 1, 2, 2, 4}}, 185 }) 186 } 187 188 func TestMetricsMergeFromEmpty(t *testing.T) { 189 src := newMetricTable(20, start) 190 dest := newMetricTable(20, start) 191 dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 192 dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 193 dest.merge(src, "") 194 195 ExpectMetrics(t, dest, []WantMetric{ 196 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 197 {"two", "", false, []float64{1, 2, 1, 2, 2, 4}}, 198 }) 199 } 200 201 func TestMetricsMerge(t *testing.T) { 202 src := newMetricTable(20, start) 203 dest := newMetricTable(20, start) 204 dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 205 dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 206 src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 207 src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced) 208 209 dest.merge(src, "") 210 211 ExpectMetrics(t, dest, []WantMetric{ 212 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 213 {"two", "", false, []float64{2, 4, 2, 2, 2, 8}}, 214 {"three", "", false, []float64{1, 2, 1, 2, 2, 4}}, 215 }) 216 } 217 218 func TestMergeFailedSuccess(t *testing.T) { 219 src := newMetricTable(20, start) 220 dest := newMetricTable(20, end) 221 dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 222 dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 223 src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 224 src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced) 225 226 if 0 != dest.failedHarvests { 227 t.Fatal(dest.failedHarvests) 228 } 229 230 dest.mergeFailed(src) 231 232 ExpectMetrics(t, dest, []WantMetric{ 233 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 234 {"two", "", false, []float64{2, 4, 2, 2, 2, 8}}, 235 {"three", "", false, []float64{1, 2, 1, 2, 2, 4}}, 236 }) 237 } 238 239 func TestMergeFailedLimitReached(t *testing.T) { 240 src := newMetricTable(20, start) 241 dest := newMetricTable(20, end) 242 dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced) 243 dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 244 src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 245 src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced) 246 247 src.failedHarvests = failedMetricAttemptsLimit 248 249 dest.mergeFailed(src) 250 251 ExpectMetrics(t, dest, []WantMetric{ 252 {"one", "", false, []float64{1, 2, 1, 2, 2, 4}}, 253 {"two", "", false, []float64{1, 2, 1, 2, 2, 4}}, 254 }) 255 } 256 257 func BenchmarkMetricTableCollectorJSON(b *testing.B) { 258 mt := newMetricTable(2000, time.Now()) 259 md := metricData{ 260 countSatisfied: 1234567812345678.1234567812345678, 261 totalTolerated: 1234567812345678.1234567812345678, 262 exclusiveFailed: 1234567812345678.1234567812345678, 263 min: 1234567812345678.1234567812345678, 264 max: 1234567812345678.1234567812345678, 265 sumSquares: 1234567812345678.1234567812345678, 266 } 267 268 for i := 0; i < 20; i++ { 269 scope := fmt.Sprintf("WebTransaction/Uri/myblog2/%d", i) 270 271 for j := 0; j < 20; j++ { 272 name := fmt.Sprintf("Datastore/statement/MySQL/City%d/insert", j) 273 mt.add(name, "", md, forced) 274 mt.add(name, scope, md, forced) 275 276 name = fmt.Sprintf("WebTransaction/Uri/myblog2/newPost_rum_%d.php", j) 277 mt.add(name, "", md, forced) 278 mt.add(name, scope, md, forced) 279 } 280 } 281 282 data, err := mt.CollectorJSON("12345", time.Now()) 283 if nil != err { 284 b.Fatal(err) 285 } 286 if err := isValidJSON(data); nil != err { 287 b.Fatal(err, string(data)) 288 } 289 290 b.ResetTimer() 291 b.ReportAllocs() 292 293 id := "12345" 294 now := time.Now() 295 for i := 0; i < b.N; i++ { 296 mt.CollectorJSON(id, now) 297 } 298 } 299 300 func BenchmarkAddingSameMetrics(b *testing.B) { 301 name := "my_name" 302 scope := "my_scope" 303 duration := 2 * time.Second 304 exclusive := 1 * time.Second 305 306 mt := newMetricTable(2000, time.Now()) 307 308 b.ResetTimer() 309 b.ReportAllocs() 310 311 for i := 0; i < b.N; i++ { 312 mt.addDuration(name, scope, duration, exclusive, forced) 313 mt.addSingleCount(name, forced) 314 } 315 } 316 317 func TestMergedMetricsAreCopied(t *testing.T) { 318 src := newMetricTable(20, start) 319 dest := newMetricTable(20, start) 320 321 src.addSingleCount("zip", unforced) 322 dest.merge(src, "") 323 src.addSingleCount("zip", unforced) 324 ExpectMetrics(t, dest, []WantMetric{ 325 {"zip", "", false, []float64{1, 0, 0, 0, 0, 0}}, 326 }) 327 } 328 329 func TestMergedWithScope(t *testing.T) { 330 src := newMetricTable(20, start) 331 dest := newMetricTable(20, start) 332 333 src.addSingleCount("one", unforced) 334 src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced) 335 dest.addDuration("two", "my_scope", 2*time.Second, 1*time.Second, unforced) 336 dest.merge(src, "my_scope") 337 338 ExpectMetrics(t, dest, []WantMetric{ 339 {"one", "my_scope", false, []float64{1, 0, 0, 0, 0, 0}}, 340 {"two", "my_scope", false, []float64{2, 4, 2, 2, 2, 8}}, 341 }) 342 }