github.com/rcrowley/go-metrics@v0.0.0-20201227073835-cf1acfcdf475/registry_test.go (about) 1 package metrics 2 3 import ( 4 "fmt" 5 "sync" 6 "testing" 7 ) 8 9 func BenchmarkRegistry(b *testing.B) { 10 r := NewRegistry() 11 r.Register("foo", NewCounter()) 12 b.ResetTimer() 13 for i := 0; i < b.N; i++ { 14 r.Each(func(string, interface{}) {}) 15 } 16 } 17 18 func BenchmarkHugeRegistry(b *testing.B) { 19 r := NewRegistry() 20 for i := 0; i < 10000; i++ { 21 r.Register(fmt.Sprintf("foo%07d", i), NewCounter()) 22 } 23 v := make([]string, 10000) 24 b.ResetTimer() 25 for i := 0; i < b.N; i++ { 26 v := v[:0] 27 r.Each(func(k string, _ interface{}) { 28 v = append(v, k) 29 }) 30 } 31 } 32 33 func BenchmarkRegistryParallel(b *testing.B) { 34 r := NewRegistry() 35 b.ResetTimer() 36 b.RunParallel(func(pb *testing.PB) { 37 for pb.Next() { 38 r.GetOrRegister("foo", NewCounter()) 39 } 40 }) 41 } 42 43 func TestRegistry(t *testing.T) { 44 r := NewRegistry() 45 r.Register("foo", NewCounter()) 46 i := 0 47 r.Each(func(name string, iface interface{}) { 48 i++ 49 if "foo" != name { 50 t.Fatal(name) 51 } 52 if _, ok := iface.(Counter); !ok { 53 t.Fatal(iface) 54 } 55 }) 56 if 1 != i { 57 t.Fatal(i) 58 } 59 r.Unregister("foo") 60 i = 0 61 r.Each(func(string, interface{}) { i++ }) 62 if 0 != i { 63 t.Fatal(i) 64 } 65 } 66 67 func TestRegistryDuplicate(t *testing.T) { 68 r := NewRegistry() 69 if err := r.Register("foo", NewCounter()); nil != err { 70 t.Fatal(err) 71 } 72 if err := r.Register("foo", NewGauge()); nil == err { 73 t.Fatal(err) 74 } 75 i := 0 76 r.Each(func(name string, iface interface{}) { 77 i++ 78 if _, ok := iface.(Counter); !ok { 79 t.Fatal(iface) 80 } 81 }) 82 if 1 != i { 83 t.Fatal(i) 84 } 85 } 86 87 func TestRegistryGet(t *testing.T) { 88 r := NewRegistry() 89 r.Register("foo", NewCounter()) 90 if count := r.Get("foo").(Counter).Count(); 0 != count { 91 t.Fatal(count) 92 } 93 r.Get("foo").(Counter).Inc(1) 94 if count := r.Get("foo").(Counter).Count(); 1 != count { 95 t.Fatal(count) 96 } 97 } 98 99 func TestRegistryGetOrRegister(t *testing.T) { 100 r := NewRegistry() 101 102 // First metric wins with GetOrRegister 103 _ = r.GetOrRegister("foo", NewCounter()) 104 m := r.GetOrRegister("foo", NewGauge()) 105 if _, ok := m.(Counter); !ok { 106 t.Fatal(m) 107 } 108 109 i := 0 110 r.Each(func(name string, iface interface{}) { 111 i++ 112 if name != "foo" { 113 t.Fatal(name) 114 } 115 if _, ok := iface.(Counter); !ok { 116 t.Fatal(iface) 117 } 118 }) 119 if i != 1 { 120 t.Fatal(i) 121 } 122 } 123 124 func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) { 125 r := NewRegistry() 126 127 // First metric wins with GetOrRegister 128 _ = r.GetOrRegister("foo", NewCounter) 129 m := r.GetOrRegister("foo", NewGauge) 130 if _, ok := m.(Counter); !ok { 131 t.Fatal(m) 132 } 133 134 i := 0 135 r.Each(func(name string, iface interface{}) { 136 i++ 137 if name != "foo" { 138 t.Fatal(name) 139 } 140 if _, ok := iface.(Counter); !ok { 141 t.Fatal(iface) 142 } 143 }) 144 if i != 1 { 145 t.Fatal(i) 146 } 147 } 148 149 func TestRegistryUnregister(t *testing.T) { 150 l := len(arbiter.meters) 151 r := NewRegistry() 152 r.Register("foo", NewCounter()) 153 r.Register("bar", NewMeter()) 154 r.Register("baz", NewTimer()) 155 if len(arbiter.meters) != l+2 { 156 t.Errorf("arbiter.meters: %d != %d\n", l+2, len(arbiter.meters)) 157 } 158 r.Unregister("foo") 159 r.Unregister("bar") 160 r.Unregister("baz") 161 if len(arbiter.meters) != l { 162 t.Errorf("arbiter.meters: %d != %d\n", l+2, len(arbiter.meters)) 163 } 164 } 165 166 func TestPrefixedChildRegistryGetOrRegister(t *testing.T) { 167 r := NewRegistry() 168 pr := NewPrefixedChildRegistry(r, "prefix.") 169 170 _ = pr.GetOrRegister("foo", NewCounter()) 171 172 i := 0 173 r.Each(func(name string, m interface{}) { 174 i++ 175 if name != "prefix.foo" { 176 t.Fatal(name) 177 } 178 }) 179 if i != 1 { 180 t.Fatal(i) 181 } 182 } 183 184 func TestPrefixedRegistryGetOrRegister(t *testing.T) { 185 r := NewPrefixedRegistry("prefix.") 186 187 _ = r.GetOrRegister("foo", NewCounter()) 188 189 i := 0 190 r.Each(func(name string, m interface{}) { 191 i++ 192 if name != "prefix.foo" { 193 t.Fatal(name) 194 } 195 }) 196 if i != 1 { 197 t.Fatal(i) 198 } 199 } 200 201 func TestPrefixedRegistryRegister(t *testing.T) { 202 r := NewPrefixedRegistry("prefix.") 203 err := r.Register("foo", NewCounter()) 204 c := NewCounter() 205 Register("bar", c) 206 if err != nil { 207 t.Fatal(err.Error()) 208 } 209 210 i := 0 211 r.Each(func(name string, m interface{}) { 212 i++ 213 if name != "prefix.foo" { 214 t.Fatal(name) 215 } 216 }) 217 if i != 1 { 218 t.Fatal(i) 219 } 220 } 221 222 func TestPrefixedRegistryUnregister(t *testing.T) { 223 r := NewPrefixedRegistry("prefix.") 224 225 _ = r.Register("foo", NewCounter()) 226 227 i := 0 228 r.Each(func(name string, m interface{}) { 229 i++ 230 if name != "prefix.foo" { 231 t.Fatal(name) 232 } 233 }) 234 if i != 1 { 235 t.Fatal(i) 236 } 237 238 r.Unregister("foo") 239 240 i = 0 241 r.Each(func(name string, m interface{}) { 242 i++ 243 }) 244 245 if i != 0 { 246 t.Fatal(i) 247 } 248 } 249 250 func TestPrefixedRegistryGet(t *testing.T) { 251 pr := NewPrefixedRegistry("prefix.") 252 name := "foo" 253 pr.Register(name, NewCounter()) 254 255 fooCounter := pr.Get(name) 256 if fooCounter == nil { 257 t.Fatal(name) 258 } 259 } 260 261 func TestPrefixedChildRegistryGet(t *testing.T) { 262 r := NewRegistry() 263 pr := NewPrefixedChildRegistry(r, "prefix.") 264 name := "foo" 265 pr.Register(name, NewCounter()) 266 fooCounter := pr.Get(name) 267 if fooCounter == nil { 268 t.Fatal(name) 269 } 270 } 271 272 func TestChildPrefixedRegistryRegister(t *testing.T) { 273 r := NewPrefixedChildRegistry(DefaultRegistry, "prefix.") 274 err := r.Register("foo", NewCounter()) 275 c := NewCounter() 276 Register("bar", c) 277 if err != nil { 278 t.Fatal(err.Error()) 279 } 280 281 i := 0 282 r.Each(func(name string, m interface{}) { 283 i++ 284 if name != "prefix.foo" { 285 t.Fatal(name) 286 } 287 }) 288 if i != 1 { 289 t.Fatal(i) 290 } 291 } 292 293 func TestChildPrefixedRegistryOfChildRegister(t *testing.T) { 294 r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") 295 r2 := NewPrefixedChildRegistry(r, "prefix2.") 296 err := r.Register("foo2", NewCounter()) 297 if err != nil { 298 t.Fatal(err.Error()) 299 } 300 err = r2.Register("baz", NewCounter()) 301 c := NewCounter() 302 Register("bars", c) 303 304 i := 0 305 r2.Each(func(name string, m interface{}) { 306 i++ 307 if name != "prefix.prefix2.baz" { 308 //t.Fatal(name) 309 } 310 }) 311 if i != 1 { 312 t.Fatal(i) 313 } 314 } 315 316 func TestWalkRegistries(t *testing.T) { 317 r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") 318 r2 := NewPrefixedChildRegistry(r, "prefix2.") 319 err := r.Register("foo2", NewCounter()) 320 if err != nil { 321 t.Fatal(err.Error()) 322 } 323 err = r2.Register("baz", NewCounter()) 324 c := NewCounter() 325 Register("bars", c) 326 327 _, prefix := findPrefix(r2, "") 328 if "prefix.prefix2." != prefix { 329 t.Fatal(prefix) 330 } 331 } 332 333 func TestConcurrentRegistryAccess(t *testing.T) { 334 r := NewRegistry() 335 336 counter := NewCounter() 337 338 signalChan := make(chan struct{}) 339 340 var wg sync.WaitGroup 341 for i := 0; i < 10; i++ { 342 wg.Add(1) 343 go func(dowork chan struct{}) { 344 defer wg.Done() 345 iface := r.GetOrRegister("foo", counter) 346 retCounter, ok := iface.(Counter) 347 if !ok { 348 t.Fatal("Expected a Counter type") 349 } 350 if retCounter != counter { 351 t.Fatal("Counter references don't match") 352 } 353 }(signalChan) 354 } 355 356 close(signalChan) // Closing will cause all go routines to execute at the same time 357 wg.Wait() // Wait for all go routines to do their work 358 359 // At the end of the test we should still only have a single "foo" Counter 360 i := 0 361 r.Each(func(name string, iface interface{}) { 362 i++ 363 if "foo" != name { 364 t.Fatal(name) 365 } 366 if _, ok := iface.(Counter); !ok { 367 t.Fatal(iface) 368 } 369 }) 370 if 1 != i { 371 t.Fatal(i) 372 } 373 r.Unregister("foo") 374 i = 0 375 r.Each(func(string, interface{}) { i++ }) 376 if 0 != i { 377 t.Fatal(i) 378 } 379 } 380 381 // exercise race detector 382 func TestRegisterAndRegisteredConcurrency(t *testing.T) { 383 r := NewRegistry() 384 wg := &sync.WaitGroup{} 385 wg.Add(1) 386 go func(r Registry, wg *sync.WaitGroup) { 387 defer wg.Done() 388 r.Each(func(name string, iface interface{}) { 389 }) 390 }(r, wg) 391 r.Register("foo", NewCounter()) 392 wg.Wait() 393 }