mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-31 15:06:26 +00:00
wip
This commit is contained in:
parent
a53b5570eb
commit
b021020e03
4 changed files with 42 additions and 21 deletions
|
@ -20,6 +20,7 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
|||
## tip
|
||||
|
||||
* FEATURE: add `default` operator to [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe). It allows setting `NaN` result to the given default value.
|
||||
* FEATURE: allow omitting result name in [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe) expresions. In this case the result name is automatically set to string representation of the corresponding math expression. For example, `_time:5m | math duration / 1000` is equivalent to `_time:5m | math (duration / 1000) as "duration / 1000"`.
|
||||
* FEATURE: allow omitting result name in [`stats` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe). In this case the result name is automatically set to string representation of the corresponding [stats function expression](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe-functions). For example, `_time:5m | count(*)` is valid [LogsQL query](https://docs.victoriametrics.com/victorialogs/logsql/) now. It is equivalent to `_time:5m | stats count(*) as "count(*)"`.
|
||||
|
||||
* BUGFIX: properly calculate the number of matching rows in `* | field_values x | stats count() rows` and in `* | unroll (x) | stats count() rows` queries.
|
||||
|
|
|
@ -1594,6 +1594,19 @@ See also:
|
|||
### math pipe
|
||||
|
||||
`| math ...` [pipe](#pipes) performs mathematical calculations over numeric values stored in [log fields](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model).
|
||||
It has the following format:
|
||||
|
||||
```
|
||||
| math
|
||||
expr1 as resultName1,
|
||||
...
|
||||
exprN as resultNameN
|
||||
```
|
||||
|
||||
Where `exprX` is one of the supported math expressions mentioned below, while `resultNameX` is the name of the field to store the calculated result to.
|
||||
The `as` keyword is optional. The result name can be omitted. In this case the result is stored to a field with the name equal to string represenation
|
||||
of the corresponding math expression.
|
||||
|
||||
For example, the following query divides `duration_msecs` field value by 1000, then rounds it to integer and stores the result in the `duration_secs` field:
|
||||
|
||||
```logsql
|
||||
|
@ -1621,15 +1634,6 @@ Every `argX` argument in every mathematical operation can contain one of the fol
|
|||
- Any [supported numeric value](#numeric-values). For example, `response_size_bytes / 1MiB`.
|
||||
- Another mathematical expression. Optionally, it may be put inside `(...)`. For example, `(a + b) * c`.
|
||||
|
||||
Multiple distinct results can be calculated in a single `math ...` pipe - just separate them with `,`. For example, the following query calculates the error rate
|
||||
and the number of successful requests from `errors`, `warnings` and `requests` [log fields](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model):
|
||||
|
||||
```logsql
|
||||
_time:5m | math
|
||||
(errors / requests) as error_rate,
|
||||
(requests - (errors + warnings)) as success_requests
|
||||
```
|
||||
|
||||
See also:
|
||||
|
||||
- [`stats` pipe](#stats-pipe)
|
||||
|
|
|
@ -384,14 +384,20 @@ func parseMathEntry(lex *lexer) (*mathEntry, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// skip optional 'as'
|
||||
if lex.isKeyword("as") {
|
||||
lex.nextToken()
|
||||
}
|
||||
resultField := ""
|
||||
if lex.isKeyword(",", "|", ")", "") {
|
||||
resultField = me.String()
|
||||
} else {
|
||||
if lex.isKeyword("as") {
|
||||
// skip optional 'as'
|
||||
lex.nextToken()
|
||||
}
|
||||
|
||||
resultField, err := parseFieldName(lex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse result name for [%s]: %w", me, err)
|
||||
fieldName, err := parseFieldName(lex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse result name for [%s]: %w", me, err)
|
||||
}
|
||||
resultField = fieldName
|
||||
}
|
||||
|
||||
e := &mathEntry{
|
||||
|
|
|
@ -32,7 +32,6 @@ func TestParsePipeMathFailure(t *testing.T) {
|
|||
}
|
||||
|
||||
f(`math`)
|
||||
f(`math x`)
|
||||
f(`math x as`)
|
||||
f(`math abs() as x`)
|
||||
f(`math abs(a, b) as x`)
|
||||
|
@ -64,7 +63,7 @@ func TestPipeMath(t *testing.T) {
|
|||
},
|
||||
})
|
||||
|
||||
f("math a / b default 10 as c", [][]Field{
|
||||
f("math a / b default c", [][]Field{
|
||||
{
|
||||
{"a", "v1"},
|
||||
{"b", "2"},
|
||||
|
@ -79,21 +78,32 @@ func TestPipeMath(t *testing.T) {
|
|||
{"a", "3"},
|
||||
{"b", "2"},
|
||||
},
|
||||
{
|
||||
{"a", "3"},
|
||||
{"b", "foo"},
|
||||
},
|
||||
}, [][]Field{
|
||||
{
|
||||
{"a", "v1"},
|
||||
{"b", "2"},
|
||||
{"c", "10"},
|
||||
{"c", "3"},
|
||||
{"a / b default c", "3"},
|
||||
},
|
||||
{
|
||||
{"a", "0"},
|
||||
{"b", "0"},
|
||||
{"c", "10"},
|
||||
{"c", "3"},
|
||||
{"a / b default c", "3"},
|
||||
},
|
||||
{
|
||||
{"a", "3"},
|
||||
{"b", "2"},
|
||||
{"c", "1.5"},
|
||||
{"a / b default c", "1.5"},
|
||||
},
|
||||
{
|
||||
{"a", "3"},
|
||||
{"b", "foo"},
|
||||
{"a / b default c", "NaN"},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue