diff --git a/rules/lexer.l b/rules/lexer.l index 1edfcc6b09..4904f7a5b3 100644 --- a/rules/lexer.l +++ b/rules/lexer.l @@ -17,6 +17,7 @@ package rules import ( "github.com/prometheus/prometheus/model" "strconv" + "strings" ) %} @@ -39,6 +40,7 @@ U [smhdwy] permanent { return PERMANENT } BY { return GROUP_OP } AVG|SUM|MAX|MIN { yylval.str = yytext; return AGGR_OP } +avg|sum|max|min { yylval.str = strings.ToUpper(yytext); return AGGR_OP } \<|>|AND|OR { yylval.str = yytext; return CMP_OP } ==|!=|>=|<= { yylval.str = yytext; return CMP_OP } [+\-] { yylval.str = yytext; return ADDITIVE_OP } diff --git a/rules/lexer.l.go b/rules/lexer.l.go index 0671c45afb..8f66be6108 100644 --- a/rules/lexer.l.go +++ b/rules/lexer.l.go @@ -12,6 +12,7 @@ import ( import ( "github.com/prometheus/prometheus/model" "strconv" +"strings" ) var yyin io.Reader = os.Stdin @@ -341,6 +342,20 @@ var yyrules []yyrule = []yyrule{{regexp.MustCompile("[^\\n]"), nil, []yystartcon return yyactionreturn{AGGR_OP, yyRT_USER_RETURN} } return yyactionreturn{0, yyRT_FALLTHROUGH} +}}, {regexp.MustCompile("avg|sum|max|min"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { + defer func() { + if r := recover(); r != nil { + if r != "yyREJECT" { + panic(r) + } + yyar.returnType = yyRT_REJECT + } + }() + { + yylval.str = strings.ToUpper(yytext) + return yyactionreturn{AGGR_OP, yyRT_USER_RETURN} + } + return yyactionreturn{0, yyRT_FALLTHROUGH} }}, {regexp.MustCompile("\\<|>|AND|OR"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { defer func() { if r := recover(); r != nil { diff --git a/rules/rules_test.go b/rules/rules_test.go index a972de4e21..68a366abe9 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -210,20 +210,29 @@ var expressionTests = []struct { fullRanges: 0, intervalRanges: 8, }, { + // Single-letter label names and values. expr: "x{y='testvalue'}", output: []string{ "x{y='testvalue'} => 100 @[%v]", }, fullRanges: 0, intervalRanges: 1, - // Invalid expressions that should fail to parse. }, { + // Lower-cased aggregation operators should work too. + expr: "sum(http_requests) + min(http_requests) + max(http_requests) + avg(http_requests)", + output: []string{"http_requests{} => 4950 @[%v]"}, + fullRanges: 0, + intervalRanges: 8, + }, { + // Empty expressions shouldn't parse. expr: "", shouldFail: true, }, { + // Subtracting a vector from a scalar is not supported. expr: "1 - http_requests", shouldFail: true, }, { + // Interval durations can't be in quotes. expr: "http_requests['1m']", shouldFail: true, },