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  }