diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index cb11dd470..d645bcc2c 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -3986,6 +3986,28 @@ func TestExecSuccess(t *testing.T) { resultExpected := []netstorage.Result{r} f(q, resultExpected) }) + t.Run(`count_gt_over_time`, func(t *testing.T) { + t.Parallel() + q := `count_gt_over_time(rand(0)[200s:10s], 0.7)` + r := netstorage.Result{ + MetricName: metricNameExpected, + Values: []float64{7, 6, 10, 6, 6, 5}, + Timestamps: timestampsExpected, + } + resultExpected := []netstorage.Result{r} + f(q, resultExpected) + }) + t.Run(`count_le_over_time`, func(t *testing.T) { + t.Parallel() + q := `count_le_over_time(rand(0)[200s:10s], 0.7)` + r := netstorage.Result{ + MetricName: metricNameExpected, + Values: []float64{13, 14, 10, 14, 14, 15}, + Timestamps: timestampsExpected, + } + resultExpected := []netstorage.Result{r} + f(q, resultExpected) + }) t.Run(`increases_over_time`, func(t *testing.T) { t.Parallel() q := `increases_over_time(rand(0)[200s:10s])` @@ -6006,6 +6028,10 @@ func TestExecError(t *testing.T) { f(`prometheus_buckets()`) f(`buckets_limit()`) f(`buckets_limit(1)`) + f(`share_le_over_time()`) + f(`share_gt_over_time()`) + f(`count_le_over_time()`) + f(`count_gt_over_time()`) // Invalid argument type f(`median_over_time({}, 2)`) diff --git a/app/vmselect/promql/rollup.go b/app/vmselect/promql/rollup.go index 851b76de4..77f8792a7 100644 --- a/app/vmselect/promql/rollup.go +++ b/app/vmselect/promql/rollup.go @@ -62,6 +62,8 @@ var rollupFuncs = map[string]newRollupFunc{ "tmax_over_time": newRollupFuncOneArg(rollupTmax), "share_le_over_time": newRollupShareLE, "share_gt_over_time": newRollupShareGT, + "count_le_over_time": newRollupCountLE, + "count_gt_over_time": newRollupCountGT, "histogram_over_time": newRollupFuncOneArg(rollupHistogram), "rollup": newRollupFuncOneArg(rollupFake), "rollup_rate": newRollupFuncOneArg(rollupFake), // + rollupFuncsRemoveCounterResets @@ -834,6 +836,25 @@ func countFilterGT(values []float64, gt float64) int { } func newRollupShareFilter(args []interface{}, countFilter func(values []float64, limit float64) int) (rollupFunc, error) { + rf, err := newRollupCountFilter(args, countFilter) + if err != nil { + return nil, err + } + return func(rfa *rollupFuncArg) float64 { + n := rf(rfa) + return n / float64(len(rfa.values)) + }, nil +} + +func newRollupCountLE(args []interface{}) (rollupFunc, error) { + return newRollupCountFilter(args, countFilterLE) +} + +func newRollupCountGT(args []interface{}) (rollupFunc, error) { + return newRollupCountFilter(args, countFilterGT) +} + +func newRollupCountFilter(args []interface{}, countFilter func(values []float64, limit float64) int) (rollupFunc, error) { if err := expectRollupArgsNum(args, 2); err != nil { return nil, err } @@ -849,8 +870,7 @@ func newRollupShareFilter(args []interface{}, countFilter func(values []float64, return nan } limit := limits[rfa.idx] - n := countFilter(values, limit) - return float64(n) / float64(len(values)) + return float64(countFilter(values, limit)) } return rf, nil } diff --git a/app/vmselect/promql/rollup_test.go b/app/vmselect/promql/rollup_test.go index 074305aca..4bb596a2e 100644 --- a/app/vmselect/promql/rollup_test.go +++ b/app/vmselect/promql/rollup_test.go @@ -239,6 +239,52 @@ func TestRollupShareGTOverTime(t *testing.T) { f(1000, 0) } +func TestRollupCountLEOverTime(t *testing.T) { + f := func(le, vExpected float64) { + t.Helper() + les := []*timeseries{{ + Values: []float64{le}, + Timestamps: []int64{123}, + }} + var me metricsql.MetricExpr + args := []interface{}{&metricsql.RollupExpr{Expr: &me}, les} + testRollupFunc(t, "count_le_over_time", args, &me, vExpected) + } + + f(-123, 0) + f(0, 0) + f(10, 0) + f(12, 1) + f(30, 2) + f(50, 9) + f(100, 11) + f(123, 12) + f(1000, 12) +} + +func TestRollupCountGTOverTime(t *testing.T) { + f := func(gt, vExpected float64) { + t.Helper() + gts := []*timeseries{{ + Values: []float64{gt}, + Timestamps: []int64{123}, + }} + var me metricsql.MetricExpr + args := []interface{}{&metricsql.RollupExpr{Expr: &me}, gts} + testRollupFunc(t, "count_gt_over_time", args, &me, vExpected) + } + + f(-123, 12) + f(0, 12) + f(10, 12) + f(12, 11) + f(30, 10) + f(50, 3) + f(100, 1) + f(123, 0) + f(1000, 0) +} + func TestRollupQuantileOverTime(t *testing.T) { f := func(phi, vExpected float64) { t.Helper() diff --git a/docs/MetricsQL.md b/docs/MetricsQL.md index ede664554..1b5c93317 100644 --- a/docs/MetricsQL.md +++ b/docs/MetricsQL.md @@ -115,6 +115,8 @@ This functionality can be tried at [an editable Grafana dashboard](http://play-g Example: `share_le_over_time(memory_usage_bytes[24h], 100*1024*1024)` returns the share of time series values for the last 24 hours when memory usage was below or equal to 100MB. - `share_gt_over_time(m[d], gt)` - returns share (in the range 0..1) of values in `m` over `d`, which are bigger than `gt`. Useful for calculating SLI and SLO. Example: `share_gt_over_time(up[24h], 0)` - returns service availability for the last 24 hours. +- `count_le_over_time(m[d], le)` - returns the number of raw samples for `m` over `d`, which don't exceed `le`. +- `count_gt_over_time(m[d], gt)` - returns the number of raw samples for `m` over `d`, which are bigger than `gt`. - `tmin_over_time(m[d])` - returns timestamp for the minimum value for `m` over `d` time range. - `tmax_over_time(m[d])` - returns timestamp for the maximum value for `m` over `d` time range. - `aggr_over_time(("aggr_func1", "aggr_func2", ...), m[d])` - simultaneously calculates all the listed `aggr_func*` for `m` over `d` time range. diff --git a/go.mod b/go.mod index a74d3a997..44004f217 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( // like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b github.com/VictoriaMetrics/fasthttp v1.0.5 github.com/VictoriaMetrics/metrics v1.12.3 - github.com/VictoriaMetrics/metricsql v0.4.2 + github.com/VictoriaMetrics/metricsql v0.4.3 github.com/aws/aws-sdk-go v1.34.14 github.com/cespare/xxhash/v2 v2.1.1 github.com/golang/snappy v0.0.1 diff --git a/go.sum b/go.sum index 22fc1761c..f7e60a188 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/VictoriaMetrics/metrics v1.12.2 h1:SG8iAmqavDNuh7GIdHPoGHUhDL23KeKfvS github.com/VictoriaMetrics/metrics v1.12.2/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE= github.com/VictoriaMetrics/metrics v1.12.3 h1:Fe6JHC6MSEKa+BtLhPN8WIvS+HKPzMc2evEpNeCGy7I= github.com/VictoriaMetrics/metrics v1.12.3/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE= -github.com/VictoriaMetrics/metricsql v0.4.2 h1:cLrPMK0IASCglRwHBwMAW+ooxG77vxlEkYheVc7gtqs= -github.com/VictoriaMetrics/metricsql v0.4.2/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8= +github.com/VictoriaMetrics/metricsql v0.4.3 h1:4lezcOTMeGOfGtrf+I2YEC98lkx4nRczTiLrL+6E3CE= +github.com/VictoriaMetrics/metricsql v0.4.3/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= diff --git a/vendor/github.com/VictoriaMetrics/metricsql/rollup.go b/vendor/github.com/VictoriaMetrics/metricsql/rollup.go index 7d9a75cbd..283f08c3e 100644 --- a/vendor/github.com/VictoriaMetrics/metricsql/rollup.go +++ b/vendor/github.com/VictoriaMetrics/metricsql/rollup.go @@ -47,6 +47,8 @@ var rollupFuncs = map[string]bool{ "tmax_over_time": true, "share_le_over_time": true, "share_gt_over_time": true, + "count_le_over_time": true, + "count_gt_over_time": true, "histogram_over_time": true, "rollup": true, "rollup_rate": true, diff --git a/vendor/modules.txt b/vendor/modules.txt index 244bfca60..f60906505 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -16,7 +16,7 @@ github.com/VictoriaMetrics/fasthttp/fasthttputil github.com/VictoriaMetrics/fasthttp/stackless # github.com/VictoriaMetrics/metrics v1.12.3 github.com/VictoriaMetrics/metrics -# github.com/VictoriaMetrics/metricsql v0.4.2 +# github.com/VictoriaMetrics/metricsql v0.4.3 github.com/VictoriaMetrics/metricsql github.com/VictoriaMetrics/metricsql/binaryop # github.com/aws/aws-sdk-go v1.34.14