mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-31 15:06:26 +00:00
wip
This commit is contained in:
parent
b021020e03
commit
c75c8d7953
3 changed files with 88 additions and 0 deletions
|
@ -1623,6 +1623,8 @@ The following mathematical operations are supported by `math` pipe:
|
|||
- `arg1 ^ arg2` - returns the power of `arg1` by `arg2`
|
||||
- `arg1 default arg2` - returns `arg2` if `arg1` equals to `NaN`.
|
||||
- `abs(arg)` - returns an absolute value for the given `arg`
|
||||
- `exp(arg)` - powers [`e`](https://en.wikipedia.org/wiki/E_(mathematical_constant)) by `arg`.
|
||||
- `ln(arg)` - returns [natural logarightm](https://en.wikipedia.org/wiki/Natural_logarithm) for the given `arg`.
|
||||
- `max(arg1, ..., argN)` - returns the maximum value among the given `arg1`, ..., `argN`
|
||||
- `min(arg1, ..., argN)` - returns the minimum value among the given `arg1`, ..., `argN`
|
||||
- `round(arg)` - returns rounded to integer value for the given `arg`. The `round()` accepts optional `nearest` arg, which allows rounding the number to the given `nearest` multiple.
|
||||
|
@ -1631,6 +1633,7 @@ The following mathematical operations are supported by `math` pipe:
|
|||
Every `argX` argument in every mathematical operation can contain one of the following values:
|
||||
|
||||
- The name of [log field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model). For example, `errors_total / requests_total`.
|
||||
If the log field contains value, which cannot be parsed into [supported numeric value](#numeric-values), then it is replaced with `NaN`.
|
||||
- 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`.
|
||||
|
||||
|
|
|
@ -479,6 +479,10 @@ func parseMathExprOperand(lex *lexer) (*mathExpr, error) {
|
|||
switch {
|
||||
case lex.isKeyword("abs"):
|
||||
return parseMathExprAbs(lex)
|
||||
case lex.isKeyword("exp"):
|
||||
return parseMathExprExp(lex)
|
||||
case lex.isKeyword("ln"):
|
||||
return parseMathExprLn(lex)
|
||||
case lex.isKeyword("max"):
|
||||
return parseMathExprMax(lex)
|
||||
case lex.isKeyword("min"):
|
||||
|
@ -509,6 +513,28 @@ func parseMathExprAbs(lex *lexer) (*mathExpr, error) {
|
|||
return me, nil
|
||||
}
|
||||
|
||||
func parseMathExprExp(lex *lexer) (*mathExpr, error) {
|
||||
me, err := parseMathExprGenericFunc(lex, "exp", mathFuncExp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(me.args) != 1 {
|
||||
return nil, fmt.Errorf("'exp' function accepts only one arg; got %d args: [%s]", len(me.args), me)
|
||||
}
|
||||
return me, nil
|
||||
}
|
||||
|
||||
func parseMathExprLn(lex *lexer) (*mathExpr, error) {
|
||||
me, err := parseMathExprGenericFunc(lex, "ln", mathFuncLn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(me.args) != 1 {
|
||||
return nil, fmt.Errorf("'ln' function accepts only one arg; got %d args: [%s]", len(me.args), me)
|
||||
}
|
||||
return me, nil
|
||||
}
|
||||
|
||||
func parseMathExprMax(lex *lexer) (*mathExpr, error) {
|
||||
me, err := parseMathExprGenericFunc(lex, "max", mathFuncMax)
|
||||
if err != nil {
|
||||
|
@ -729,6 +755,20 @@ func mathFuncAbs(result []float64, args [][]float64) {
|
|||
}
|
||||
}
|
||||
|
||||
func mathFuncExp(result []float64, args [][]float64) {
|
||||
arg := args[0]
|
||||
for i := range result {
|
||||
result[i] = math.Exp(arg[i])
|
||||
}
|
||||
}
|
||||
|
||||
func mathFuncLn(result []float64, args [][]float64) {
|
||||
arg := args[0]
|
||||
for i := range result {
|
||||
result[i] = math.Log(arg[i])
|
||||
}
|
||||
}
|
||||
|
||||
func mathFuncUnaryMinus(result []float64, args [][]float64) {
|
||||
arg := args[0]
|
||||
for i := range result {
|
||||
|
|
|
@ -23,6 +23,7 @@ func TestParsePipeMathSuccess(t *testing.T) {
|
|||
f(`math round(foo) as x`)
|
||||
f(`math round(foo, 0.1) as y`)
|
||||
f(`math (a / b default 10) as z`)
|
||||
f(`math (ln(a) + exp(b)) as x`)
|
||||
}
|
||||
|
||||
func TestParsePipeMathFailure(t *testing.T) {
|
||||
|
@ -107,6 +108,50 @@ func TestPipeMath(t *testing.T) {
|
|||
},
|
||||
})
|
||||
|
||||
f("math round(exp(a), 0.01), round(ln(a), 0.01)", [][]Field{
|
||||
{
|
||||
{"a", "v1"},
|
||||
},
|
||||
{
|
||||
{"a", "0"},
|
||||
},
|
||||
{
|
||||
{"a", "1"},
|
||||
},
|
||||
{
|
||||
{"a", "2"},
|
||||
},
|
||||
{
|
||||
{"a", "3"},
|
||||
},
|
||||
}, [][]Field{
|
||||
{
|
||||
{"a", "v1"},
|
||||
{"round(exp(a), 0.01)", "NaN"},
|
||||
{"round(ln(a), 0.01)", "NaN"},
|
||||
},
|
||||
{
|
||||
{"a", "0"},
|
||||
{"round(exp(a), 0.01)", "1"},
|
||||
{"round(ln(a), 0.01)", "NaN"},
|
||||
},
|
||||
{
|
||||
{"a", "1"},
|
||||
{"round(exp(a), 0.01)", "2.72"},
|
||||
{"round(ln(a), 0.01)", "0"},
|
||||
},
|
||||
{
|
||||
{"a", "2"},
|
||||
{"round(exp(a), 0.01)", "7.39"},
|
||||
{"round(ln(a), 0.01)", "0.69"},
|
||||
},
|
||||
{
|
||||
{"a", "3"},
|
||||
{"round(exp(a), 0.01)", "20.09"},
|
||||
{"round(ln(a), 0.01)", "1.1"},
|
||||
},
|
||||
})
|
||||
|
||||
f("math 1 as a", [][]Field{
|
||||
{
|
||||
{"a", "v1"},
|
||||
|
|
Loading…
Reference in a new issue