From 42601acfdeda9422d6941f29efddcdb84acc8dff Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Sat, 21 Feb 2015 17:45:47 +0100 Subject: [PATCH] Replace labelsToKey() with metric Fingerprint (fixes grouping bug). --- rules/ast/ast.go | 32 ++++------------------- rules/rules_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 27 deletions(-) diff --git a/rules/ast/ast.go b/rules/ast/ast.go index 8eae7359a..a3eb25788 100644 --- a/rules/ast/ast.go +++ b/rules/ast/ast.go @@ -19,7 +19,6 @@ import ( "fmt" "hash/fnv" "math" - "sort" "time" clientmodel "github.com/prometheus/client_golang/model" @@ -382,27 +381,6 @@ func (node *VectorAggregation) labelsToGroupingKey(labels clientmodel.Metric) ui return summer.Sum64() } -func labelsToKey(labels clientmodel.Metric) uint64 { - pairs := metric.LabelPairs{} - - for label, value := range labels { - pairs = append(pairs, &metric.LabelPair{ - Name: label, - Value: value, - }) - } - - sort.Sort(pairs) - - summer := fnv.New64a() - - for _, pair := range pairs { - fmt.Fprint(summer, pair.Name, pair.Value) - } - - return summer.Sum64() -} - // EvalVectorInstant evaluates a VectorNode with an instant query. func EvalVectorInstant(node VectorNode, timestamp clientmodel.Timestamp, storage local.Storage, queryStats *stats.TimerGroup) (Vector, error) { totalEvalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start() @@ -436,7 +414,7 @@ func EvalVectorRange(node VectorNode, start clientmodel.Timestamp, end clientmod defer closer.Close() evalTimer := queryStats.GetTimer(stats.InnerEvalTime).Start() - sampleStreams := map[uint64]*SampleStream{} + sampleStreams := map[clientmodel.Fingerprint]*SampleStream{} for t := start; !t.After(end); t = t.Add(interval) { if et := totalEvalTimer.ElapsedTime(); et > *queryTimeout { evalTimer.Stop() @@ -448,14 +426,14 @@ func EvalVectorRange(node VectorNode, start clientmodel.Timestamp, end clientmod Value: sample.Value, Timestamp: sample.Timestamp, } - groupingKey := labelsToKey(sample.Metric.Metric) - if sampleStreams[groupingKey] == nil { - sampleStreams[groupingKey] = &SampleStream{ + fp := sample.Metric.Metric.Fingerprint() + if sampleStreams[fp] == nil { + sampleStreams[fp] = &SampleStream{ Metric: sample.Metric, Values: metric.Values{samplePair}, } } else { - sampleStreams[groupingKey].Values = append(sampleStreams[groupingKey].Values, samplePair) + sampleStreams[fp].Values = append(sampleStreams[fp].Values, samplePair) } } } diff --git a/rules/rules_test.go b/rules/rules_test.go index 61f3b9c4e..d25cd2501 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -860,6 +860,70 @@ func TestRangedEvaluationRegressions(t *testing.T) { }, expr: "sum(testmetric) keeping_extra", }, + { + // Testing metric fingerprint grouping behavior. + in: ast.Matrix{ + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "testmetric", + "aa": "bb", + }, + }, + Values: metric.Values{ + { + Timestamp: testStartTime, + Value: 1, + }, + }, + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "testmetric", + "a": "abb", + }, + }, + Values: metric.Values{ + { + Timestamp: testStartTime, + Value: 2, + }, + }, + }, + }, + out: ast.Matrix{ + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "testmetric", + "aa": "bb", + }, + }, + Values: metric.Values{ + { + Timestamp: testStartTime, + Value: 1, + }, + }, + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "testmetric", + "a": "abb", + }, + }, + Values: metric.Values{ + { + Timestamp: testStartTime, + Value: 2, + }, + }, + }, + }, + expr: "testmetric", + }, } for i, s := range scenarios {