Merge pull request #17687 from ADITYATIWARI342005/fix/utf8

promql/parser: fix UTF-8 label quoting in format_query endpoint
This commit is contained in:
Julius Volz 2025-12-28 12:08:07 +01:00 committed by GitHub
commit 9da9e6daf4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 3 deletions

View File

@ -109,7 +109,7 @@ func writeLabels(b *bytes.Buffer, ss []string) {
if i > 0 {
b.WriteString(", ")
}
if !model.LegacyValidation.IsValidMetricName(s) {
if !model.LegacyValidation.IsValidLabelName(s) {
b.Write(strconv.AppendQuote(b.AvailableBuffer(), s))
} else {
b.WriteString(s)
@ -147,6 +147,7 @@ func (node *BinaryExpr) ShortString() string {
func (node *BinaryExpr) getMatchingStr() string {
matching := ""
var b bytes.Buffer
vm := node.VectorMatching
if vm != nil {
if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
@ -154,7 +155,10 @@ func (node *BinaryExpr) getMatchingStr() string {
if vm.On {
vmTag = "on"
}
matching = fmt.Sprintf(" %s (%s)", vmTag, strings.Join(vm.MatchingLabels, ", "))
b.WriteString(" " + vmTag + " (")
writeLabels(&b, vm.MatchingLabels)
b.WriteString(")")
matching = b.String()
}
if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
@ -162,7 +166,11 @@ func (node *BinaryExpr) getMatchingStr() string {
if vm.Card == CardManyToOne {
vmCard = "left"
}
matching += fmt.Sprintf(" group_%s (%s)", vmCard, strings.Join(vm.Include, ", "))
b.Reset()
b.WriteString(" group_" + vmCard + " (")
writeLabels(&b, vm.Include)
b.WriteString(")")
matching += b.String()
}
}
return matching

View File

@ -284,6 +284,18 @@ func TestExprString(t *testing.T) {
{
in: `predict_linear(foo[1h], 3000)`,
},
{
in: `sum by("üüü") (foo)`,
out: `sum by ("üüü") (foo)`,
},
{
in: `sum without("äää") (foo)`,
out: `sum without ("äää") (foo)`,
},
{
in: `count by("ööö", job) (foo)`,
out: `count by ("ööö", job) (foo)`,
},
}
EnableExtendedRangeSelectors = true
@ -409,3 +421,55 @@ func TestVectorSelector_String(t *testing.T) {
})
}
}
func TestBinaryExprUTF8Labels(t *testing.T) {
testCases := []struct {
name string
input string
expected string
}{
{
name: "UTF-8 labels in on clause",
input: `foo / on("äää") bar`,
expected: `foo / on ("äää") bar`,
},
{
name: "UTF-8 labels in ignoring clause",
input: `foo / ignoring("üüü") bar`,
expected: `foo / ignoring ("üüü") bar`,
},
{
name: "UTF-8 labels in group_left clause",
input: `foo / on("äää") group_left("ööö") bar`,
expected: `foo / on ("äää") group_left ("ööö") bar`,
},
{
name: "UTF-8 labels in group_right clause",
input: `foo / on("äää") group_right("ööö") bar`,
expected: `foo / on ("äää") group_right ("ööö") bar`,
},
{
name: "Mixed legacy and UTF-8 labels",
input: `foo / on(legacy, "üüü") bar`,
expected: `foo / on (legacy, "üüü") bar`,
},
{
name: "Legacy labels only (should not quote)",
input: `foo / on(job, instance) bar`,
expected: `foo / on (job, instance) bar`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
expr, err := ParseExpr(tc.input)
if err != nil {
t.Fatalf("Failed to parse: %v", err)
}
result := expr.String()
if result != tc.expected {
t.Errorf("Expected: %s\nGot: %s", tc.expected, result)
}
})
}
}