diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index 0369ab0e9..f4025997b 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -3248,6 +3248,17 @@ func TestExecSuccess(t *testing.T) { resultExpected := []netstorage.Result{r} f(q, resultExpected) }) + t.Run(`range_over_time(time)`, func(t *testing.T) { + t.Parallel() + q := `range_over_time(alias(time()/100, "foobar")[3i])` + r := netstorage.Result{ + MetricName: metricNameExpected, + Values: []float64{4, 4, 4, 4, 4, 4}, + Timestamps: timestampsExpected, + } + resultExpected := []netstorage.Result{r} + f(q, resultExpected) + }) t.Run(`sum(multi-vector)`, func(t *testing.T) { t.Parallel() q := `sum(label_set(10, "foo", "bar") or label_set(time()/100, "baz", "sss"))` diff --git a/app/vmselect/promql/rollup.go b/app/vmselect/promql/rollup.go index 9bc1bf6c0..563f9dffe 100644 --- a/app/vmselect/promql/rollup.go +++ b/app/vmselect/promql/rollup.go @@ -15,8 +15,6 @@ import ( ) var rollupFuncs = map[string]newRollupFunc{ - "default_rollup": newRollupFuncOneArg(rollupDefault), // default rollup func - // Standard rollup funcs from PromQL. // See funcs accepting range-vector on https://prometheus.io/docs/prometheus/latest/querying/functions/ . "changes": newRollupFuncOneArg(rollupChanges), @@ -41,6 +39,8 @@ var rollupFuncs = map[string]newRollupFunc{ "absent_over_time": newRollupFuncOneArg(rollupAbsent), // Additional rollup funcs. + "default_rollup": newRollupFuncOneArg(rollupDefault), // default rollup func + "range_over_time": newRollupFuncOneArg(rollupRange), "sum2_over_time": newRollupFuncOneArg(rollupSum2), "geomean_over_time": newRollupFuncOneArg(rollupGeomean), "first_over_time": newRollupFuncOneArg(rollupFirst), @@ -91,6 +91,7 @@ var rollupAggrFuncs = map[string]rollupFunc{ "absent_over_time": rollupAbsent, // Additional rollup funcs. + "range_over_time": rollupRange, "sum2_over_time": rollupSum2, "geomean_over_time": rollupGeomean, "first_over_time": rollupFirst, @@ -1052,6 +1053,12 @@ func rollupSum(rfa *rollupFuncArg) float64 { return sum } +func rollupRange(rfa *rollupFuncArg) float64 { + max := rollupMax(rfa) + min := rollupMin(rfa) + return max - min +} + func rollupSum2(rfa *rollupFuncArg) float64 { // There is no need in handling NaNs here, since they must be cleaned up // before calling rollup funcs. diff --git a/app/vmselect/promql/rollup_test.go b/app/vmselect/promql/rollup_test.go index f93c917ab..3e506cea9 100644 --- a/app/vmselect/promql/rollup_test.go +++ b/app/vmselect/promql/rollup_test.go @@ -370,6 +370,7 @@ func TestRollupNewRollupFuncSuccess(t *testing.T) { f("irate", 0) f("rate", 2200) f("resets", 5) + f("range_over_time", 111) f("avg_over_time", 47.083333333333336) f("min_over_time", 12) f("max_over_time", 123) diff --git a/docs/ExtendedPromQL.md b/docs/ExtendedPromQL.md index b199e0a8e..f749b4095 100644 --- a/docs/ExtendedPromQL.md +++ b/docs/ExtendedPromQL.md @@ -66,6 +66,7 @@ This functionality can be tried at [an editable Grafana dashboard](http://play-g - `lifetime(q[d])` - returns lifetime of `q` over `d` in seconds. It is expected that `d` exceeds the lifetime of `q`. - `scrape_interval(q[d])` - returns the average interval in seconds between data points of `q` over `d` aka `scrape interval`. - Trigonometric functions - `sin(q)`, `cos(q)`, `asin(q)`, `acos(q)` and `pi()`. +- `range_over_time(m[d])` - returns value range for `m` over `d` time window, i.e. `max_over_time(m[d])-min_over_time(m[d])`. - `median_over_time(m[d])` - calculates median values for `m` over `d` time window. Shorthand to `quantile_over_time(0.5, m[d])`. - `median(q)` - median aggregate. Shorthand to `quantile(0.5, q)`. - `limitk(k, q)` - limits the number of time series returned from `q` to `k`. diff --git a/lib/metricsql/rollup.go b/lib/metricsql/rollup.go index 0100d9a02..dbfa223d1 100644 --- a/lib/metricsql/rollup.go +++ b/lib/metricsql/rollup.go @@ -30,6 +30,7 @@ var rollupFuncs = map[string]bool{ // Additional rollup funcs. "default_rollup": true, + "range_over_time": true, "sum2_over_time": true, "geomean_over_time": true, "first_over_time": true,