Properly unregister Summary metric in Set.UnregisterMetric

This commit is contained in:
Aliaksandr Valialkin 2020-02-26 20:37:47 +02:00
parent 900c892625
commit a494df3462
3 changed files with 83 additions and 24 deletions

48
set.go
View File

@ -439,23 +439,57 @@ func (s *Set) registerMetric(name string, m metric) {
} }
} }
// UnregisterMetric will remove a registered metric // UnregisterMetric removes metric with the given name from s.
//
// True is returned if the metric has been removed.
// False is returned if the given metric is missing in s.
func (s *Set) UnregisterMetric(name string) bool { func (s *Set) UnregisterMetric(name string) bool {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock()
nm, ok := s.m[name] nm, ok := s.m[name]
if ok { if !ok {
return false
}
m := nm.metric
delete(s.m, name) delete(s.m, name)
for i, a := range s.a {
if a == nm { // remove metric from s.a
found := false
for i, nm := range s.a {
if nm.name == name {
s.a = append(s.a[:i], s.a[i+1:]...) s.a = append(s.a[:i], s.a[i+1:]...)
found = true
break
} }
} }
if !found {
panic(fmt.Errorf("BUG: cannot find metric %q in the list of registered metrics", name))
} }
s.mu.Unlock() sm, ok := m.(*Summary)
return ok if !ok {
// There is no need in cleaning up s.summaries.
return true
} }
// ListMetricNames will return a list of all registered metrics // Remove sm from s.summaries
found = false
for i, xsm := range s.summaries {
if xsm == sm {
s.summaries = append(s.summaries[:i], s.summaries[i+1:]...)
found = true
break
}
}
if !found {
panic(fmt.Errorf("BUG: cannot find summary %q in the list of registered summaries", name))
}
unregisterSummary(sm)
return true
}
// ListMetricNames returns a list of all the metrics in s.
func (s *Set) ListMetricNames() []string { func (s *Set) ListMetricNames() []string {
var list []string var list []string
for name := range s.m { for name := range s.m {

View File

@ -35,7 +35,7 @@ func TestNewSet(t *testing.T) {
} }
} }
func TestListMetricNames(t *testing.T) { func TestSetListMetricNames(t *testing.T) {
s := NewSet() s := NewSet()
expect := []string{"cnt1", "cnt2", "cnt3"} expect := []string{"cnt1", "cnt2", "cnt3"}
// Initialize a few counters // Initialize a few counters
@ -62,33 +62,39 @@ func TestListMetricNames(t *testing.T) {
} }
} }
func TestUnregisterMetric(t *testing.T) { func TestSetUnregisterMetric(t *testing.T) {
s := NewSet() s := NewSet()
// Initialize a few counters // Initialize a few metrics
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
c := s.NewCounter(fmt.Sprintf("counter_%d", i)) c := s.NewCounter(fmt.Sprintf("counter_%d", i))
c.Inc() c.Inc()
sm := s.NewSummary(fmt.Sprintf("summary_%d", i))
sm.Update(float64(i))
} }
// Unregister existing counters // Unregister existing metrics
ok := s.UnregisterMetric("counter_1") if !s.UnregisterMetric("counter_1") {
if !ok { t.Fatalf("UnregisterMetric(counter_1) must return true")
t.Fatalf("Metric counter_1 should return true for deregistering") }
if !s.UnregisterMetric("summary_1") {
t.Fatalf("UnregisterMetric(summary_1) must return true")
} }
// Unregister twice must return false // Unregister twice must return false
ok = s.UnregisterMetric("counter_1") if s.UnregisterMetric("counter_1") {
if ok { t.Fatalf("UnregisterMetric(counter_1) must return false on unregistered metric")
t.Fatalf("Metric counter_1 should not return false on unregister twice") }
if s.UnregisterMetric("summary_1") {
t.Fatalf("UnregisterMetric(summary_1) must return false on unregistered metric")
} }
// Validate counters are removed // Validate metrics are removed
ok = false ok := false
for _, n := range s.ListMetricNames() { for _, n := range s.ListMetricNames() {
if n == "counter_1" { if n == "counter_1" || n == "summary_1" {
ok = true ok = true
} }
} }
if ok { if ok {
t.Fatalf("Metric counter_1 and counter_3 must not be listed anymore after unregister") t.Fatalf("Metric counter_1 and summary_1 must not be listed anymore after unregister")
} }
} }

View File

@ -213,6 +213,25 @@ func registerSummary(sm *Summary) {
summariesLock.Unlock() summariesLock.Unlock()
} }
func unregisterSummary(sm *Summary) {
window := sm.window
summariesLock.Lock()
sms := summaries[window]
found := false
for i, xsm := range sms {
if xsm == sm {
sms = append(sms[:i], sms[i+1:]...)
found = true
break
}
}
if !found {
panic(fmt.Errorf("BUG: cannot find registered summary %p", sm))
}
summaries[window] = sms
summariesLock.Unlock()
}
func summariesSwapCron(window time.Duration) { func summariesSwapCron(window time.Duration) {
for { for {
time.Sleep(window / 2) time.Sleep(window / 2)