diff --git a/app/vmselect/promql/aggr.go b/app/vmselect/promql/aggr.go index 458061959f..ba908e6b89 100644 --- a/app/vmselect/promql/aggr.go +++ b/app/vmselect/promql/aggr.go @@ -1010,6 +1010,11 @@ func aggrFuncLimitK(afa *aggrFuncArg) ([]*timeseries, error) { } } afe := func(tss []*timeseries, modifier *metricsql.ModifierExpr) []*timeseries { + // Sort series by metricName in order to get consistent set of output series + // across multiple calls to limitk() function. + sort.Slice(tss, func(i, j int) bool { + return metricNameLess(&tss[i].MetricName, &tss[j].MetricName) + }) if len(tss) > maxK { tss = tss[:maxK] } diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index 6c7df0b1a5..a90dd7f7bb 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -5003,7 +5003,7 @@ func TestExecSuccess(t *testing.T) { }) t.Run(`limitk(1)`, func(t *testing.T) { t.Parallel() - q := `limitk(1, label_set(10, "foo", "bar") or label_set(time()/150, "baz", "sss"))` + q := `limitk(1, label_set(10, "foo", "bar") or label_set(time()/150, "xbaz", "sss"))` r1 := netstorage.Result{ MetricName: metricNameExpected, Values: []float64{10, 10, 10, 10, 10, 10}, diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 73447c7cbf..f494b30ffd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,7 +6,9 @@ sort: 15 ## tip -BUGFIX: vmstorage: fix `unaligned 64-bit atomic operation` panic on 32-bit architectures (arm and 386). The panic has been introduced in v1.67.0 +* FEATURE: consistently return the same set of time series from [limitk](https://docs.victoriametrics.com/MetricsQL.html#limitk) function. This improves the usability of periodically refreshed graphs. + +* BUGFIX: vmstorage: fix `unaligned 64-bit atomic operation` panic on 32-bit architectures (arm and 386). The panic has been introduced in v1.67.0 ## [v1.67.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.67.0) diff --git a/docs/MetricsQL.md b/docs/MetricsQL.md index e700f951c8..2700443dbd 100644 --- a/docs/MetricsQL.md +++ b/docs/MetricsQL.md @@ -762,7 +762,7 @@ See also [implicit query conversions](#implicit-query-conversions). #### limitk -`limitk(k, q) by (group_labels)` returns up to `k` time series per each `group_labels` out of time series returned by `q`. The returned set of time series can change with each call. +`limitk(k, q) by (group_labels)` returns up to `k` time series per each `group_labels` out of time series returned by `q`. The returned set of time series remain the same across calls. #### mad