mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-31 15:06:26 +00:00
wip
This commit is contained in:
parent
8a14e2daef
commit
4009de2797
4 changed files with 55 additions and 2 deletions
|
@ -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).
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue