From a18224d02dedec50ff5ce0a3e76e114e20817b94 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Sun, 17 Oct 2021 11:46:38 +0200 Subject: [PATCH] make aggregations deterministic (#9459) * Add deterministic test for aggregations Signed-off-by: Julien Pivotto * Make aggregations deterministic Signed-off-by: Julien Pivotto * Increase testing Signed-off-by: Julien Pivotto --- promql/engine.go | 9 +++++++-- promql/testdata/aggregators.test | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/promql/engine.go b/promql/engine.go index 5d530f34a..bd3d836a3 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -2138,6 +2138,7 @@ type groupedAggregation struct { func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without bool, param interface{}, vec Vector, seriesHelper []EvalSeriesHelper, enh *EvalNodeHelper) Vector { result := map[uint64]*groupedAggregation{} + orderedResult := []*groupedAggregation{} var k int64 if op == parser.TOPK || op == parser.BOTTOMK { f := param.(float64) @@ -2206,12 +2207,16 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without } else { m = metric.WithLabels(grouping...) } - result[groupingKey] = &groupedAggregation{ + newAgg := &groupedAggregation{ labels: m, value: s.V, mean: s.V, groupCount: 1, } + + result[groupingKey] = newAgg + orderedResult = append(orderedResult, newAgg) + inputVecLen := int64(len(vec)) resultSize := k if k > inputVecLen { @@ -2333,7 +2338,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without } // Construct the result Vector from the aggregated groups. - for _, aggr := range result { + for _, aggr := range orderedResult { switch op { case parser.AVG: aggr.value = aggr.mean diff --git a/promql/testdata/aggregators.test b/promql/testdata/aggregators.test index cda2e7f4e..aaf731f35 100644 --- a/promql/testdata/aggregators.test +++ b/promql/testdata/aggregators.test @@ -497,3 +497,13 @@ eval instant at 1m avg(data{test="-big"}) eval instant at 1m avg(data{test="bigzero"}) {} 0 + +clear + +# Test that aggregations are deterministic. +load 10s + up{job="prometheus"} 1 + up{job="prometheus2"} 1 + +eval instant at 1m count(topk(1,max(up) without()) == topk(1,max(up) without()) == topk(1,max(up) without()) == topk(1,max(up) without()) == topk(1,max(up) without())) + {} 1