From e2e243d1b6ac0d2d17df1b738407576b9a5e4724 Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:26:04 +0200 Subject: [PATCH] Elasticsearch: Fix processing of duplicated metric types and field (#66973) * Elasticsearch: Fix processing of duplicated metric types and field * Fix lint * Fix linting --- pkg/tsdb/elasticsearch/response_parser.go | 15 +++++- .../elasticsearch/response_parser_test.go | 48 +++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/pkg/tsdb/elasticsearch/response_parser.go b/pkg/tsdb/elasticsearch/response_parser.go index 4ffe2346977..fd32aef692d 100644 --- a/pkg/tsdb/elasticsearch/response_parser.go +++ b/pkg/tsdb/elasticsearch/response_parser.go @@ -1255,13 +1255,24 @@ func addOtherMetricsToFields(fields *[]*data.Field, bucket *simplejson.Json, met otherMetrics := make([]*MetricAgg, 0) for _, m := range target.Metrics { - if m.Type == metric.Type { + // To other metrics we add metric of the same type that are not the current metric + if m.ID != metric.ID && m.Type == metric.Type { otherMetrics = append(otherMetrics, m) } } - if len(otherMetrics) > 1 { + if len(otherMetrics) > 0 { metricName += " " + metric.Field + + // We check if we have metric with the same type and same field name + // If so, append metric.ID to the metric name + for _, m := range otherMetrics { + if m.Field == metric.Field { + metricName += " " + metric.ID + break + } + } + if metric.Type == "bucket_script" { // Use the formula in the column name metricName = metric.Settings.Get("script").MustString("") diff --git a/pkg/tsdb/elasticsearch/response_parser_test.go b/pkg/tsdb/elasticsearch/response_parser_test.go index 2b3bb0c345d..fb186ac1f64 100644 --- a/pkg/tsdb/elasticsearch/response_parser_test.go +++ b/pkg/tsdb/elasticsearch/response_parser_test.go @@ -124,6 +124,54 @@ func TestResponseParser(t *testing.T) { assert.Equal(t, frame.Fields[1].Config.DisplayNameFromDS, "Average value") }) + t.Run("Query with duplicated avg metric creates unique field name", func(t *testing.T) { + targets := map[string]string{ + "A": `{ + "metrics": [{"type": "avg", "field": "value", "id": "1" }, {"type": "avg", "field": "value", "id": "4" }], + "bucketAggs": [{ "type": "terms", "field": "label", "id": "3" }] + }`, + } + response := `{ + "responses": [ + { + "aggregations": { + "3": { + "buckets": [ + { + "1": { "value": 88 }, + "4": { "value": 88 }, + "doc_count": 10, + "key": "val1" + }, + { + "1": { "value": 99 }, + "4": { "value": 99 }, + "doc_count": 15, + "key": "val2" + } + ] + } + } + } + ] + }` + result, err := parseTestResponse(targets, response) + require.NoError(t, err) + require.Len(t, result.Responses, 1) + + queryRes := result.Responses["A"] + require.NotNil(t, queryRes) + dataframes := queryRes.Frames + require.NoError(t, err) + require.Len(t, dataframes, 1) + + frame := dataframes[0] + require.Len(t, frame.Fields, 3) + require.Equal(t, frame.Fields[0].Name, "label") + require.Equal(t, frame.Fields[1].Name, "Average value 1") + require.Equal(t, frame.Fields[2].Name, "Average value 4") + }) + t.Run("Single group by query one metric", func(t *testing.T) { targets := map[string]string{ "A": `{