Skip to content

Commit 0a8115f

Browse files
authored
Merge pull request #474 from prometheus/beorn7/testing
Add check for duplicated label name
2 parents daeaac0 + edb489a commit 0a8115f

File tree

2 files changed

+59
-8
lines changed

2 files changed

+59
-8
lines changed

prometheus/registry.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,8 @@ func checkMetricConsistency(
787787
dtoMetric *dto.Metric,
788788
metricHashes map[uint64]struct{},
789789
) error {
790+
name := metricFamily.GetName()
791+
790792
// Type consistency with metric family.
791793
if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil ||
792794
metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil ||
@@ -795,33 +797,42 @@ func checkMetricConsistency(
795797
metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil {
796798
return fmt.Errorf(
797799
"collected metric %q { %s} is not a %s",
798-
metricFamily.GetName(), dtoMetric, metricFamily.GetType(),
800+
name, dtoMetric, metricFamily.GetType(),
799801
)
800802
}
801803

804+
previousLabelName := ""
802805
for _, labelPair := range dtoMetric.GetLabel() {
803-
if !checkLabelName(labelPair.GetName()) {
806+
labelName := labelPair.GetName()
807+
if labelName == previousLabelName {
808+
return fmt.Errorf(
809+
"collected metric %q { %s} has two or more labels with the same name: %s",
810+
name, dtoMetric, labelName,
811+
)
812+
}
813+
if !checkLabelName(labelName) {
804814
return fmt.Errorf(
805815
"collected metric %q { %s} has a label with an invalid name: %s",
806-
metricFamily.GetName(), dtoMetric, labelPair.GetName(),
816+
name, dtoMetric, labelName,
807817
)
808818
}
809-
if dtoMetric.Summary != nil && labelPair.GetName() == quantileLabel {
819+
if dtoMetric.Summary != nil && labelName == quantileLabel {
810820
return fmt.Errorf(
811821
"collected metric %q { %s} must not have an explicit %q label",
812-
metricFamily.GetName(), dtoMetric, quantileLabel,
822+
name, dtoMetric, quantileLabel,
813823
)
814824
}
815825
if !utf8.ValidString(labelPair.GetValue()) {
816826
return fmt.Errorf(
817827
"collected metric %q { %s} has a label named %q whose value is not utf8: %#v",
818-
metricFamily.GetName(), dtoMetric, labelPair.GetName(), labelPair.GetValue())
828+
name, dtoMetric, labelName, labelPair.GetValue())
819829
}
830+
previousLabelName = labelName
820831
}
821832

822833
// Is the metric unique (i.e. no other metric with the same name and the same labels)?
823834
h := hashNew()
824-
h = hashAdd(h, metricFamily.GetName())
835+
h = hashAdd(h, name)
825836
h = hashAddByte(h, separatorByte)
826837
// Make sure label pairs are sorted. We depend on it for the consistency
827838
// check.
@@ -835,7 +846,7 @@ func checkMetricConsistency(
835846
if _, exists := metricHashes[h]; exists {
836847
return fmt.Errorf(
837848
"collected metric %q { %s} was collected before with the same name and label values",
838-
metricFamily.GetName(), dtoMetric,
849+
name, dtoMetric,
839850
)
840851
}
841852
metricHashes[h] = struct{}{}

prometheus/registry_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,32 @@ collected metric named "complex_count" collides with previously collected summar
307307
histogramCountCollisionMsg := []byte(`An error has occurred during metrics gathering:
308308
309309
collected metric named "complex_count" collides with previously collected histogram named "complex"
310+
`)
311+
externalMetricFamilyWithDuplicateLabel := &dto.MetricFamily{
312+
Name: proto.String("broken_metric"),
313+
Help: proto.String("The registry should detect the duplicate label."),
314+
Type: dto.MetricType_COUNTER.Enum(),
315+
Metric: []*dto.Metric{
316+
{
317+
Label: []*dto.LabelPair{
318+
{
319+
Name: proto.String("foo"),
320+
Value: proto.String("bar"),
321+
},
322+
{
323+
Name: proto.String("foo"),
324+
Value: proto.String("baz"),
325+
},
326+
},
327+
Counter: &dto.Counter{
328+
Value: proto.Float64(2.7),
329+
},
330+
},
331+
},
332+
}
333+
duplicateLabelMsg := []byte(`An error has occurred during metrics gathering:
334+
335+
collected metric "broken_metric" { label:<name:"foo" value:"bar" > label:<name:"foo" value:"baz" > counter:<value:2.7 > } has two or more labels with the same name: foo
310336
`)
311337

312338
type output struct {
@@ -646,6 +672,20 @@ collected metric named "complex_count" collides with previously collected histog
646672
externalMetricFamilyWithBucketSuffix,
647673
},
648674
},
675+
{ // 22
676+
headers: map[string]string{
677+
"Accept": "text/plain",
678+
},
679+
out: output{
680+
headers: map[string]string{
681+
"Content-Type": `text/plain; charset=utf-8`,
682+
},
683+
body: duplicateLabelMsg,
684+
},
685+
externalMF: []*dto.MetricFamily{
686+
externalMetricFamilyWithDuplicateLabel,
687+
},
688+
},
649689
}
650690
for i, scenario := range scenarios {
651691
registry := prometheus.NewPedanticRegistry()

0 commit comments

Comments
 (0)