be819551e3
The change covers two things: 1. Cleanup of Set.a metrics list from per-quantile metrics for summary. 2. Register summary metric and per-quantile metrics in one take. This prevents registry corruption when Unregister called in the middle of metric register process.
153 lines
3.6 KiB
Go
153 lines
3.6 KiB
Go
package metrics
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNewSet(t *testing.T) {
|
|
var ss []*Set
|
|
for i := 0; i < 10; i++ {
|
|
s := NewSet()
|
|
ss = append(ss, s)
|
|
}
|
|
for i := 0; i < 10; i++ {
|
|
s := ss[i]
|
|
for j := 0; j < 10; j++ {
|
|
c := s.NewCounter(fmt.Sprintf("counter_%d", j))
|
|
c.Inc()
|
|
if n := c.Get(); n != 1 {
|
|
t.Fatalf("unexpected counter value; got %d; want %d", n, 1)
|
|
}
|
|
g := s.NewGauge(fmt.Sprintf("gauge_%d", j), func() float64 { return 123 })
|
|
if v := g.Get(); v != 123 {
|
|
t.Fatalf("unexpected gauge value; got %v; want %v", v, 123)
|
|
}
|
|
sm := s.NewSummary(fmt.Sprintf("summary_%d", j))
|
|
if sm == nil {
|
|
t.Fatalf("NewSummary returned nil")
|
|
}
|
|
h := s.NewHistogram(fmt.Sprintf("histogram_%d", j))
|
|
if h == nil {
|
|
t.Fatalf("NewHistogram returned nil")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSetListMetricNames(t *testing.T) {
|
|
s := NewSet()
|
|
expect := []string{"cnt1", "cnt2", "cnt3"}
|
|
// Initialize a few counters
|
|
for _, n := range expect {
|
|
c := s.NewCounter(n)
|
|
c.Inc()
|
|
}
|
|
|
|
list := s.ListMetricNames()
|
|
|
|
if len(list) != len(expect) {
|
|
t.Fatalf("Metrics count is wrong for listing")
|
|
}
|
|
for _, e := range expect {
|
|
found := false
|
|
for _, n := range list {
|
|
if e == n {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("Metric %s not found in listing", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSetUnregisterMetric(t *testing.T) {
|
|
s := NewSet()
|
|
const cName, smName = "counter_1", "summary_1"
|
|
// Initialize a few metrics
|
|
c := s.NewCounter(cName)
|
|
c.Inc()
|
|
sm := s.NewSummary(smName)
|
|
sm.Update(1)
|
|
|
|
// Unregister existing metrics
|
|
if !s.UnregisterMetric(cName) {
|
|
t.Fatalf("UnregisterMetric(%s) must return true", cName)
|
|
}
|
|
if !s.UnregisterMetric(smName) {
|
|
t.Fatalf("UnregisterMetric(%s) must return true", smName)
|
|
}
|
|
|
|
// Unregister twice must return false
|
|
if s.UnregisterMetric(cName) {
|
|
t.Fatalf("UnregisterMetric(%s) must return false on unregistered metric", cName)
|
|
}
|
|
if s.UnregisterMetric(smName) {
|
|
t.Fatalf("UnregisterMetric(%s) must return false on unregistered metric", smName)
|
|
}
|
|
|
|
// verify that registry is empty
|
|
if len(s.m) != 0 {
|
|
t.Fatalf("expected metrics map to be empty; got %d elements", len(s.m))
|
|
}
|
|
if len(s.a) != 0 {
|
|
t.Fatalf("expected metrics list to be empty; got %d elements", len(s.a))
|
|
}
|
|
|
|
// Validate metrics are removed
|
|
ok := false
|
|
for _, n := range s.ListMetricNames() {
|
|
if n == cName || n == smName {
|
|
ok = true
|
|
}
|
|
}
|
|
if ok {
|
|
t.Fatalf("Metric counter_1 and summary_1 must not be listed anymore after unregister")
|
|
}
|
|
|
|
// re-register with the same names supposed
|
|
// to be successful
|
|
s.NewCounter(cName).Inc()
|
|
s.NewSummary(smName).Update(float64(1))
|
|
}
|
|
|
|
// TestRegisterUnregister tests concurrent access to
|
|
// metrics during registering and unregistering.
|
|
// Should be tested specifically with `-race` enabled.
|
|
func TestRegisterUnregister(t *testing.T) {
|
|
const (
|
|
workers = 16
|
|
iterations = 1e3
|
|
)
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(workers)
|
|
for n := 0; n < workers; n++ {
|
|
go func() {
|
|
defer wg.Done()
|
|
now := time.Now()
|
|
for i := 0; i < iterations; i++ {
|
|
iteration := i % 5
|
|
counter := fmt.Sprintf(`counter{iteration="%d"}`, iteration)
|
|
GetOrCreateCounter(counter).Add(i)
|
|
UnregisterMetric(counter)
|
|
|
|
histogram := fmt.Sprintf(`histogram{iteration="%d"}`, iteration)
|
|
GetOrCreateHistogram(histogram).UpdateDuration(now)
|
|
UnregisterMetric(histogram)
|
|
|
|
gauge := fmt.Sprintf(`gauge{iteration="%d"}`, iteration)
|
|
GetOrCreateGauge(gauge, func() float64 { return 1 })
|
|
UnregisterMetric(gauge)
|
|
|
|
summary := fmt.Sprintf(`summary{iteration="%d"}`, iteration)
|
|
GetOrCreateSummary(summary).Update(float64(i))
|
|
UnregisterMetric(summary)
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|