package metrics import ( "sync" "testing" ) func BenchmarkRegistry(b *testing.B) { r := NewRegistry() r.Register("foo", NewCounter()) b.ResetTimer() for i := 0; i < b.N; i++ { r.Each(func(string, interface{}) {}) } } func BenchmarkRegistryGetOrRegister(b *testing.B) { sample := func() Sample { return nil } tests := []struct { name string ctor func() any }{ {name: "counter", ctor: func() any { return GetOrRegisterCounter("counter", DefaultRegistry) }}, {name: "gauge", ctor: func() any { return GetOrRegisterGauge("gauge", DefaultRegistry) }}, {name: "gaugefloat64", ctor: func() any { return GetOrRegisterGaugeFloat64("gaugefloat64", DefaultRegistry) }}, {name: "histogram", ctor: func() any { return GetOrRegisterHistogram("histogram", DefaultRegistry, sample()) }}, {name: "meter", ctor: func() any { return GetOrRegisterMeter("meter", DefaultRegistry) }}, {name: "timer", ctor: func() any { return GetOrRegisterTimer("timer", DefaultRegistry) }}, {name: "gaugeinfo", ctor: func() any { return GetOrRegisterGaugeInfo("gaugeinfo", DefaultRegistry) }}, {name: "resettingtimer", ctor: func() any { return GetOrRegisterResettingTimer("resettingtimer", DefaultRegistry) }}, {name: "runtimehistogramlazy", ctor: func() any { return GetOrRegisterHistogramLazy("runtimehistogramlazy", DefaultRegistry, sample) }}, } for _, test := range tests { b.Run(test.name, func(b *testing.B) { for i := 0; i < b.N; i++ { test.ctor() } }) } } func BenchmarkRegistryGetOrRegisterParallel_8(b *testing.B) { benchmarkRegistryGetOrRegisterParallel(b, 8) } func BenchmarkRegistryGetOrRegisterParallel_32(b *testing.B) { benchmarkRegistryGetOrRegisterParallel(b, 32) } func benchmarkRegistryGetOrRegisterParallel(b *testing.B, amount int) { r := NewRegistry() b.ResetTimer() var wg sync.WaitGroup for i := 0; i < amount; i++ { wg.Add(1) go func() { for i := 0; i < b.N; i++ { GetOrRegisterMeter("foo", r) } wg.Done() }() } wg.Wait() } func TestRegistry(t *testing.T) { r := NewRegistry() r.Register("foo", NewCounter()) i := 0 r.Each(func(name string, iface interface{}) { i++ if name != "foo" { t.Fatal(name) } if _, ok := iface.(*Counter); !ok { t.Fatal(iface) } }) if i != 1 { t.Fatal(i) } r.Unregister("foo") i = 0 r.Each(func(string, interface{}) { i++ }) if i != 0 { t.Fatal(i) } } func TestRegistryDuplicate(t *testing.T) { r := NewRegistry() if err := r.Register("foo", NewCounter()); nil != err { t.Fatal(err) } if err := r.Register("foo", NewGauge()); nil == err { t.Fatal(err) } i := 0 r.Each(func(name string, iface interface{}) { i++ if _, ok := iface.(*Counter); !ok { t.Fatal(iface) } }) if i != 1 { t.Fatal(i) } } func TestRegistryGet(t *testing.T) { r := NewRegistry() r.Register("foo", NewCounter()) if count := r.Get("foo").(*Counter).Snapshot().Count(); count != 0 { t.Fatal(count) } r.Get("foo").(*Counter).Inc(1) if count := r.Get("foo").(*Counter).Snapshot().Count(); count != 1 { t.Fatal(count) } } func TestRegistryGetOrRegister(t *testing.T) { r := NewRegistry() // First metric wins with GetOrRegister c1 := GetOrRegisterCounter("foo", r) c2 := GetOrRegisterCounter("foo", r) if c1 != c2 { t.Fatal("counters should've matched") } i := 0 r.Each(func(name string, iface interface{}) { i++ if name != "foo" { t.Fatal(name) } if _, ok := iface.(*Counter); !ok { t.Fatal(iface) } }) if i != 1 { t.Fatal(i) } } func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) { r := NewRegistry() // First metric wins with GetOrRegister c1 := GetOrRegisterCounter("foo", r) c2 := GetOrRegisterCounter("foo", r) if c1 != c2 { t.Fatal("counters should've matched") } i := 0 r.Each(func(name string, iface interface{}) { i++ if name != "foo" { t.Fatal(name) } if _, ok := iface.(*Counter); !ok { t.Fatal(iface) } }) if i != 1 { t.Fatal(i) } } func TestRegistryUnregister(t *testing.T) { l := len(arbiter.meters) r := NewRegistry() r.Register("foo", NewCounter()) r.Register("bar", NewMeter()) r.Register("baz", NewTimer()) if len(arbiter.meters) != l+2 { t.Errorf("arbiter.meters: %d != %d\n", l+2, len(arbiter.meters)) } r.Unregister("foo") r.Unregister("bar") r.Unregister("baz") if len(arbiter.meters) != l { t.Errorf("arbiter.meters: %d != %d\n", l+2, len(arbiter.meters)) } } func TestPrefixedChildRegistryGetOrRegister(t *testing.T) { r := NewRegistry() pr := NewPrefixedChildRegistry(r, "prefix.") _ = GetOrRegisterCounter("foo", pr) i := 0 r.Each(func(name string, m interface{}) { i++ if name != "prefix.foo" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } } func TestPrefixedRegistryGetOrRegister(t *testing.T) { r := NewPrefixedRegistry("prefix.") _ = GetOrRegisterCounter("foo", r) i := 0 r.Each(func(name string, m interface{}) { i++ if name != "prefix.foo" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } } func TestPrefixedRegistryRegister(t *testing.T) { r := NewPrefixedRegistry("prefix.") err := r.Register("foo", NewCounter()) c := NewCounter() Register("bar", c) if err != nil { t.Fatal(err.Error()) } i := 0 r.Each(func(name string, m interface{}) { i++ if name != "prefix.foo" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } } func TestPrefixedRegistryUnregister(t *testing.T) { r := NewPrefixedRegistry("prefix.") _ = r.Register("foo", NewCounter()) i := 0 r.Each(func(name string, m interface{}) { i++ if name != "prefix.foo" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } r.Unregister("foo") i = 0 r.Each(func(name string, m interface{}) { i++ }) if i != 0 { t.Fatal(i) } } func TestPrefixedRegistryGet(t *testing.T) { pr := NewPrefixedRegistry("prefix.") name := "foo" pr.Register(name, NewCounter()) fooCounter := pr.Get(name) if fooCounter == nil { t.Fatal(name) } } func TestPrefixedChildRegistryGet(t *testing.T) { r := NewRegistry() pr := NewPrefixedChildRegistry(r, "prefix.") name := "foo" pr.Register(name, NewCounter()) fooCounter := pr.Get(name) if fooCounter == nil { t.Fatal(name) } } func TestChildPrefixedRegistryRegister(t *testing.T) { r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") err := r.Register("foo", NewCounter()) c := NewCounter() Register("bar", c) if err != nil { t.Fatal(err.Error()) } i := 0 r.Each(func(name string, m interface{}) { i++ if name != "prefix.foo" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } } func TestChildPrefixedRegistryOfChildRegister(t *testing.T) { r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") r2 := NewPrefixedChildRegistry(r, "prefix2.") err := r.Register("foo2", NewCounter()) if err != nil { t.Fatal(err.Error()) } err = r2.Register("baz", NewCounter()) if err != nil { t.Fatal(err.Error()) } c := NewCounter() Register("bars", c) i := 0 r2.Each(func(name string, m interface{}) { i++ if name != "prefix.prefix2.baz" { t.Fatal(name) } }) if i != 1 { t.Fatal(i) } } func TestWalkRegistries(t *testing.T) { r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") r2 := NewPrefixedChildRegistry(r, "prefix2.") err := r.Register("foo2", NewCounter()) if err != nil { t.Fatal(err.Error()) } err = r2.Register("baz", NewCounter()) if err != nil { t.Fatal(err.Error()) } c := NewCounter() Register("bars", c) _, prefix := findPrefix(r2, "") if prefix != "prefix.prefix2." { t.Fatal(prefix) } }