fix: restore ability to match __name__ multiple times in selector

Add tests to cover this case.

Signed-off-by: Owen Williams <owen.williams@grafana.com>
This commit is contained in:
Owen Williams 2024-02-29 10:22:03 -05:00
parent ab9b770aea
commit e01e7d36e2
2 changed files with 44 additions and 13 deletions

View file

@ -791,20 +791,7 @@ func (p *parser) checkAST(node Node) (typ ValueType) {
// Skip the check for non-empty matchers because an explicit // Skip the check for non-empty matchers because an explicit
// metric name is a non-empty matcher. // metric name is a non-empty matcher.
break 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 // A Vector selector must contain at least one non-empty matcher to prevent
// implicit selection of all metrics (e.g. by a typo). // implicit selection of all metrics (e.g. by a typo).
notEmpty := false notEmpty := false

View file

@ -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: `{`, input: `{`,
fail: true, fail: true,
@ -1934,6 +1976,8 @@ var testExpr = []struct {
fail: true, fail: true,
errMsg: "vector selector must contain at least one non-empty matcher", 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"}`, input: `foo{__name__="bar"}`,
fail: true, fail: true,