Skip to content

Commit 41c7344

Browse files
fix: deduplicate prom labels in metric generator registry again (#5819) (#5822)
* fix: deduplicate prom labels in metric generator registry again * handle nil case
1 parent e4d8776 commit 41c7344

File tree

7 files changed

+40
-32
lines changed

7 files changed

+40
-32
lines changed

modules/generator/registry/counter.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,8 @@ func (c *counter) Inc(labelValueCombo *LabelValueCombo, value float64) {
102102
}
103103

104104
func (c *counter) newSeries(labelValueCombo *LabelValueCombo, value float64) *counterSeries {
105-
lb := labels.NewBuilder(getLabelsFromValueCombo(labelValueCombo))
106-
for name, value := range c.externalLabels {
107-
lb.Set(name, value)
108-
}
109-
110-
lb.Set(labels.MetricName, c.metricName)
111-
112105
return &counterSeries{
113-
labels: lb.Labels(),
106+
labels: getSeriesLabels(c.metricName, labelValueCombo, c.externalLabels),
114107
value: atomic.NewFloat64(value),
115108
lastUpdated: atomic.NewInt64(time.Now().UnixMilli()),
116109
firstSeries: atomic.NewBool(true),

modules/generator/registry/gauge.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,8 @@ func (g *gauge) updateSeries(labelValueCombo *LabelValueCombo, value float64, op
114114
}
115115

116116
func (g *gauge) newSeries(labelValueCombo *LabelValueCombo, value float64) *gaugeSeries {
117-
lb := labels.NewBuilder(getLabelsFromValueCombo(labelValueCombo))
118-
for name, value := range g.externalLabels {
119-
lb.Set(name, value)
120-
}
121-
122-
lb.Set(labels.MetricName, g.metricName)
123-
124117
return &gaugeSeries{
125-
labels: lb.Labels(),
118+
labels: getSeriesLabels(g.metricName, labelValueCombo, g.externalLabels),
126119
value: atomic.NewFloat64(value),
127120
lastUpdated: atomic.NewInt64(time.Now().UnixMilli()),
128121
}

modules/generator/registry/histogram.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,7 @@ func (h *histogram) newSeries(labelValueCombo *LabelValueCombo, value float64, t
146146
// Precompute all labels for all sub-metrics upfront
147147

148148
// Create and populate label builder
149-
lb := labels.NewBuilder(getLabelsFromValueCombo(labelValueCombo))
150-
for name, value := range h.externalLabels {
151-
lb.Set(name, value)
152-
}
149+
lb := newSeriesLabelsBuilder(labelValueCombo, h.externalLabels)
153150

154151
// _count
155152
lb.Set(labels.MetricName, h.nameCount)

modules/generator/registry/native_histogram.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,7 @@ func (h *nativeHistogram) newSeries(labelValueCombo *LabelValueCombo, value floa
188188

189189
h.updateSeries(newSeries, value, traceID, multiplier)
190190

191-
lb := labels.NewBuilder(getLabelsFromValueCombo(labelValueCombo))
192-
// set external labels
193-
for name, value := range h.externalLabels {
194-
lb.Set(name, value)
195-
}
191+
lb := newSeriesLabelsBuilder(labelValueCombo, h.externalLabels)
196192

197193
lb.Set(labels.MetricName, h.metricName)
198194

modules/generator/registry/registry_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func TestManagedRegistry_counter(t *testing.T) {
6666

6767
counter := registry.NewCounter("my_counter")
6868

69-
counter.Inc(newLabelValueCombo([]string{"label"}, []string{"value-1"}), 1.0)
69+
counter.Inc(newLabelValueCombo([]string{"label", "label"}, []string{"repeated-value", "value-1"}), 1.0)
7070

7171
expectedSamples := []sample{
7272
newSample(map[string]string{"__name__": "my_counter", "label": "value-1", "__metrics_gen_instance": mustGetHostname()}, 0, 0.0),
@@ -304,6 +304,14 @@ func collectRegistryMetricsAndAssert(t *testing.T, r *ManagedRegistry, appender
304304
collectionTimeMs := time.Now().UnixMilli()
305305
r.CollectMetrics(context.Background())
306306

307+
// Validate that there are no duplicate label names in any sample
308+
for i, sample := range appender.samples {
309+
if duplicateLabel, hasDuplicate := sample.l.HasDuplicateLabelNames(); hasDuplicate {
310+
t.Errorf("Sample %d has duplicate label name %q. Full labels: %v",
311+
i, duplicateLabel, sample.l)
312+
}
313+
}
314+
307315
// Ignore the collection time on expected samples, since we won't know when the collection will actually take place.
308316
for i := range expectedSamples {
309317
expectedSamples[i].t = collectionTimeMs

modules/generator/registry/test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,12 @@ func (t *testHistogram) countActiveSeries() int {
215215
// countSeriesDemand is a stub to satisfy optional estimator usage in registry.
216216
// Test registry does not track estimates, so return 0.
217217
func (t *testHistogram) countSeriesDemand() int { return 0 }
218+
219+
func getLabelsFromValueCombo(labelValueCombo *LabelValueCombo) labels.Labels {
220+
lbls := labelValueCombo.getLabelPair()
221+
lb := make([]labels.Label, len(lbls.names))
222+
for i := range lbls.names {
223+
lb[i] = labels.Label{Name: lbls.names[i], Value: lbls.values[i]}
224+
}
225+
return labels.New(lb...)
226+
}

modules/generator/registry/util.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@ package registry
22

33
import "github.com/prometheus/prometheus/model/labels"
44

5-
func getLabelsFromValueCombo(labelValueCombo *LabelValueCombo) labels.Labels {
6-
lbls := labelValueCombo.getLabelPair()
7-
lb := make([]labels.Label, len(lbls.names))
8-
for i := range lbls.names {
9-
lb[i] = labels.Label{Name: lbls.names[i], Value: lbls.values[i]}
5+
// newSeriesLabelsBuilder creates a labels builder with user labels and external labels pre-populated.
6+
func newSeriesLabelsBuilder(labelValueCombo *LabelValueCombo, externalLabels map[string]string) *labels.Builder {
7+
builder := labels.NewBuilder(labels.Labels{})
8+
if labelValueCombo != nil {
9+
for i := range labelValueCombo.labels.names {
10+
builder.Set(labelValueCombo.labels.names[i], labelValueCombo.labels.values[i])
11+
}
1012
}
11-
return labels.New(lb...)
13+
for name, value := range externalLabels {
14+
builder.Set(name, value)
15+
}
16+
return builder
17+
}
18+
19+
// Returns the labels for the metric series including external labels
20+
func getSeriesLabels(metricName string, labelValueCombo *LabelValueCombo, externalLabels map[string]string) labels.Labels {
21+
builder := newSeriesLabelsBuilder(labelValueCombo, externalLabels)
22+
builder.Set(labels.MetricName, metricName)
23+
return builder.Labels()
1224
}

0 commit comments

Comments
 (0)