Skip to content

Commit ddb09eb

Browse files
ashrayjainbmoylan
authored andcommitted
Fix memory leak in Unregister (#145)
1 parent 37420ae commit ddb09eb

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

metrics/registry.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,13 @@ func (r *rootRegistry) Each(f MetricVisitor) {
283283
name = metricWithTags.name
284284
tags = make(Tags, len(metricWithTags.tags))
285285
copy(tags, metricWithTags.tags)
286-
} else {
286+
} else if r.registry.Get(id) != nil {
287287
// Metric was added to rcrowley registry outside of our registry.
288288
// This is likely a go runtime metric (nothing else is exposed).
289289
name = id
290+
} else {
291+
// Metric was unregistered between us looking at the registry and idToMetricWithTags, move on
292+
continue
290293
}
291294

292295
val := ToMetricVal(allMetrics[id])
@@ -301,6 +304,11 @@ func (r *rootRegistry) Each(f MetricVisitor) {
301304
func (r *rootRegistry) Unregister(name string, tags ...Tag) {
302305
metricID := toMetricTagsID(name, newSortedTags(tags))
303306
r.registry.Unregister(string(metricID))
307+
308+
// This must happen after the registry Unregister() above to preserve the correctness guarantees in Each()
309+
r.idToMetricMutex.Lock()
310+
delete(r.idToMetricWithTags, metricID)
311+
r.idToMetricMutex.Unlock()
304312
}
305313

306314
func (r *rootRegistry) Counter(name string, tags ...Tag) metrics.Counter {

metrics/registry_internal_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2019 Palantir Technologies. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package metrics
6+
7+
import (
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestRootRegistry_UnregisterReleasesResources(t *testing.T) {
14+
// register root metrics
15+
root := NewRootMetricsRegistry().(*rootRegistry)
16+
17+
id := toMetricTagsID("my-counter", Tags{})
18+
19+
// register metric
20+
root.Counter("my-counter").Inc(1)
21+
assert.Contains(t, root.idToMetricWithTags, id)
22+
23+
// unregister metric
24+
root.Unregister("my-counter")
25+
assert.NotContains(t, root.idToMetricWithTags, id)
26+
}

0 commit comments

Comments
 (0)