diff --git a/docs/victorialogs/CHANGELOG.md b/docs/victorialogs/CHANGELOG.md index aad272b68d..d2567c3ed2 100644 --- a/docs/victorialogs/CHANGELOG.md +++ b/docs/victorialogs/CHANGELOG.md @@ -24,6 +24,7 @@ according to the following docs: * FEATURE: [querying API](https://docs.victoriametrics.com/victorialogs/querying/): allow using [`limit`](https://docs.victoriametrics.com/victorialogs/logsql/#limit-pipe) and [`offset`](https://docs.victoriametrics.com/victorialogs/logsql/#offset-pipe) pipes after the [`stats` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe) in queries to [`/select/logsql/stats_query`](https://docs.victoriametrics.com/victorialogs/querying/#querying-log-stats). This enables the usage for these pipes in [alerting and recording rules for VictoriaLogs](https://docs.victoriametrics.com/victorialogs/vmalert/). See [#1296](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1296). * FEATURE: [alerts](https://github.com/VictoriaMetrics/VictoriaLogs/blob/master/deployment/docker/rules): add new alerting rules `PersistentQueueRunsOutOfSpaceIn12Hours` and `PersistentQueueRunsOutOfSpaceIn4Hours` for `vlagent` persistent queue capacity. These alerts help users to take proactive actions before `vlagent` starts dropping logs due to insufficient persistent queue space. See [#10193](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10193) +* FEATURE: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): return a parse error on whitespace between a filter function name and the opening parenthesis, such as `ip:ipv4_range (1.2.3.4, 5.6.7.8)`. Previously such queries were accepted. See [#1385](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1385). * FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): remove the `Date format` setting and always display timestamps with nanosecond precision. See [#1161](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1161). * FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): rename field `Query time` to `Hits query` on the Hits chart panel. The change makes it clear duration of which query is displayed. diff --git a/lib/logstorage/parser.go b/lib/logstorage/parser.go index 3c6204395d..843c4b2c85 100644 --- a/lib/logstorage/parser.go +++ b/lib/logstorage/parser.go @@ -2333,6 +2333,9 @@ func parseFuncArgMaybePrefix(lex *lexer, fieldName string, callback func(arg str lex.restoreState(lexState) return parseFilterPhrase(lex, fieldName) } + if lex.isSkippedSpace { + return nil, fmt.Errorf("unexpected whitespace between %q and '('", funcName) + } lex.nextToken() arg := "" @@ -2873,6 +2876,9 @@ func parseFilterRange(lex *lexer, fieldName string) (filter, error) { lex.restoreState(lexState) return parseFilterPhrase(lex, fieldName) } + if lex.isSkippedSpace { + return nil, fmt.Errorf("unexpected whitespace between %q and %q", funcName, lex.token) + } lex.nextToken() minValue, minValueStr, err := parseNumber(lex) @@ -2953,6 +2959,9 @@ func parseFuncArgs(lex *lexer, fieldName string, callback func(funcName string, lex.restoreState(lexState) return parseFilterPhrase(lex, fieldName) } + if lex.isSkippedSpace { + return nil, fmt.Errorf("unexpected whitespace between %q and '('", funcName) + } args, err := parseArgsInParens(lex) if err != nil { @@ -2969,6 +2978,9 @@ func parseFuncArgsPossibleWildcard(lex *lexer, callback func(args []string) (fil if !lex.isKeyword("(") { return nil, fmt.Errorf("the %q must be put in quotes", funcName) } + if lex.isSkippedSpace { + return nil, fmt.Errorf("unexpected whitespace between %q and '('", funcName) + } args, isWildcard, err := parseArgsInParensPossibleWildcard(lex) if err != nil { diff --git a/lib/logstorage/parser_test.go b/lib/logstorage/parser_test.go index 67fae3e4cf..3d20717d8f 100644 --- a/lib/logstorage/parser_test.go +++ b/lib/logstorage/parser_test.go @@ -2696,6 +2696,7 @@ func TestParseQuery_Failure(t *testing.T) { // invalid i f(`i(`) + f(`i (foo)`) f(`i(aa`) f(`i(aa, bb)`) f(`i(*`) @@ -2729,6 +2730,7 @@ func TestParseQuery_Failure(t *testing.T) { // invalid contains_any f(`contains_any`) f(`a:contains_any`) + f(`contains_any (foo)`) f(`contains_any(`) f(`contains_any(,)`) f(`contains_any(f, b c)`) @@ -2763,6 +2765,8 @@ func TestParseQuery_Failure(t *testing.T) { f(`contains_all(x | fields a,b)`) // invalid ipv4_range + f(`ipv4_range (1.2.3.4, 5.6.7.8)`) + f(`ip:ipv4_range (1.2.3.4, 5.6.7.8)`) f(`ipv4_range(`) f(`ipv4_range(foo,bar)`) f(`ipv4_range(1.2.3.4*)`) @@ -2800,6 +2804,8 @@ func TestParseQuery_Failure(t *testing.T) { f(`pattern_match_suffix(`) // invalid range + f(`range (1,2)`) + f(`foo:range (1,2)`) f(`range(`) f(`range(foo,bar)`) f(`range(1"`)