From e01e7d36e284857cd6b961cc1627bedbd62be890 Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Thu, 29 Feb 2024 10:22:03 -0500 Subject: [PATCH] fix: restore ability to match __name__ multiple times in selector Add tests to cover this case. Signed-off-by: Owen Williams --- promql/parser/parse.go | 13 ----------- promql/parser/parse_test.go | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/promql/parser/parse.go b/promql/parser/parse.go index 6a05e4a79..eca439652 100644 --- a/promql/parser/parse.go +++ b/promql/parser/parse.go @@ -791,20 +791,7 @@ func (p *parser) checkAST(node Node) (typ ValueType) { // Skip the check for non-empty matchers because an explicit // metric name is a non-empty matcher. break - } else { - // We also have to make sure a metric name was not set twice inside the - // braces. - foundMetricName := "" - for _, m := range n.LabelMatchers { - if m != nil && m.Name == labels.MetricName { - if foundMetricName != "" { - p.addParseErrf(n.PositionRange(), "metric name must not be set twice: %q or %q", foundMetricName, m.Value) - } - foundMetricName = m.Value - } - } } - // A Vector selector must contain at least one non-empty matcher to prevent // implicit selection of all metrics (e.g. by a typo). notEmpty := false diff --git a/promql/parser/parse_test.go b/promql/parser/parse_test.go index bd696ae96..48d742653 100644 --- a/promql/parser/parse_test.go +++ b/promql/parser/parse_test.go @@ -1852,6 +1852,48 @@ var testExpr = []struct { }, }, }, + { + // Specifying __name__ twice inside the braces is ok. + input: `{__name__=~"bar", __name__!~"baz"}`, + expected: &VectorSelector{ + LabelMatchers: []*labels.Matcher{ + MustLabelMatcher(labels.MatchRegexp, model.MetricNameLabel, "bar"), + MustLabelMatcher(labels.MatchNotRegexp, model.MetricNameLabel, "baz"), + }, + PosRange: posrange.PositionRange{ + Start: 0, + End: 34, + }, + }, + }, + { + // Specifying __name__ with equality twice inside the braces is even allowed. + input: `{__name__="bar", __name__="baz"}`, + expected: &VectorSelector{ + LabelMatchers: []*labels.Matcher{ + MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"), + MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "baz"), + }, + PosRange: posrange.PositionRange{ + Start: 0, + End: 32, + }, + }, + }, + { + // Because the above are allowed, this is also allowed. + input: `{"bar", __name__="baz"}`, + expected: &VectorSelector{ + LabelMatchers: []*labels.Matcher{ + MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"), + MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "baz"), + }, + PosRange: posrange.PositionRange{ + Start: 0, + End: 23, + }, + }, + }, { input: `{`, fail: true, @@ -1934,6 +1976,8 @@ var testExpr = []struct { fail: true, errMsg: "vector selector must contain at least one non-empty matcher", }, + // Although {"bar", __name__="baz"} is allowed (see above), specifying a + // metric name inside and outside the braces is not. { input: `foo{__name__="bar"}`, fail: true,