Skip to content

Commit 7845b1b

Browse files
authored
Merge branch 'main' into fix-multi-target-missing-metrics
2 parents 366ad11 + 77d9ba3 commit 7845b1b

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

expr/expr_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ func TestEvalExpr(t *testing.T) {
172172
from: 1437127020,
173173
until: 1437127140,
174174
},
175+
"metric unicode name inside a function": {
176+
metric: "1Метрика",
177+
request: "summarize(1Метрика,'1min')",
178+
metricRequest: parser.MetricRequest{
179+
Metric: "1Метрика",
180+
From: 1437127020,
181+
Until: 1437127140,
182+
},
183+
values: []float64{343, 407, 385},
184+
isAbsent: []bool{false, false, false},
185+
stepTime: 60,
186+
from: 1437127020,
187+
until: 1437127140,
188+
},
175189
}
176190

177191
parser.RangeTables = append(parser.RangeTables, unicode.Cyrillic)

pkg/parser/parser.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,16 @@ var disallowedCharactersInMetricName = map[rune]struct{}{
847847
'\'': struct{}{},
848848
' ': struct{}{},
849849
'/': struct{}{},
850+
'|': struct{}{},
850851
}
851852

852853
func unicodeRuneAllowedInName(r rune) bool {
853854
if _, ok := disallowedCharactersInMetricName[r]; ok {
854855
return false
855856
}
857+
if unicode.IsSpace(r) {
858+
return false
859+
}
856860

857861
return true
858862
}
@@ -920,6 +924,10 @@ FOR:
920924
if len(s) < i+2 || s[i+1] == '=' || s[i+1] == ',' || s[i+1] == ')' {
921925
continue
922926
}
927+
// we are here: `key=value`
928+
// ^
929+
// even if '=' is a valid character for metric name, it's a separator for a named arg or tag
930+
break FOR
923931
}
924932
fallthrough
925933
/* */
@@ -929,6 +937,10 @@ FOR:
929937
if isDefault {
930938
r, w = utf8.DecodeRuneInString(s[i:])
931939
if unicodeRuneAllowedInName(r) && unicode.In(r, RangeTables...) {
940+
// this may be a multi-byte rune, but we only wrote the first byte
941+
if w > 1 {
942+
buf.WriteString(s[i+1 : i+w])
943+
}
932944
continue
933945
}
934946
if !isEscape {

pkg/parser/parser_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package parser
22

33
import (
44
"testing"
5+
"unicode"
56

67
"github.com/stretchr/testify/assert"
78
)
@@ -39,13 +40,24 @@ func TestSkipWhitespace(t *testing.T) {
3940
}
4041

4142
func TestParseExpr(t *testing.T) {
43+
// Widen RangeTables to every script so non-ASCII names are allowed.
44+
// The grammar must still recognize '|', '\n', '=', etc. as special characters depending on context.
45+
orig := RangeTables
46+
defer func() { RangeTables = orig }()
47+
for _, t := range unicode.Scripts {
48+
RangeTables = append(RangeTables, t)
49+
}
50+
4251
tests := []struct {
4352
s string
4453
e *expr
4554
}{
4655
{"metric=",
4756
&expr{target: "metric="},
4857
},
58+
{"métric.ñame",
59+
&expr{target: "métric.ñame"},
60+
},
4961
{"metric",
5062
&expr{target: "metric"},
5163
},
@@ -181,6 +193,18 @@ func TestParseExpr(t *testing.T) {
181193
argString: "metric, key='value'",
182194
},
183195
},
196+
{
197+
"func(metric, true\n)",
198+
&expr{
199+
target: "func",
200+
etype: EtFunc,
201+
args: []*expr{
202+
{target: "metric"},
203+
{etype: EtBool, target: "true", valStr: "true"},
204+
},
205+
argString: "metric, true\n",
206+
},
207+
},
184208
{
185209
"func(metric, key=true)",
186210
&expr{

0 commit comments

Comments
 (0)