Add mad_over_time function
Signed-off-by: Jeanette Tan <jeanette.tan@grafana.com>
This commit is contained in:
parent
5dbbadf598
commit
9bf4cc993e
|
@ -640,6 +640,7 @@ over time and return an instant vector with per-series aggregation results:
|
|||
* `quantile_over_time(scalar, range-vector)`: the φ-quantile (0 ≤ φ ≤ 1) of the values in the specified interval.
|
||||
* `stddev_over_time(range-vector)`: the population standard deviation of the values in the specified interval.
|
||||
* `stdvar_over_time(range-vector)`: the population standard variance of the values in the specified interval.
|
||||
* `mad_over_time(range-vector)`: the median absolute deviation of all points in the specified interval.
|
||||
* `last_over_time(range-vector)`: the most recent point value in the specified interval.
|
||||
* `present_over_time(range-vector)`: the value 1 for any series in the specified interval.
|
||||
|
||||
|
|
|
@ -609,6 +609,25 @@ func funcLastOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNod
|
|||
}), nil
|
||||
}
|
||||
|
||||
// === mad_over_time(Matrix parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcMadOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
if len(vals[0].(Matrix)[0].Floats) == 0 {
|
||||
return enh.Out, nil
|
||||
}
|
||||
return aggrOverTime(vals, enh, func(s Series) float64 {
|
||||
values := make(vectorByValueHeap, 0, len(s.Floats))
|
||||
for _, f := range s.Floats {
|
||||
values = append(values, Sample{F: f.F})
|
||||
}
|
||||
median := quantile(0.5, values)
|
||||
values = make(vectorByValueHeap, 0, len(s.Floats))
|
||||
for _, f := range s.Floats {
|
||||
values = append(values, Sample{F: math.Abs(f.F - median)})
|
||||
}
|
||||
return quantile(0.5, values)
|
||||
}), nil
|
||||
}
|
||||
|
||||
// === max_over_time(Matrix parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcMaxOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
if len(vals[0].(Matrix)[0].Floats) == 0 {
|
||||
|
@ -1538,6 +1557,7 @@ var FunctionCalls = map[string]FunctionCall{
|
|||
"log10": funcLog10,
|
||||
"log2": funcLog2,
|
||||
"last_over_time": funcLastOverTime,
|
||||
"mad_over_time": funcMadOverTime,
|
||||
"max_over_time": funcMaxOverTime,
|
||||
"min_over_time": funcMinOverTime,
|
||||
"minute": funcMinute,
|
||||
|
|
|
@ -15,6 +15,7 @@ package promql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -86,3 +87,52 @@ func TestKahanSum(t *testing.T) {
|
|||
expected := 2.0
|
||||
require.Equal(t, expected, kahanSum(vals))
|
||||
}
|
||||
|
||||
func TestMadOverTime(t *testing.T) {
|
||||
cases := []struct {
|
||||
series []int
|
||||
expectedRes float64
|
||||
}{
|
||||
{
|
||||
series: []int{4, 6, 2, 1, 999, 1, 2},
|
||||
expectedRes: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "float_series"
|
||||
|
||||
ts := int64(0)
|
||||
app := storage.Appender(context.Background())
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
var err error
|
||||
for _, num := range c.series {
|
||||
_, err = app.Append(0, lbls, ts, float64(num))
|
||||
require.NoError(t, err)
|
||||
ts += int64(1 * time.Minute / time.Millisecond)
|
||||
}
|
||||
require.NoError(t, app.Commit())
|
||||
|
||||
queryAndCheck := func(queryString string, exp Vector) {
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, exp, vector)
|
||||
}
|
||||
|
||||
queryString := fmt.Sprintf(`mad_over_time(%s[%dm])`, seriesName, len(c.series))
|
||||
queryAndCheck(queryString, []Sample{{T: ts, F: c.expectedRes, Metric: labels.EmptyLabels()}})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,6 +254,11 @@ var Functions = map[string]*Function{
|
|||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
ReturnType: ValueTypeVector,
|
||||
},
|
||||
"mad_over_time": {
|
||||
Name: "mad_over_time",
|
||||
ArgTypes: []ValueType{ValueTypeMatrix},
|
||||
ReturnType: ValueTypeVector,
|
||||
},
|
||||
"max_over_time": {
|
||||
Name: "max_over_time",
|
||||
ArgTypes: []ValueType{ValueTypeMatrix},
|
||||
|
|
|
@ -317,6 +317,12 @@ export const functionIdentifierTerms = [
|
|||
info: 'Calculate base-2 logarithm of input series',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'mad_over_time',
|
||||
detail: 'function',
|
||||
info: 'Return the median absolute deviation over time for input series',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'max_over_time',
|
||||
detail: 'function',
|
||||
|
|
|
@ -95,6 +95,11 @@ describe('promql operations', () => {
|
|||
expectedValueType: ValueType.vector,
|
||||
expectedDiag: [] as Diagnostic[],
|
||||
},
|
||||
{
|
||||
expr: 'mad_over_time(rate(metric_name[5m])[1h:] offset 1m)',
|
||||
expectedValueType: ValueType.vector,
|
||||
expectedDiag: [] as Diagnostic[],
|
||||
},
|
||||
{
|
||||
expr: 'max_over_time(rate(metric_name[5m])[1h:] offset 1m)',
|
||||
expectedValueType: ValueType.vector,
|
||||
|
|
|
@ -56,6 +56,7 @@ import {
|
|||
Ln,
|
||||
Log10,
|
||||
Log2,
|
||||
MadOverTime,
|
||||
MaxOverTime,
|
||||
MinOverTime,
|
||||
Minute,
|
||||
|
@ -370,6 +371,12 @@ const promqlFunctions: { [key: number]: PromQLFunction } = {
|
|||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[MadOverTime]: {
|
||||
name: 'mad_over_time',
|
||||
argTypes: [ValueType.matrix],
|
||||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[MaxOverTime]: {
|
||||
name: 'max_over_time',
|
||||
argTypes: [ValueType.matrix],
|
||||
|
|
|
@ -149,6 +149,7 @@ FunctionIdentifier {
|
|||
Ln |
|
||||
Log10 |
|
||||
Log2 |
|
||||
MadOverTime |
|
||||
MaxOverTime |
|
||||
MinOverTime |
|
||||
Minute |
|
||||
|
@ -380,6 +381,7 @@ NumberLiteral {
|
|||
Ln { condFn<"ln"> }
|
||||
Log10 { condFn<"log10"> }
|
||||
Log2 { condFn<"log2"> }
|
||||
MadOverTime { condFn<"mad_over_time"> }
|
||||
MaxOverTime { condFn<"max_over_time"> }
|
||||
MinOverTime { condFn<"min_over_time"> }
|
||||
Minute { condFn<"minute"> }
|
||||
|
|
Loading…
Reference in New Issue