This commit is contained in:
Aliaksandr Valialkin 2024-06-04 18:14:34 +02:00
parent 8a14e2daef
commit 4009de2797
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
4 changed files with 55 additions and 2 deletions

View file

@ -19,6 +19,7 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
## tip
* FEATURE: add `ceil()` and `floor()` functions to [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe).
* FEATURE: add support for bitwise `and`, `or` and `xor` operations at [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe).
* FEATURE: add support for automatic conversion of [RFC3339 time](https://www.rfc-editor.org/rfc/rfc3339) and IPv4 addresses into numeric representation at [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe).
* FEATURE: add ability to format numeric fields into string representation of time, duration and IPv4 with [`format` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#format-pipe).

View file

@ -1662,7 +1662,9 @@ The following mathematical operations are supported by `math` pipe:
- `arg1 xor arg2` - returns bitwise `xor` for `arg1` and `arg2`. It is expected that `arg1` and `arg2` are in the range `[0 .. 2^53-1]`
- `arg1 default arg2` - returns `arg2` if `arg1` is non-[numeric](#numeric-values) or 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`.
- `ceil(arg)` - returns the least integer value greater than or equal to `arg`
- `exp(arg)` - powers [`e`](https://en.wikipedia.org/wiki/E_(mathematical_constant)) by `arg`
- `floor(arg)` - returns the greatest integer values less than or equal to `arg`
- `ln(arg)` - returns [natural logarithm](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`

View file

@ -497,6 +497,10 @@ func parseMathExprOperand(lex *lexer) (*mathExpr, error) {
return parseMathExprMin(lex)
case lex.isKeyword("round"):
return parseMathExprRound(lex)
case lex.isKeyword("ceil"):
return parseMathExprCeil(lex)
case lex.isKeyword("floor"):
return parseMathExprFloor(lex)
case lex.isKeyword("-"):
return parseMathExprUnaryMinus(lex)
case lex.isKeyword("+"):
@ -576,6 +580,28 @@ func parseMathExprRound(lex *lexer) (*mathExpr, error) {
return me, nil
}
func parseMathExprCeil(lex *lexer) (*mathExpr, error) {
me, err := parseMathExprGenericFunc(lex, "ceil", mathFuncCeil)
if err != nil {
return nil, err
}
if len(me.args) != 1 {
return nil, fmt.Errorf("'ceil' function needs one arg; got %d args: [%s]", len(me.args), me)
}
return me, nil
}
func parseMathExprFloor(lex *lexer) (*mathExpr, error) {
me, err := parseMathExprGenericFunc(lex, "floor", mathFuncFloor)
if err != nil {
return nil, err
}
if len(me.args) != 1 {
return nil, fmt.Errorf("'floor' function needs one arg; got %d args: [%s]", len(me.args), me)
}
return me, nil
}
func parseMathExprGenericFunc(lex *lexer, funcName string, f mathFunc) (*mathExpr, error) {
if !lex.isKeyword(funcName) {
return nil, fmt.Errorf("missing %q keyword", funcName)
@ -844,6 +870,20 @@ func mathFuncMin(result []float64, args [][]float64) {
}
}
func mathFuncCeil(result []float64, args [][]float64) {
arg := args[0]
for i := range result {
result[i] = math.Ceil(arg[i])
}
}
func mathFuncFloor(result []float64, args [][]float64) {
arg := args[0]
for i := range result {
result[i] = math.Floor(arg[i])
}
}
func mathFuncRound(result []float64, args [][]float64) {
arg := args[0]
if len(args) == 1 {

View file

@ -135,7 +135,7 @@ func TestPipeMath(t *testing.T) {
},
})
f("math round(exp(a), 0.01), round(ln(a), 0.01)", [][]Field{
f("math round(exp(a), 0.01), round(ln(a), 0.01), ceil(exp(a)), floor(exp(a))", [][]Field{
{
{"a", "v1"},
},
@ -156,26 +156,36 @@ func TestPipeMath(t *testing.T) {
{"a", "v1"},
{"round(exp(a), 0.01)", "NaN"},
{"round(ln(a), 0.01)", "NaN"},
{"ceil(exp(a))", "NaN"},
{"floor(exp(a))", "NaN"},
},
{
{"a", "0"},
{"round(exp(a), 0.01)", "1"},
{"round(ln(a), 0.01)", "NaN"},
{"ceil(exp(a))", "1"},
{"floor(exp(a))", "1"},
},
{
{"a", "1"},
{"round(exp(a), 0.01)", "2.72"},
{"round(ln(a), 0.01)", "0"},
{"ceil(exp(a))", "3"},
{"floor(exp(a))", "2"},
},
{
{"a", "2"},
{"round(exp(a), 0.01)", "7.39"},
{"round(ln(a), 0.01)", "0.69"},
{"ceil(exp(a))", "8"},
{"floor(exp(a))", "7"},
},
{
{"a", "3"},
{"round(exp(a), 0.01)", "20.09"},
{"round(ln(a), 0.01)", "1.1"},
{"ceil(exp(a))", "21"},
{"floor(exp(a))", "20"},
},
})