From 7f8b1300a9d9f8fa4752e023a48c05635a5cdede Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Sun, 29 Sep 2024 09:46:11 +0200 Subject: [PATCH] lib/logstorage: add non-empty `if (...)` condition to automatically generated result names in `stats` pipe This allows executing queries with `stats` pipe, which calculate multiple results with the same functions, but with different `if (...)` conditions. For example: _time:5m | count(), count() if (error) Previously such queries couldn't be executed becasue automatically generated name for the second result didn't include `if (error)`, so names for both results were identical - `count(*)`. --- docs/VictoriaLogs/CHANGELOG.md | 1 + lib/logstorage/parser_test.go | 1 + lib/logstorage/pipe_stats.go | 3 +++ 3 files changed, 5 insertions(+) diff --git a/docs/VictoriaLogs/CHANGELOG.md b/docs/VictoriaLogs/CHANGELOG.md index 59de19e650..5b0e97032d 100644 --- a/docs/VictoriaLogs/CHANGELOG.md +++ b/docs/VictoriaLogs/CHANGELOG.md @@ -17,6 +17,7 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta * FEATURE: [data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/): accept Unix timestamps in seconds in the ingested logs. * FEATURE: [`sort` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#sort-pipe): allow using `order` alias instead of `sort`. For example, `_time:5s | order by (_time)` query works the same as `_time:5s | sort by (_time)`. +* FEATURE: [`stats` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe): allow using multiple identical [stats functions](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe-functions) with distinct [filters](https://docs.victoriametrics.com/victorialogs/logsql/#stats-with-additional-filters) and automatically generated result names. For example, `_time:5m | count(), count() if (error)` query works as expected now, e.g. it returns two results over the last 5 minutes: the total number of logs and the number of logs with `error` [word](https://docs.victoriametrics.com/victorialogs/logsql/#word). Previously this query couldn't be executed because the `if (...)` condition wasn't included in the automatically generate result name, so both results had the same name - `count(*)`. ## [v0.31.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.31.0-victorialogs) diff --git a/lib/logstorage/parser_test.go b/lib/logstorage/parser_test.go index 7571e240f9..3593477047 100644 --- a/lib/logstorage/parser_test.go +++ b/lib/logstorage/parser_test.go @@ -1025,6 +1025,7 @@ func TestParseQuerySuccess(t *testing.T) { f(`* | stats count('') foo`, `* | stats count(_msg) as foo`) f(`* | stats count(foo) ''`, `* | stats count(foo) as _msg`) f(`* | count()`, `* | stats count(*) as "count(*)"`) + f(`* | count(), count() if (foo)`, `* | stats count(*) as "count(*)", count(*) if (foo) as "count(*) if (foo)"`) // stats pipe count_empty f(`* | stats count_empty() x`, `* | stats count_empty(*) as x`) diff --git a/lib/logstorage/pipe_stats.go b/lib/logstorage/pipe_stats.go index 9d1906fd35..7946efd1db 100644 --- a/lib/logstorage/pipe_stats.go +++ b/lib/logstorage/pipe_stats.go @@ -577,6 +577,9 @@ func parsePipeStats(lex *lexer, needStatsKeyword bool) (*pipeStats, error) { resultName := "" if lex.isKeyword(",", "|", ")", "") { resultName = sf.String() + if f.iff != nil { + resultName += " " + f.iff.String() + } } else { if lex.isKeyword("as") { lex.nextToken()