Skip to content

Commit e1944b1

Browse files
Remove registry level labels
Registry level labels are redundant and can cause pointless data-series growth.
1 parent 12829c0 commit e1944b1

4 files changed

Lines changed: 112 additions & 42 deletions

File tree

pkg/metrics/gauge.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ func (g *Gauge) expose() string {
4343
}
4444
labels := strings.Join(labelsStrings, ",")
4545

46-
body := fmt.Sprintf("%v{%v} %v %v", g.name, labels, g.value, g.timestamp)
46+
if len(labels) > 0 {
47+
labels = "{" + labels + "}"
48+
}
49+
50+
body := fmt.Sprintf("%v%v %v %v", g.name, labels, g.value, g.timestamp)
4751

4852
return fmt.Sprintf("%v\n%v", typeLine, body)
4953
}

pkg/metrics/gauge_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,26 @@ func TestGaugeExpose(t *testing.T) {
5959
)
6060
}
6161
}
62+
63+
func TestGaugeWithoutLabelsExpose(t *testing.T) {
64+
gauge := &Gauge{
65+
name: "test_gauge",
66+
labels: map[string]string{},
67+
value: 500,
68+
timestamp: 1000,
69+
}
70+
71+
actualText := gauge.expose()
72+
73+
expectedText := "# TYPE test_gauge gauge\ntest_gauge 500 1000"
74+
75+
if actualText != expectedText {
76+
t.Fatalf(
77+
"incorrect gauge expose text:\n"+
78+
"expected: [%v]\n"+
79+
"actual: [%v]",
80+
expectedText,
81+
actualText,
82+
)
83+
}
84+
}

pkg/metrics/registry.go

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -42,50 +42,17 @@ func NewLabel(name, value string) Label {
4242
// Registry performs all management of metrics. Specifically, it allows
4343
// to registering new metrics and exposing them through the metrics server.
4444
type Registry struct {
45-
labels map[string]string
46-
4745
metrics map[string]metric
4846
metricsMutex sync.RWMutex
4947
}
5048

5149
// NewRegistry creates a new metrics registry.
52-
func NewRegistry(
53-
application, identifier string,
54-
additionalLabels ...Label,
55-
) *Registry {
56-
labels := mergeLabels(
57-
map[string]string{
58-
"application": application,
59-
"identifier": identifier,
60-
},
61-
additionalLabels,
62-
)
63-
50+
func NewRegistry() *Registry {
6451
return &Registry{
65-
labels: labels,
6652
metrics: make(map[string]metric),
6753
}
6854
}
6955

70-
func mergeLabels(
71-
labels map[string]string,
72-
additionalLabels []Label,
73-
) map[string]string {
74-
for _, additionalLabel := range additionalLabels {
75-
if additionalLabel.name == "" || additionalLabel.value == "" {
76-
continue
77-
}
78-
79-
if _, exists := labels[additionalLabel.name]; exists {
80-
continue
81-
}
82-
83-
labels[additionalLabel.name] = additionalLabel.value
84-
}
85-
86-
return labels
87-
}
88-
8956
// EnableServer enables the metrics server on the given port. Data will
9057
// be exposed on `/metrics` path.
9158
func (r *Registry) EnableServer(port int) {
@@ -122,7 +89,7 @@ func (r *Registry) exposeMetrics() string {
12289
// will be returned.
12390
func (r *Registry) NewGauge(
12491
name string,
125-
additionalLabels ...Label,
92+
labels ...Label,
12693
) (*Gauge, error) {
12794
r.metricsMutex.Lock()
12895
defer r.metricsMutex.Unlock()
@@ -133,7 +100,7 @@ func (r *Registry) NewGauge(
133100

134101
gauge := &Gauge{
135102
name: name,
136-
labels: mergeLabels(r.labels, additionalLabels),
103+
labels: processLabels(labels),
137104
}
138105

139106
r.metrics[name] = gauge
@@ -146,9 +113,9 @@ func (r *Registry) NewGauge(
146113
func (r *Registry) NewGaugeObserver(
147114
name string,
148115
input ObserverInput,
149-
additionalLabels ...Label,
116+
labels ...Label,
150117
) (*Observer, error) {
151-
gauge, err := r.NewGauge(name, additionalLabels...)
118+
gauge, err := r.NewGauge(name, labels...)
152119
if err != nil {
153120
return nil, err
154121
}
@@ -164,7 +131,7 @@ func (r *Registry) NewGaugeObserver(
164131
// will be returned.
165132
func (r *Registry) NewInfo(
166133
name string,
167-
additionalLabels ...Label,
134+
labels []Label,
168135
) (*Info, error) {
169136
r.metricsMutex.Lock()
170137
defer r.metricsMutex.Unlock()
@@ -173,11 +140,31 @@ func (r *Registry) NewInfo(
173140
return nil, fmt.Errorf("metric [%v] already exists", name)
174141
}
175142

143+
if len(labels) == 0 {
144+
return nil, fmt.Errorf("at least one label should be set")
145+
}
146+
176147
info := &Info{
177148
name: name,
178-
labels: mergeLabels(r.labels, additionalLabels),
149+
labels: processLabels(labels),
179150
}
180151

181152
r.metrics[name] = info
182153
return info, nil
183154
}
155+
156+
func processLabels(
157+
labels []Label,
158+
) map[string]string {
159+
result := make(map[string]string)
160+
161+
for _, label := range labels {
162+
if label.name == "" || label.value == "" {
163+
continue
164+
}
165+
166+
result[label.name] = label.value
167+
}
168+
169+
return result
170+
}

pkg/metrics/registry_test.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
)
66

77
func TestRegistryNewGauge(t *testing.T) {
8-
registry := NewRegistry("test-app", "test-id")
8+
registry := NewRegistry()
99

1010
gauge, err := registry.NewGauge("test-gauge")
1111
if err != nil {
@@ -20,3 +20,59 @@ func TestRegistryNewGauge(t *testing.T) {
2020
t.Fatalf("metric with name [%v] should exist in the registry", gauge.name)
2121
}
2222
}
23+
24+
func TestRegistryNewGaugeObserver(t *testing.T) {
25+
registry := NewRegistry()
26+
27+
input := func() float64 {
28+
return 1
29+
}
30+
31+
_, err := registry.NewGaugeObserver("test-gauge", input)
32+
if err != nil {
33+
t.Fatal(err)
34+
}
35+
36+
if _, err = registry.NewGaugeObserver("test-gauge", input); err == nil {
37+
t.Fatalf("should fail when creating gauge with the same name")
38+
}
39+
40+
if _, exists := registry.metrics["test-gauge"]; !exists {
41+
t.Fatalf("metric with name [%v] should exist in the registry", "test-gauge")
42+
}
43+
}
44+
45+
func TestRegistryNewInfo(t *testing.T) {
46+
registry := NewRegistry()
47+
48+
if _, err := registry.NewInfo("test-info", []Label{}); err == nil {
49+
t.Fatalf("should fail when creating info without labels")
50+
}
51+
52+
label := NewLabel("label", "value")
53+
info, err := registry.NewInfo("test-info", []Label{label})
54+
if err != nil {
55+
t.Fatal(err)
56+
}
57+
58+
if _, err = registry.NewInfo("test-info", []Label{label}); err == nil {
59+
t.Fatalf("should fail when creating info with the same name")
60+
}
61+
62+
if _, exists := registry.metrics[info.name]; !exists {
63+
t.Fatalf("metric with name [%v] should exist in the registry", info.name)
64+
}
65+
66+
expectedLabelValue, exists := info.labels[label.name]
67+
if !exists {
68+
t.Fatalf("label with name [%v] should exist", label.name)
69+
}
70+
71+
if expectedLabelValue != label.value {
72+
t.Fatalf(
73+
"label with name [%v] should have value [%v]",
74+
label.name,
75+
label.value,
76+
)
77+
}
78+
}

0 commit comments

Comments
 (0)