From b398bc592b1128a8d649ecf48bcf329fa2e23c05 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 17 Jan 2020 12:47:40 +0100 Subject: [PATCH] CloudWatch: Multi-valued template variable dimension alias fix (#21541) * Match dimension value with label substring * Add unit tests --- pkg/tsdb/cloudwatch/response_parser.go | 2 +- pkg/tsdb/cloudwatch/response_parser_test.go | 166 ++++++++++++++++++++ 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/pkg/tsdb/cloudwatch/response_parser.go b/pkg/tsdb/cloudwatch/response_parser.go index 78b5c16c3f1..0c69740702c 100644 --- a/pkg/tsdb/cloudwatch/response_parser.go +++ b/pkg/tsdb/cloudwatch/response_parser.go @@ -85,7 +85,7 @@ func parseGetMetricDataTimeSeries(metricDataResults map[string]*cloudwatch.Metri series.Tags[key] = values[0] } else { for _, value := range values { - if value == label || value == "*" { + if value == label || value == "*" || strings.Contains(label, value) { series.Tags[key] = label } } diff --git a/pkg/tsdb/cloudwatch/response_parser_test.go b/pkg/tsdb/cloudwatch/response_parser_test.go index 512ad1d13ff..4367a3a36be 100644 --- a/pkg/tsdb/cloudwatch/response_parser_test.go +++ b/pkg/tsdb/cloudwatch/response_parser_test.go @@ -12,6 +12,172 @@ import ( func TestCloudWatchResponseParser(t *testing.T) { Convey("TestCloudWatchResponseParser", t, func() { + Convey("can expand dimension value using exact match", func() { + timestamp := time.Unix(0, 0) + resp := map[string]*cloudwatch.MetricDataResult{ + "lb1": { + Id: aws.String("id1"), + Label: aws.String("lb1"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + "lb2": { + Id: aws.String("id2"), + Label: aws.String("lb2"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + } + + query := &cloudWatchQuery{ + RefId: "refId1", + Region: "us-east-1", + Namespace: "AWS/ApplicationELB", + MetricName: "TargetResponseTime", + Dimensions: map[string][]string{ + "LoadBalancer": {"lb2"}, + "TargetGroup": {"tg"}, + }, + Stats: "Average", + Period: 60, + Alias: "{{LoadBalancer}} Expanded", + } + series, err := parseGetMetricDataTimeSeries(resp, query) + timeSeries := (*series)[0] + + So(err, ShouldBeNil) + So(timeSeries.Name, ShouldEqual, "lb2 Expanded") + So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb2") + }) + + Convey("can expand dimension value using substring", func() { + timestamp := time.Unix(0, 0) + resp := map[string]*cloudwatch.MetricDataResult{ + "lb1 Sum": { + Id: aws.String("id1"), + Label: aws.String("lb1 Sum"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + "lb2 Average": { + Id: aws.String("id2"), + Label: aws.String("lb2 Average"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + } + + query := &cloudWatchQuery{ + RefId: "refId1", + Region: "us-east-1", + Namespace: "AWS/ApplicationELB", + MetricName: "TargetResponseTime", + Dimensions: map[string][]string{ + "LoadBalancer": {"lb1"}, + "TargetGroup": {"tg"}, + }, + Stats: "Average", + Period: 60, + Alias: "{{LoadBalancer}} Expanded", + } + series, err := parseGetMetricDataTimeSeries(resp, query) + timeSeries := (*series)[0] + + So(err, ShouldBeNil) + So(timeSeries.Name, ShouldEqual, "lb1 Expanded") + So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb1") + }) + + Convey("can expand dimension value using wildcard", func() { + timestamp := time.Unix(0, 0) + resp := map[string]*cloudwatch.MetricDataResult{ + "lb3": { + Id: aws.String("lb3"), + Label: aws.String("lb3"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + "lb4": { + Id: aws.String("lb4"), + Label: aws.String("lb4"), + Timestamps: []*time.Time{ + aws.Time(timestamp), + aws.Time(timestamp.Add(60 * time.Second)), + aws.Time(timestamp.Add(180 * time.Second)), + }, + Values: []*float64{ + aws.Float64(10), + aws.Float64(20), + aws.Float64(30), + }, + StatusCode: aws.String("Complete"), + }, + } + + query := &cloudWatchQuery{ + RefId: "refId1", + Region: "us-east-1", + Namespace: "AWS/ApplicationELB", + MetricName: "TargetResponseTime", + Dimensions: map[string][]string{ + "LoadBalancer": {"*"}, + "TargetGroup": {"tg"}, + }, + Stats: "Average", + Period: 60, + Alias: "{{LoadBalancer}} Expanded", + } + series, err := parseGetMetricDataTimeSeries(resp, query) + + So(err, ShouldBeNil) + So((*series)[0].Name, ShouldEqual, "lb3 Expanded") + So((*series)[1].Name, ShouldEqual, "lb4 Expanded") + }) Convey("can parse cloudwatch response", func() { timestamp := time.Unix(0, 0)