vitess.io/vitess@v0.16.2/go/vt/servenv/exporter_test.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package servenv 18 19 import ( 20 "expvar" 21 "fmt" 22 "io" 23 "net" 24 "net/http" 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/assert" 29 30 "vitess.io/vitess/go/stats" 31 ) 32 33 func TestURLPrefix(t *testing.T) { 34 assert.Equal(t, "", NewExporter("", "").URLPrefix()) 35 assert.Equal(t, "/a", NewExporter("a", "").URLPrefix()) 36 } 37 38 func TestHandleFunc(t *testing.T) { 39 // Listen on a random port 40 listener, err := net.Listen("tcp", "127.0.0.1:0") 41 if err != nil { 42 t.Fatalf("Cannot listen: %v", err) 43 } 44 defer listener.Close() 45 port := listener.Addr().(*net.TCPAddr).Port 46 go http.Serve(listener, nil) 47 48 ebd := NewExporter("", "") 49 ebd.HandleFunc("/path", func(w http.ResponseWriter, r *http.Request) { 50 w.Write([]byte("1")) 51 }) 52 assert.Equal(t, "1", httpGet(t, fmt.Sprintf("http://localhost:%d/path", port))) 53 assert.Contains(t, httpGet(t, fmt.Sprintf("http://localhost:%d/debug/status", port)), "Status for") 54 55 ebd = NewExporter("a", "") 56 ebd.HandleFunc("/path", func(w http.ResponseWriter, r *http.Request) { 57 w.Write([]byte("2")) 58 }) 59 assert.Equal(t, "2", httpGet(t, fmt.Sprintf("http://localhost:%d/a/path", port))) 60 assert.Contains(t, httpGet(t, fmt.Sprintf("http://localhost:%d/debug/status", port)), "Status for") 61 62 ebd.HandleFunc("/path", func(w http.ResponseWriter, r *http.Request) { 63 w.Write([]byte("3")) 64 }) 65 assert.Equal(t, "3", httpGet(t, fmt.Sprintf("http://localhost:%d/a/path", port))) 66 assert.Contains(t, httpGet(t, fmt.Sprintf("http://localhost:%d/a/debug/status", port)), "Status for") 67 68 ebd = NewExporter("a", "") 69 ebd.HandleFunc("/path", func(w http.ResponseWriter, r *http.Request) { 70 w.Write([]byte("4")) 71 }) 72 assert.Equal(t, "4", httpGet(t, fmt.Sprintf("http://localhost:%d/a/path", port))) 73 74 ebd = NewExporter("b", "") 75 ebd.HandleFunc("/path", func(w http.ResponseWriter, r *http.Request) { 76 w.Write([]byte("5")) 77 }) 78 assert.Equal(t, "5", httpGet(t, fmt.Sprintf("http://localhost:%d/b/path", port))) 79 assert.Contains(t, httpGet(t, fmt.Sprintf("http://localhost:%d/b/debug/status", port)), "Status for") 80 // Ensure "a" is still the same. 81 assert.Equal(t, "4", httpGet(t, fmt.Sprintf("http://localhost:%d/a/path", port))) 82 assert.Contains(t, httpGet(t, fmt.Sprintf("http://localhost:%d/a/debug/status", port)), "Status for") 83 } 84 85 func httpGet(t *testing.T, url string) string { 86 t.Helper() 87 88 resp, err := http.Get(url) 89 if err != nil { 90 t.Fatal(err) 91 } 92 defer resp.Body.Close() 93 94 body, err := io.ReadAll(resp.Body) 95 if err != nil { 96 t.Fatal(err) 97 } 98 return string(body) 99 } 100 101 func TestCountersFuncWithMultiLabels(t *testing.T) { 102 ebd := NewExporter("", "") 103 ebd.NewCountersFuncWithMultiLabels("gcfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 1} }) 104 assert.Equal(t, `{"a": 1}`, expvar.Get("gcfwml").String()) 105 106 ebd = NewExporter("i1", "label") 107 108 // Ensure anonymous vars don't cause panics. 109 ebd.NewCountersFuncWithMultiLabels("", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 2} }) 110 ebd.NewCountersFuncWithMultiLabels("", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 3} }) 111 112 // Ensure reuse of global var is ignored. 113 ebd.NewCountersFuncWithMultiLabels("gcfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 2} }) 114 assert.Equal(t, `{"a": 1}`, expvar.Get("gcfwml").String()) 115 116 ebd.NewCountersFuncWithMultiLabels("lcfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 4} }) 117 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lcfwml").String()) 118 119 // Ensure var gets replaced. 120 ebd.NewCountersFuncWithMultiLabels("lcfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 5} }) 121 assert.Equal(t, `{"i1.a": 5}`, expvar.Get("lcfwml").String()) 122 123 ebd = NewExporter("i2", "label") 124 ebd.NewCountersFuncWithMultiLabels("lcfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 6} }) 125 assert.Contains(t, expvar.Get("lcfwml").String(), `"i1.a": 5`) 126 assert.Contains(t, expvar.Get("lcfwml").String(), `"i2.a": 6`) 127 } 128 129 func TestGaugesFuncWithMultiLabels(t *testing.T) { 130 ebd := NewExporter("", "") 131 ebd.NewGaugesFuncWithMultiLabels("ggfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 1} }) 132 assert.Equal(t, `{"a": 1}`, expvar.Get("ggfwml").String()) 133 134 ebd = NewExporter("i1", "label") 135 136 // Ensure anonymous vars don't cause panics. 137 ebd.NewGaugesFuncWithMultiLabels("", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 2} }) 138 ebd.NewGaugesFuncWithMultiLabels("", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 3} }) 139 140 // Ensure reuse of global var is ignored. 141 ebd.NewGaugesFuncWithMultiLabels("ggfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 1} }) 142 assert.Equal(t, `{"a": 1}`, expvar.Get("ggfwml").String()) 143 144 ebd.NewGaugesFuncWithMultiLabels("lgfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 4} }) 145 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lgfwml").String()) 146 147 // Ensure var gets replaced. 148 ebd.NewGaugesFuncWithMultiLabels("lgfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 5} }) 149 assert.Equal(t, `{"i1.a": 5}`, expvar.Get("lgfwml").String()) 150 151 ebd = NewExporter("i2", "label") 152 ebd.NewGaugesFuncWithMultiLabels("lgfwml", "", []string{"l"}, func() map[string]int64 { return map[string]int64{"a": 6} }) 153 assert.Contains(t, expvar.Get("lgfwml").String(), `"i1.a": 5`) 154 assert.Contains(t, expvar.Get("lgfwml").String(), `"i2.a": 6`) 155 } 156 157 func TestCounter(t *testing.T) { 158 ebd := NewExporter("", "") 159 c := ebd.NewCounter("gcounter", "") 160 c.Add(1) 161 assert.Equal(t, "1", expvar.Get("gcounter").String()) 162 163 ebd = NewExporter("i1", "label") 164 165 // Ensure anonymous vars don't cause panics. 166 ebd.NewCounter("", "") 167 ebd.NewCounter("", "") 168 169 // Ensure global var gets reused. 170 c = ebd.NewCounter("gcounter", "") 171 c.Add(1) 172 assert.Equal(t, "2", expvar.Get("gcounter").String()) 173 174 c = ebd.NewCounter("lcounter", "") 175 c.Add(4) 176 assert.Equal(t, `{"i1": 4}`, expvar.Get("lcounter").String()) 177 178 // Ensure var gets reused. 179 c = ebd.NewCounter("lcounter", "") 180 c.Add(5) 181 assert.Equal(t, `{"i1": 9}`, expvar.Get("lcounter").String()) 182 183 ebd = NewExporter("i2", "label") 184 c = ebd.NewCounter("lcounter", "") 185 c.Add(6) 186 assert.Contains(t, expvar.Get("lcounter").String(), `"i1": 9`) 187 assert.Contains(t, expvar.Get("lcounter").String(), `"i2": 6`) 188 } 189 190 func TestGauge(t *testing.T) { 191 ebd := NewExporter("", "") 192 c := ebd.NewGauge("ggauge", "") 193 c.Set(1) 194 assert.Equal(t, "1", expvar.Get("ggauge").String()) 195 196 ebd = NewExporter("i1", "label") 197 198 // Ensure anonymous vars don't cause panics. 199 ebd.NewGauge("", "") 200 ebd.NewGauge("", "") 201 202 // Ensure global var gets reused. 203 c = ebd.NewGauge("ggauge", "") 204 c.Set(2) 205 assert.Equal(t, "2", expvar.Get("ggauge").String()) 206 207 c = ebd.NewGauge("lgauge", "") 208 c.Set(4) 209 assert.Equal(t, `{"i1": 4}`, expvar.Get("lgauge").String()) 210 211 // Ensure var gets reused. 212 c = ebd.NewGauge("lgauge", "") 213 assert.Equal(t, `{"i1": 4}`, expvar.Get("lgauge").String()) 214 c.Set(5) 215 assert.Equal(t, `{"i1": 5}`, expvar.Get("lgauge").String()) 216 217 ebd = NewExporter("i2", "label") 218 c = ebd.NewGauge("lgauge", "") 219 c.Set(6) 220 assert.Contains(t, expvar.Get("lgauge").String(), `"i1": 5`) 221 assert.Contains(t, expvar.Get("lgauge").String(), `"i2": 6`) 222 } 223 224 func TestCounterFunc(t *testing.T) { 225 ebd := NewExporter("", "") 226 ebd.NewCounterFunc("gcf", "", func() int64 { return 1 }) 227 assert.Equal(t, "1", expvar.Get("gcf").String()) 228 229 ebd = NewExporter("i1", "label") 230 231 // Ensure anonymous vars don't cause panics. 232 ebd.NewCounterFunc("", "", func() int64 { return 2 }) 233 ebd.NewCounterFunc("", "", func() int64 { return 3 }) 234 235 // Ensure reuse of global var is ignored. 236 ebd.NewCounterFunc("gcf", "", func() int64 { return 2 }) 237 assert.Equal(t, "1", expvar.Get("gcf").String()) 238 239 ebd.NewCounterFunc("lcf", "", func() int64 { return 4 }) 240 assert.Equal(t, `{"i1": 4}`, expvar.Get("lcf").String()) 241 242 // Ensure var gets replaced. 243 ebd.NewCounterFunc("lcf", "", func() int64 { return 5 }) 244 assert.Equal(t, `{"i1": 5}`, expvar.Get("lcf").String()) 245 246 ebd = NewExporter("i2", "label") 247 ebd.NewCounterFunc("lcf", "", func() int64 { return 6 }) 248 assert.Contains(t, expvar.Get("lcf").String(), `"i1": 5`) 249 assert.Contains(t, expvar.Get("lcf").String(), `"i2": 6`) 250 } 251 252 func TestGaugeFunc(t *testing.T) { 253 ebd := NewExporter("", "") 254 ebd.NewGaugeFunc("ggf", "", func() int64 { return 1 }) 255 assert.Equal(t, "1", expvar.Get("ggf").String()) 256 257 ebd = NewExporter("i1", "label") 258 259 // Ensure anonymous vars don't cause panics. 260 ebd.NewGaugeFunc("", "", func() int64 { return 2 }) 261 ebd.NewGaugeFunc("", "", func() int64 { return 3 }) 262 263 // Ensure reuse of global var is ignored. 264 ebd.NewGaugeFunc("ggf", "", func() int64 { return 2 }) 265 assert.Equal(t, "1", expvar.Get("ggf").String()) 266 267 ebd.NewGaugeFunc("lgf", "", func() int64 { return 4 }) 268 assert.Equal(t, `{"i1": 4}`, expvar.Get("lgf").String()) 269 270 // Ensure var gets replaced. 271 ebd.NewGaugeFunc("lgf", "", func() int64 { return 5 }) 272 assert.Equal(t, `{"i1": 5}`, expvar.Get("lgf").String()) 273 274 ebd = NewExporter("i2", "label") 275 ebd.NewGaugeFunc("lgf", "", func() int64 { return 6 }) 276 assert.Contains(t, expvar.Get("lgf").String(), `"i1": 5`) 277 assert.Contains(t, expvar.Get("lgf").String(), `"i2": 6`) 278 } 279 280 func TestCounterDurationFunc(t *testing.T) { 281 ebd := NewExporter("", "") 282 ebd.NewCounterDurationFunc("gcduration", "", func() time.Duration { return 1 }) 283 assert.Equal(t, "1", expvar.Get("gcduration").String()) 284 285 ebd = NewExporter("i1", "label") 286 287 // Ensure anonymous vars don't cause panics. 288 ebd.NewCounterDurationFunc("", "", func() time.Duration { return 2 }) 289 ebd.NewCounterDurationFunc("", "", func() time.Duration { return 3 }) 290 291 // Ensure reuse of global var is ignored. 292 ebd.NewCounterDurationFunc("gcduration", "", func() time.Duration { return 2 }) 293 assert.Equal(t, "1", expvar.Get("gcduration").String()) 294 295 ebd.NewCounterDurationFunc("lcduration", "", func() time.Duration { return 4 }) 296 assert.Equal(t, `{"i1": 4}`, expvar.Get("lcduration").String()) 297 298 // Ensure var gets replaced. 299 ebd.NewCounterDurationFunc("lcduration", "", func() time.Duration { return 5 }) 300 assert.Equal(t, `{"i1": 5}`, expvar.Get("lcduration").String()) 301 302 ebd = NewExporter("i2", "label") 303 ebd.NewCounterDurationFunc("lcduration", "", func() time.Duration { return 6 }) 304 assert.Contains(t, expvar.Get("lcduration").String(), `"i1": 5`) 305 assert.Contains(t, expvar.Get("lcduration").String(), `"i2": 6`) 306 } 307 308 func TestGaugeDurationFunc(t *testing.T) { 309 ebd := NewExporter("", "") 310 ebd.NewGaugeDurationFunc("ggduration", "", func() time.Duration { return 1 }) 311 assert.Equal(t, "1", expvar.Get("ggduration").String()) 312 313 ebd = NewExporter("i1", "label") 314 315 // Ensure anonymous vars don't cause panics. 316 ebd.NewGaugeDurationFunc("", "", func() time.Duration { return 2 }) 317 ebd.NewGaugeDurationFunc("", "", func() time.Duration { return 3 }) 318 319 // Ensure reuse of global var is ignored. 320 ebd.NewGaugeDurationFunc("ggduration", "", func() time.Duration { return 2 }) 321 assert.Equal(t, "1", expvar.Get("ggduration").String()) 322 323 ebd.NewGaugeDurationFunc("lgduration", "", func() time.Duration { return 4 }) 324 assert.Equal(t, `{"i1": 4}`, expvar.Get("lgduration").String()) 325 326 // Ensure var gets replaced. 327 ebd.NewGaugeDurationFunc("lgduration", "", func() time.Duration { return 5 }) 328 assert.Equal(t, `{"i1": 5}`, expvar.Get("lgduration").String()) 329 330 ebd = NewExporter("i2", "label") 331 ebd.NewGaugeDurationFunc("lgduration", "", func() time.Duration { return 6 }) 332 assert.Contains(t, expvar.Get("lgduration").String(), `"i1": 5`) 333 assert.Contains(t, expvar.Get("lgduration").String(), `"i2": 6`) 334 } 335 336 func TestCountersWithSingleLabel(t *testing.T) { 337 ebd := NewExporter("", "") 338 g := ebd.NewCountersWithSingleLabel("gcwsl", "", "l") 339 g.Add("a", 1) 340 assert.Equal(t, `{"a": 1}`, expvar.Get("gcwsl").String()) 341 342 ebd = NewExporter("i1", "label") 343 344 // Ensure anonymous vars don't cause panics. 345 ebd.NewCountersWithSingleLabel("", "", "l") 346 ebd.NewCountersWithSingleLabel("", "", "l") 347 348 // Ensure global var gets reused. 349 g = ebd.NewCountersWithSingleLabel("gcwsl", "", "l") 350 g.Add("a", 1) 351 assert.Equal(t, `{"a": 2}`, expvar.Get("gcwsl").String()) 352 353 g = ebd.NewCountersWithSingleLabel("lcwsl", "", "l") 354 g.Add("a", 4) 355 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lcwsl").String()) 356 357 // Ensure var gets reused. 358 g = ebd.NewCountersWithSingleLabel("lcwsl", "", "l") 359 g.Add("a", 5) 360 assert.Equal(t, `{"i1.a": 9}`, expvar.Get("lcwsl").String()) 361 362 ebd = NewExporter("i2", "label") 363 g = ebd.NewCountersWithSingleLabel("lcwsl", "", "l") 364 g.Add("a", 6) 365 assert.Contains(t, expvar.Get("lcwsl").String(), `"i1.a": 9`) 366 assert.Contains(t, expvar.Get("lcwsl").String(), `"i2.a": 6`) 367 } 368 369 func TestGaugesWithSingleLabel(t *testing.T) { 370 ebd := NewExporter("", "") 371 g := ebd.NewGaugesWithSingleLabel("ggwsl", "", "l") 372 g.Set("a", 1) 373 assert.Equal(t, `{"a": 1}`, expvar.Get("ggwsl").String()) 374 375 ebd = NewExporter("i1", "label") 376 377 // Ensure anonymous vars don't cause panics. 378 ebd.NewGaugesWithSingleLabel("", "", "l") 379 ebd.NewGaugesWithSingleLabel("", "", "l") 380 381 // Ensure reuse of global var is ignored. 382 g = ebd.NewGaugesWithSingleLabel("ggwsl", "", "l") 383 g.Set("a", 2) 384 assert.Equal(t, `{"a": 1}`, expvar.Get("ggwsl").String()) 385 386 g = ebd.NewGaugesWithSingleLabel("lgwsl", "", "l") 387 g.Set("a", 4) 388 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lgwsl").String()) 389 390 // Ensure var gets reused. 391 g = ebd.NewGaugesWithSingleLabel("lgwsl", "", "l") 392 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lgwsl").String()) 393 g.Set("a", 5) 394 assert.Equal(t, `{"i1.a": 5}`, expvar.Get("lgwsl").String()) 395 396 ebd = NewExporter("i2", "label") 397 g = ebd.NewGaugesWithSingleLabel("lgwsl", "", "l") 398 g.Set("a", 6) 399 assert.Contains(t, expvar.Get("lgwsl").String(), `"i1.a": 5`) 400 assert.Contains(t, expvar.Get("lgwsl").String(), `"i2.a": 6`) 401 } 402 403 func TestCountersWithMultiLabels(t *testing.T) { 404 ebd := NewExporter("", "") 405 g := ebd.NewCountersWithMultiLabels("gcwml", "", []string{"l"}) 406 g.Add([]string{"a"}, 1) 407 assert.Equal(t, `{"a": 1}`, expvar.Get("gcwml").String()) 408 409 ebd = NewExporter("i1", "label") 410 411 // Ensure anonymous vars don't cause panics. 412 ebd.NewCountersWithMultiLabels("", "", []string{"l"}) 413 ebd.NewCountersWithMultiLabels("", "", []string{"l"}) 414 415 // Ensure global var gets reused. 416 g = ebd.NewCountersWithMultiLabels("gcwml", "", []string{"l"}) 417 g.Add([]string{"a"}, 1) 418 assert.Equal(t, `{"a": 2}`, expvar.Get("gcwml").String()) 419 420 g = ebd.NewCountersWithMultiLabels("lcwml", "", []string{"l"}) 421 g.Add([]string{"a"}, 4) 422 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lcwml").String()) 423 424 // Ensure var gets reused. 425 g = ebd.NewCountersWithMultiLabels("lcwml", "", []string{"l"}) 426 g.Add([]string{"a"}, 5) 427 assert.Equal(t, `{"i1.a": 9}`, expvar.Get("lcwml").String()) 428 429 ebd = NewExporter("i2", "label") 430 g = ebd.NewCountersWithMultiLabels("lcwml", "", []string{"l"}) 431 g.Add([]string{"a"}, 6) 432 assert.Contains(t, expvar.Get("lcwml").String(), `"i1.a": 9`) 433 assert.Contains(t, expvar.Get("lcwml").String(), `"i2.a": 6`) 434 } 435 436 func TestGaugesWithMultiLabels(t *testing.T) { 437 ebd := NewExporter("", "") 438 g := ebd.NewGaugesWithMultiLabels("ggwml", "", []string{"l"}) 439 g.Set([]string{"a"}, 1) 440 assert.Equal(t, `{"a": 1}`, expvar.Get("ggwml").String()) 441 442 ebd = NewExporter("i1", "label") 443 444 // Ensure anonymous vars don't cause panics. 445 ebd.NewGaugesWithMultiLabels("", "", []string{"l"}) 446 ebd.NewGaugesWithMultiLabels("", "", []string{"l"}) 447 448 // Ensure reuse of global var is ignored. 449 g = ebd.NewGaugesWithMultiLabels("ggwml", "", []string{"l"}) 450 g.Set([]string{"a"}, 2) 451 assert.Equal(t, `{"a": 1}`, expvar.Get("ggwml").String()) 452 453 g = ebd.NewGaugesWithMultiLabels("lgwml", "", []string{"l"}) 454 g.Set([]string{"a"}, 4) 455 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lgwml").String()) 456 457 // Ensure var gets reused. 458 g = ebd.NewGaugesWithMultiLabels("lgwml", "", []string{"l"}) 459 assert.Equal(t, `{"i1.a": 4}`, expvar.Get("lgwml").String()) 460 g.Set([]string{"a"}, 5) 461 assert.Equal(t, `{"i1.a": 5}`, expvar.Get("lgwml").String()) 462 463 ebd = NewExporter("i2", "label") 464 g = ebd.NewGaugesWithMultiLabels("lgwml", "", []string{"l"}) 465 g.Set([]string{"a"}, 6) 466 assert.Contains(t, expvar.Get("lgwml").String(), `"i1.a": 5`) 467 assert.Contains(t, expvar.Get("lgwml").String(), `"i2.a": 6`) 468 } 469 470 func TestTimings(t *testing.T) { 471 ebd := NewExporter("", "") 472 g := ebd.NewTimings("gtimings", "", "l") 473 g.Add("a", 1) 474 assert.Contains(t, expvar.Get("gtimings").String(), `"TotalCount":1`) 475 g.Record("a", time.Now()) 476 assert.Contains(t, expvar.Get("gtimings").String(), `"TotalCount":2`) 477 478 ebd = NewExporter("i1", "label") 479 480 // Ensure anonymous vars don't cause panics. 481 ebd.NewTimings("", "", "l") 482 ebd.NewTimings("", "", "l") 483 484 // Ensure global var gets reused. 485 g = ebd.NewTimings("gtimings", "", "l") 486 g.Add("a", 1) 487 assert.Contains(t, expvar.Get("gtimings").String(), `"TotalCount":3`) 488 489 g = ebd.NewTimings("ltimings", "", "l") 490 g.Add("a", 1) 491 g.Add("a", 1) 492 assert.Contains(t, expvar.Get("ltimings").String(), `i1.a`) 493 assert.Contains(t, expvar.Get("ltimings").String(), `"TotalCount":2`) 494 495 // Ensure var gets reused. 496 g = ebd.NewTimings("ltimings", "", "l") 497 g.Add("a", 1) 498 assert.Contains(t, expvar.Get("ltimings").String(), `i1.a`) 499 assert.Contains(t, expvar.Get("ltimings").String(), `"TotalCount":3`) 500 g.Record("a", time.Now()) 501 assert.Contains(t, expvar.Get("ltimings").String(), `"TotalCount":4`) 502 503 ebd = NewExporter("i2", "label") 504 g = ebd.NewTimings("ltimings", "", "l") 505 g.Add("a", 1) 506 assert.Contains(t, expvar.Get("ltimings").String(), `i1.a`) 507 assert.Contains(t, expvar.Get("ltimings").String(), `i2.a`) 508 assert.Contains(t, expvar.Get("ltimings").String(), `"TotalCount":5`) 509 510 want := map[string]int64{ 511 "All": 5, 512 "i1.a": 4, 513 "i2.a": 1, 514 } 515 assert.Equal(t, want, g.Counts()) 516 } 517 518 func TestMultiTimings(t *testing.T) { 519 ebd := NewExporter("", "") 520 g := ebd.NewMultiTimings("gmtimings", "", []string{"l"}) 521 g.Add([]string{"a"}, 1) 522 assert.Contains(t, expvar.Get("gmtimings").String(), `"TotalCount":1`) 523 g.Record([]string{"a"}, time.Now()) 524 assert.Contains(t, expvar.Get("gmtimings").String(), `"TotalCount":2`) 525 526 ebd = NewExporter("i1", "label") 527 528 // Ensure anonymous vars don't cause panics. 529 ebd.NewMultiTimings("", "", []string{"l"}) 530 ebd.NewMultiTimings("", "", []string{"l"}) 531 532 // Ensure global var gets reused. 533 g = ebd.NewMultiTimings("gmtimings", "", []string{"l"}) 534 g.Add([]string{"a"}, 1) 535 assert.Contains(t, expvar.Get("gmtimings").String(), `"TotalCount":3`) 536 537 g = ebd.NewMultiTimings("lmtimings", "", []string{"l"}) 538 g.Add([]string{"a"}, 1) 539 g.Add([]string{"a"}, 1) 540 assert.Contains(t, expvar.Get("lmtimings").String(), `i1.a`) 541 assert.Contains(t, expvar.Get("lmtimings").String(), `"TotalCount":2`) 542 g.Record([]string{"a"}, time.Now()) 543 assert.Contains(t, expvar.Get("lmtimings").String(), `"TotalCount":3`) 544 545 // Ensure var gets reused. 546 g = ebd.NewMultiTimings("lmtimings", "", []string{"l"}) 547 g.Add([]string{"a"}, 1) 548 assert.Contains(t, expvar.Get("lmtimings").String(), `i1.a`) 549 assert.Contains(t, expvar.Get("lmtimings").String(), `"TotalCount":4`) 550 551 ebd = NewExporter("i2", "label") 552 g = ebd.NewMultiTimings("lmtimings", "", []string{"l"}) 553 g.Add([]string{"a"}, 1) 554 assert.Contains(t, expvar.Get("lmtimings").String(), `i1.a`) 555 assert.Contains(t, expvar.Get("lmtimings").String(), `i2.a`) 556 assert.Contains(t, expvar.Get("lmtimings").String(), `"TotalCount":5`) 557 558 want := map[string]int64{ 559 "All": 5, 560 "i1.a": 4, 561 "i2.a": 1, 562 } 563 assert.Equal(t, want, g.Counts()) 564 } 565 566 func TestRates(t *testing.T) { 567 ebd := NewExporter("", "") 568 tm := ebd.NewMultiTimings("gratetimings", "", []string{"l"}) 569 ebd.NewRates("grates", tm, 15*60/5, 5*time.Second) 570 assert.Equal(t, "{}", expvar.Get("grates").String()) 571 572 ebd = NewExporter("i1", "label") 573 574 // Ensure anonymous vars don't cause panics. 575 ebd.NewRates("", tm, 15*60/5, 5*time.Second) 576 ebd.NewRates("", tm, 15*60/5, 5*time.Second) 577 578 // Ensure global var gets reused. 579 ebd.NewRates("grates", tm, 15*60/5, 5*time.Second) 580 assert.Equal(t, "{}", expvar.Get("grates").String()) 581 582 // Ensure var gets reused. 583 rates1 := ebd.NewRates("lrates", tm, 15*60/5, 5*time.Second) 584 rates2 := ebd.NewRates("lrates", tm, 15*60/5, 5*time.Second) 585 assert.True(t, rates2 == rates1) 586 587 ebd = NewExporter("i2", "label") 588 rates3 := ebd.NewRates("lrates", tm, 15*60/5, 5*time.Second) 589 assert.True(t, rates3 != rates1) 590 } 591 592 func TestHistogram(t *testing.T) { 593 ebd := NewExporter("", "") 594 g := ebd.NewHistogram("ghistogram", "", []int64{10}) 595 g.Add(1) 596 assert.Contains(t, expvar.Get("ghistogram").String(), `{"10": 1, "inf": 0, "Count": 1, "Total": 1}`) 597 598 ebd = NewExporter("i1", "label") 599 600 // Ensure anonymous vars don't cause panics. 601 ebd.NewHistogram("", "", []int64{10}) 602 ebd.NewHistogram("", "", []int64{10}) 603 604 // Ensure reuse of global var doesn't panic. 605 _ = ebd.NewHistogram("ghistogram", "", []int64{10}) 606 607 g = ebd.NewHistogram("lhistogram", "", []int64{10}) 608 g.Add(1) 609 g.Add(1) 610 assert.Contains(t, expvar.Get("lmtimings").String(), `i1`) 611 assert.Contains(t, expvar.Get("lhistogram").String(), `{"10": 2, "inf": 0, "Count": 2, "Total": 2}`) 612 613 // Ensure var gets replaced. 614 g = ebd.NewHistogram("lhistogram", "", []int64{10}) 615 g.Add(1) 616 assert.Contains(t, expvar.Get("lmtimings").String(), `i1`) 617 assert.Contains(t, expvar.Get("lhistogram").String(), `{"10": 1, "inf": 0, "Count": 1, "Total": 1}`) 618 } 619 620 func TestPublish(t *testing.T) { 621 ebd := NewExporter("", "") 622 s := stats.NewString("") 623 ebd.Publish("gpub", s) 624 s.Set("1") 625 assert.Equal(t, `"1"`, expvar.Get("gpub").String()) 626 627 ebd = NewExporter("i1", "label") 628 ebd.Publish("lpub", s) 629 assert.Equal(t, `{"i1": "1"}`, expvar.Get("lpub").String()) 630 631 // Ensure reuse of global var doesn't panic. 632 ebd.Publish("gpub", s) 633 634 ebd = NewExporter("i2", "label") 635 ebd.Publish("lpub", s) 636 assert.Contains(t, expvar.Get("lpub").String(), `"i1": "1"`) 637 assert.Contains(t, expvar.Get("lpub").String(), `"i2": "1"`) 638 }