From 20aac7f04ba29744a21618725783c46b81978c91 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 17 Jan 2020 11:18:28 +0100 Subject: [PATCH] CloudWatch: Display partial result in graph when max DP/call limit is reached (#21533) * Return data and warning in case dp limit is reached * Change warning text --- pkg/tsdb/cloudwatch/query_transformer.go | 7 +++++++ pkg/tsdb/cloudwatch/response_parser.go | 13 ++++++++----- pkg/tsdb/cloudwatch/response_parser_test.go | 2 +- pkg/tsdb/cloudwatch/types.go | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/tsdb/cloudwatch/query_transformer.go b/pkg/tsdb/cloudwatch/query_transformer.go index f4e215a504a..c71e6d40444 100644 --- a/pkg/tsdb/cloudwatch/query_transformer.go +++ b/pkg/tsdb/cloudwatch/query_transformer.go @@ -71,6 +71,7 @@ func (e *CloudWatchExecutor) transformQueryResponseToQueryResult(cloudwatchRespo timeSeries := make(tsdb.TimeSeriesSlice, 0) requestExceededMaxLimit := false + partialData := false queryMeta := []struct { Expression, ID string }{} @@ -78,6 +79,7 @@ func (e *CloudWatchExecutor) transformQueryResponseToQueryResult(cloudwatchRespo for _, response := range responses { timeSeries = append(timeSeries, *response.series...) requestExceededMaxLimit = requestExceededMaxLimit || response.RequestExceededMaxLimit + partialData = partialData || response.PartialData queryMeta = append(queryMeta, struct { Expression, ID string }{ @@ -93,6 +95,11 @@ func (e *CloudWatchExecutor) transformQueryResponseToQueryResult(cloudwatchRespo if requestExceededMaxLimit { queryResult.ErrorString = "Cloudwatch GetMetricData error: Maximum number of allowed metrics exceeded. Your search may have been limited." } + + if partialData { + queryResult.ErrorString = "Cloudwatch GetMetricData error: Too many datapoints requested - your search have been limited. Please try to reduce the time range" + } + queryResult.Series = append(queryResult.Series, timeSeries...) queryResult.Meta.Set("gmdMeta", queryMeta) results[refID] = queryResult diff --git a/pkg/tsdb/cloudwatch/response_parser.go b/pkg/tsdb/cloudwatch/response_parser.go index 3be09c3e7e3..78b5c16c3f1 100644 --- a/pkg/tsdb/cloudwatch/response_parser.go +++ b/pkg/tsdb/cloudwatch/response_parser.go @@ -42,7 +42,7 @@ func (e *CloudWatchExecutor) parseResponse(metricDataOutputs []*cloudwatch.GetMe cloudWatchResponses := make([]*cloudwatchResponse, 0) for id, lr := range mdr { response := &cloudwatchResponse{} - series, err := parseGetMetricDataTimeSeries(lr, queries[id]) + series, partialData, err := parseGetMetricDataTimeSeries(lr, queries[id]) if err != nil { return cloudWatchResponses, err } @@ -52,6 +52,7 @@ func (e *CloudWatchExecutor) parseResponse(metricDataOutputs []*cloudwatch.GetMe response.RefId = queries[id].RefId response.Id = queries[id].Id response.RequestExceededMaxLimit = queries[id].RequestExceededMaxLimit + response.PartialData = partialData cloudWatchResponses = append(cloudWatchResponses, response) } @@ -59,16 +60,18 @@ func (e *CloudWatchExecutor) parseResponse(metricDataOutputs []*cloudwatch.GetMe return cloudWatchResponses, nil } -func parseGetMetricDataTimeSeries(metricDataResults map[string]*cloudwatch.MetricDataResult, query *cloudWatchQuery) (*tsdb.TimeSeriesSlice, error) { +func parseGetMetricDataTimeSeries(metricDataResults map[string]*cloudwatch.MetricDataResult, query *cloudWatchQuery) (*tsdb.TimeSeriesSlice, bool, error) { result := tsdb.TimeSeriesSlice{} + partialData := false for label, metricDataResult := range metricDataResults { if *metricDataResult.StatusCode != "Complete" { - return nil, fmt.Errorf("too many datapoints requested in query %s. Please try to reduce the time range", query.RefId) + // return nil, fmt.Errorf("too many datapoints requested in query %s. Please try to reduce the time range", query.RefId) + partialData = true } for _, message := range metricDataResult.Messages { if *message.Code == "ArithmeticError" { - return nil, fmt.Errorf("ArithmeticError in query %s: %s", query.RefId, *message.Value) + return nil, false, fmt.Errorf("ArithmeticError in query %s: %s", query.RefId, *message.Value) } } @@ -102,7 +105,7 @@ func parseGetMetricDataTimeSeries(metricDataResults map[string]*cloudwatch.Metri } result = append(result, &series) } - return &result, nil + return &result, partialData, nil } func formatAlias(query *cloudWatchQuery, stat string, dimensions map[string]string, label string) string { diff --git a/pkg/tsdb/cloudwatch/response_parser_test.go b/pkg/tsdb/cloudwatch/response_parser_test.go index e5921f1dce5..512ad1d13ff 100644 --- a/pkg/tsdb/cloudwatch/response_parser_test.go +++ b/pkg/tsdb/cloudwatch/response_parser_test.go @@ -46,7 +46,7 @@ func TestCloudWatchResponseParser(t *testing.T) { Period: 60, Alias: "{{namespace}}_{{metric}}_{{stat}}", } - series, err := parseGetMetricDataTimeSeries(resp, query) + series, _, err := parseGetMetricDataTimeSeries(resp, query) timeSeries := (*series)[0] So(err, ShouldBeNil) diff --git a/pkg/tsdb/cloudwatch/types.go b/pkg/tsdb/cloudwatch/types.go index eafda265e14..c287a75fabc 100644 --- a/pkg/tsdb/cloudwatch/types.go +++ b/pkg/tsdb/cloudwatch/types.go @@ -36,6 +36,7 @@ type cloudwatchResponse struct { RefId string Expression string RequestExceededMaxLimit bool + PartialData bool } type queryError struct {