From 8f96d23eee17436b3f0273cb909106a6c297ffea Mon Sep 17 00:00:00 2001 From: Shabeeb Khalid Date: Mon, 23 Oct 2023 17:17:06 +0300 Subject: [PATCH] CloudWatch: Use context in aws ListMetricsPages (#76938) Use context in aws ListMetricsPages Use ListMetricsPagesWithContext and pass context in related sub calls --- pkg/tsdb/cloudwatch/clients/metrics.go | 6 +++-- pkg/tsdb/cloudwatch/clients/metrics_test.go | 10 ++++---- pkg/tsdb/cloudwatch/cloudwatch.go | 2 +- .../get_dimension_values_for_wildcards.go | 5 ++-- ...get_dimension_values_for_wildcards_test.go | 24 ++++++++++--------- .../cloudwatch/mocks/cloudwatch_metric_api.go | 4 ++-- .../cloudwatch/mocks/list_metrics_service.go | 8 ++++--- pkg/tsdb/cloudwatch/mocks/metrics_client.go | 4 +++- pkg/tsdb/cloudwatch/models/api.go | 10 ++++---- pkg/tsdb/cloudwatch/routes/dimension_keys.go | 2 +- .../cloudwatch/routes/dimension_values.go | 2 +- pkg/tsdb/cloudwatch/routes/metrics.go | 2 +- pkg/tsdb/cloudwatch/services/list_metrics.go | 13 +++++----- .../cloudwatch/services/list_metrics_test.go | 9 +++---- pkg/tsdb/cloudwatch/test_utils.go | 2 +- pkg/tsdb/cloudwatch/time_series_query.go | 2 +- pkg/tsdb/cloudwatch/time_series_query_test.go | 2 +- 17 files changed, 60 insertions(+), 47 deletions(-) diff --git a/pkg/tsdb/cloudwatch/clients/metrics.go b/pkg/tsdb/cloudwatch/clients/metrics.go index f5f53ffd95e..05456f3cf8a 100644 --- a/pkg/tsdb/cloudwatch/clients/metrics.go +++ b/pkg/tsdb/cloudwatch/clients/metrics.go @@ -1,6 +1,8 @@ package clients import ( + "context" + "github.com/aws/aws-sdk-go/aws/awsutil" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/grafana/grafana/pkg/infra/metrics" @@ -19,10 +21,10 @@ func NewMetricsClient(api models.CloudWatchMetricsAPIProvider, config *setting.C return &metricsClient{CloudWatchMetricsAPIProvider: api, config: config} } -func (l *metricsClient) ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) { +func (l *metricsClient) ListMetricsWithPageLimit(ctx context.Context, params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) { var cloudWatchMetrics []resources.MetricResponse pageNum := 0 - err := l.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { + err := l.ListMetricsPagesWithContext(ctx, params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { pageNum++ metrics.MAwsCloudWatchListMetrics.Inc() metrics, err := awsutil.ValuesAtPath(page, "Metrics") diff --git a/pkg/tsdb/cloudwatch/clients/metrics_test.go b/pkg/tsdb/cloudwatch/clients/metrics_test.go index 0a28e34c5a2..4dd455b65b7 100644 --- a/pkg/tsdb/cloudwatch/clients/metrics_test.go +++ b/pkg/tsdb/cloudwatch/clients/metrics_test.go @@ -1,6 +1,7 @@ package clients import ( + "context" "testing" "github.com/aws/aws-sdk-go/aws" @@ -25,12 +26,13 @@ func TestMetricsClient(t *testing.T) { {MetricName: aws.String("Test_MetricName9")}, {MetricName: aws.String("Test_MetricName10")}, } + ctx := context.Background() t.Run("List Metrics and page limit is reached", func(t *testing.T) { pageLimit := 3 fakeApi := &mocks.FakeMetricsAPI{Metrics: metrics, MetricsPerPage: 2} client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}) - response, err := client.ListMetricsWithPageLimit(&cloudwatch.ListMetricsInput{}) + response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{}) require.NoError(t, err) expectedMetrics := fakeApi.MetricsPerPage * pageLimit @@ -42,7 +44,7 @@ func TestMetricsClient(t *testing.T) { fakeApi := &mocks.FakeMetricsAPI{Metrics: metrics} client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}) - response, err := client.ListMetricsWithPageLimit(&cloudwatch.ListMetricsInput{}) + response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{}) require.NoError(t, err) assert.Equal(t, len(metrics), len(response)) @@ -56,7 +58,7 @@ func TestMetricsClient(t *testing.T) { }, OwningAccounts: []*string{aws.String("1234567890"), aws.String("1234567890"), aws.String("1234567895")}} client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: 100}) - response, err := client.ListMetricsWithPageLimit(&cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(true)}) + response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(true)}) require.NoError(t, err) expected := []resources.MetricResponse{ {Metric: &cloudwatch.Metric{MetricName: aws.String("Test_MetricName1")}, AccountId: stringPtr("1234567890")}, @@ -70,7 +72,7 @@ func TestMetricsClient(t *testing.T) { fakeApi := &mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{{MetricName: aws.String("Test_MetricName1")}}, OwningAccounts: []*string{aws.String("1234567890")}} client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: 100}) - response, err := client.ListMetricsWithPageLimit(&cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(false)}) + response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(false)}) require.NoError(t, err) assert.Nil(t, response[0].AccountId) }) diff --git a/pkg/tsdb/cloudwatch/cloudwatch.go b/pkg/tsdb/cloudwatch/cloudwatch.go index cd3fb5c501f..2807d7372cd 100644 --- a/pkg/tsdb/cloudwatch/cloudwatch.go +++ b/pkg/tsdb/cloudwatch/cloudwatch.go @@ -226,7 +226,7 @@ func (e *cloudWatchExecutor) checkHealthMetrics(ctx context.Context, pluginCtx b return err } metricClient := clients.NewMetricsClient(NewMetricsAPI(session), e.cfg) - _, err = metricClient.ListMetricsWithPageLimit(params) + _, err = metricClient.ListMetricsWithPageLimit(ctx, params) return err } diff --git a/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards.go b/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards.go index 9dd58d43d87..ab1a6158106 100644 --- a/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards.go +++ b/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards.go @@ -1,6 +1,7 @@ package cloudwatch import ( + "context" "fmt" "github.com/grafana/grafana-plugin-sdk-go/backend" @@ -13,7 +14,7 @@ import ( ) // getDimensionValues gets the actual dimension values for dimensions with a wildcard -func (e *cloudWatchExecutor) getDimensionValuesForWildcards(pluginCtx backend.PluginContext, region string, +func (e *cloudWatchExecutor) getDimensionValuesForWildcards(ctx context.Context, pluginCtx backend.PluginContext, region string, client models.CloudWatchMetricsAPIProvider, origQueries []*models.CloudWatchQuery, tagValueCache *cache.Cache, logger log.Logger) ([]*models.CloudWatchQuery, error) { metricsClient := clients.NewMetricsClient(client, e.cfg) service := services.NewListMetricsService(metricsClient) @@ -50,7 +51,7 @@ func (e *cloudWatchExecutor) getDimensionValuesForWildcards(pluginCtx backend.Pl DimensionKey: dimensionKey, } - dimensions, err := service.GetDimensionValuesByDimensionFilter(request) + dimensions, err := service.GetDimensionValuesByDimensionFilter(ctx, request) if err != nil { return nil, err } diff --git a/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards_test.go b/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards_test.go index efb3cdedee6..e0951515152 100644 --- a/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards_test.go +++ b/pkg/tsdb/cloudwatch/get_dimension_values_for_wildcards_test.go @@ -1,6 +1,7 @@ package cloudwatch import ( + "context" "testing" "time" @@ -17,6 +18,7 @@ import ( func TestGetDimensionValuesForWildcards(t *testing.T) { logger := &logtest.Fake{} executor := &cloudWatchExecutor{} + ctx := context.Background() pluginCtx := backend.PluginContext{ DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ID: 1, Updated: time.Now()}, } @@ -26,7 +28,7 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { query := getBaseQuery() query.MetricName = "Test_MetricName1" query.Dimensions = map[string][]string{"Test_DimensionName1": {"Value1"}} - queries, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) + queries, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) assert.NotNil(t, queries[0].Dimensions["Test_DimensionName1"], 1) @@ -37,7 +39,7 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { query := getBaseQuery() query.MetricName = "Test_MetricName1" query.Dimensions = map[string][]string{"Test_DimensionName1": {"*"}} - queries, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) + queries, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) assert.NotNil(t, queries[0].Dimensions["Test_DimensionName1"]) @@ -55,8 +57,8 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { {MetricName: utils.Pointer("Test_MetricName3"), Dimensions: []*cloudwatch.Dimension{{Name: utils.Pointer("Test_DimensionName1"), Value: utils.Pointer("Value4")}}}, {MetricName: utils.Pointer("Test_MetricName4"), Dimensions: []*cloudwatch.Dimension{{Name: utils.Pointer("Test_DimensionName1"), Value: utils.Pointer("Value2")}}}, }} - api.On("ListMetricsPages").Return(nil) - queries, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) + api.On("ListMetricsPagesWithContext").Return(nil) + queries, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) assert.Equal(t, map[string][]string{"Test_DimensionName1": {"Value1", "Value2", "Value3", "Value4"}}, queries[0].Dimensions) @@ -71,14 +73,14 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { api := &mocks.MetricsAPI{Metrics: []*cloudwatch.Metric{ {MetricName: utils.Pointer("Test_MetricName"), Dimensions: []*cloudwatch.Dimension{{Name: utils.Pointer("Test_DimensionName"), Value: utils.Pointer("Value")}}}, }} - api.On("ListMetricsPages").Return(nil) - _, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) + api.On("ListMetricsPagesWithContext").Return(nil) + _, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) // make sure the original query wasn't altered assert.Equal(t, map[string][]string{"Test_DimensionName": {"*"}}, query.Dimensions) //setting the api to nil confirms that it's using the cached value - queries, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) + queries, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", nil, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) assert.Equal(t, map[string][]string{"Test_DimensionName": {"Value"}}, queries[0].Dimensions) @@ -91,8 +93,8 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { query.Dimensions = map[string][]string{"Test_DimensionName2": {"*"}} query.MatchExact = false api := &mocks.MetricsAPI{Metrics: []*cloudwatch.Metric{}} - api.On("ListMetricsPages").Return(nil) - queries, err := executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) + api.On("ListMetricsPagesWithContext").Return(nil) + queries, err := executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) // assert that the values was set to an empty array @@ -102,8 +104,8 @@ func TestGetDimensionValuesForWildcards(t *testing.T) { api.Metrics = []*cloudwatch.Metric{ {MetricName: utils.Pointer("Test_MetricName"), Dimensions: []*cloudwatch.Dimension{{Name: utils.Pointer("Test_DimensionName2"), Value: utils.Pointer("Value")}}}, } - api.On("ListMetricsPages").Return(nil) - queries, err = executor.getDimensionValuesForWildcards(pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) + api.On("ListMetricsPagesWithContext").Return(nil) + queries, err = executor.getDimensionValuesForWildcards(ctx, pluginCtx, "us-east-1", api, []*models.CloudWatchQuery{query}, tagValueCache, logger) assert.Nil(t, err) assert.Len(t, queries, 1) assert.Equal(t, map[string][]string{"Test_DimensionName2": {"Value"}}, queries[0].Dimensions) diff --git a/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go b/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go index 1f827a1ac94..cdb1aeca82f 100644 --- a/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go +++ b/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go @@ -14,7 +14,7 @@ type FakeMetricsAPI struct { MetricsPerPage int } -func (c *FakeMetricsAPI) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error { +func (c *FakeMetricsAPI) ListMetricsPagesWithContext(ctx aws.Context, input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool, opts ...request.Option) error { if c.MetricsPerPage == 0 { c.MetricsPerPage = 1000 } @@ -62,7 +62,7 @@ func (m *MetricsAPI) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch return args.Get(0).(*cloudwatch.GetMetricDataOutput), args.Error(1) } -func (m *MetricsAPI) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error { +func (m *MetricsAPI) ListMetricsPagesWithContext(ctx aws.Context, input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool, opts ...request.Option) error { fn(&cloudwatch.ListMetricsOutput{ Metrics: m.Metrics, }, true) diff --git a/pkg/tsdb/cloudwatch/mocks/list_metrics_service.go b/pkg/tsdb/cloudwatch/mocks/list_metrics_service.go index 8c9fb73f697..223dd27ace8 100644 --- a/pkg/tsdb/cloudwatch/mocks/list_metrics_service.go +++ b/pkg/tsdb/cloudwatch/mocks/list_metrics_service.go @@ -1,6 +1,8 @@ package mocks import ( + "context" + "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/stretchr/testify/mock" ) @@ -9,19 +11,19 @@ type ListMetricsServiceMock struct { mock.Mock } -func (a *ListMetricsServiceMock) GetDimensionKeysByDimensionFilter(r resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) { +func (a *ListMetricsServiceMock) GetDimensionKeysByDimensionFilter(ctx context.Context, r resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) { args := a.Called(r) return args.Get(0).([]resources.ResourceResponse[string]), args.Error(1) } -func (a *ListMetricsServiceMock) GetDimensionValuesByDimensionFilter(r resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) { +func (a *ListMetricsServiceMock) GetDimensionValuesByDimensionFilter(ctx context.Context, r resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) { args := a.Called(r) return args.Get(0).([]resources.ResourceResponse[string]), args.Error(1) } -func (a *ListMetricsServiceMock) GetMetricsByNamespace(r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) { +func (a *ListMetricsServiceMock) GetMetricsByNamespace(ctx context.Context, r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) { args := a.Called(r) return args.Get(0).([]resources.ResourceResponse[resources.Metric]), args.Error(1) diff --git a/pkg/tsdb/cloudwatch/mocks/metrics_client.go b/pkg/tsdb/cloudwatch/mocks/metrics_client.go index 057389ba71e..44ab1fbcb5b 100644 --- a/pkg/tsdb/cloudwatch/mocks/metrics_client.go +++ b/pkg/tsdb/cloudwatch/mocks/metrics_client.go @@ -1,6 +1,8 @@ package mocks import ( + "context" + "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/stretchr/testify/mock" @@ -10,7 +12,7 @@ type FakeMetricsClient struct { mock.Mock } -func (m *FakeMetricsClient) ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) { +func (m *FakeMetricsClient) ListMetricsWithPageLimit(ctx context.Context, params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) { args := m.Called(params) return args.Get(0).([]resources.MetricResponse), args.Error(1) } diff --git a/pkg/tsdb/cloudwatch/models/api.go b/pkg/tsdb/cloudwatch/models/api.go index ace24bedf97..329ae338822 100644 --- a/pkg/tsdb/cloudwatch/models/api.go +++ b/pkg/tsdb/cloudwatch/models/api.go @@ -31,9 +31,9 @@ type RequestContext struct { // Services type ListMetricsProvider interface { - GetDimensionKeysByDimensionFilter(resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) - GetDimensionValuesByDimensionFilter(resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) - GetMetricsByNamespace(r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) + GetDimensionKeysByDimensionFilter(ctx context.Context, r resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) + GetDimensionValuesByDimensionFilter(ctx context.Context, r resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) + GetMetricsByNamespace(ctx context.Context, r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) } type LogGroupsProvider interface { @@ -51,12 +51,12 @@ type RegionsAPIProvider interface { // Clients type MetricsClientProvider interface { - ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) + ListMetricsWithPageLimit(ctx context.Context, params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) } // APIs - instead of using the API defined in the services within the aws-sdk-go directly, specify a subset of the API with methods that are actually used in a service or a client type CloudWatchMetricsAPIProvider interface { - ListMetricsPages(*cloudwatch.ListMetricsInput, func(*cloudwatch.ListMetricsOutput, bool) bool) error + ListMetricsPagesWithContext(ctx context.Context, in *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool, opts ...request.Option) error } type CloudWatchLogsAPIProvider interface { diff --git a/pkg/tsdb/cloudwatch/routes/dimension_keys.go b/pkg/tsdb/cloudwatch/routes/dimension_keys.go index f22f85c65c3..1e8e581e920 100644 --- a/pkg/tsdb/cloudwatch/routes/dimension_keys.go +++ b/pkg/tsdb/cloudwatch/routes/dimension_keys.go @@ -26,7 +26,7 @@ func DimensionKeysHandler(ctx context.Context, pluginCtx backend.PluginContext, var response []resources.ResourceResponse[string] switch dimensionKeysRequest.Type() { case resources.FilterDimensionKeysRequest: - response, err = service.GetDimensionKeysByDimensionFilter(dimensionKeysRequest) + response, err = service.GetDimensionKeysByDimensionFilter(ctx, dimensionKeysRequest) default: response, err = services.GetHardCodedDimensionKeysByNamespace(dimensionKeysRequest.Namespace) } diff --git a/pkg/tsdb/cloudwatch/routes/dimension_values.go b/pkg/tsdb/cloudwatch/routes/dimension_values.go index d4be586c013..c949b4a5f48 100644 --- a/pkg/tsdb/cloudwatch/routes/dimension_values.go +++ b/pkg/tsdb/cloudwatch/routes/dimension_values.go @@ -22,7 +22,7 @@ func DimensionValuesHandler(ctx context.Context, pluginCtx backend.PluginContext return nil, models.NewHttpError("error in DimensionValuesHandler", http.StatusInternalServerError, err) } - response, err := service.GetDimensionValuesByDimensionFilter(dimensionValuesRequest) + response, err := service.GetDimensionValuesByDimensionFilter(ctx, dimensionValuesRequest) if err != nil { return nil, models.NewHttpError("error in DimensionValuesHandler", http.StatusInternalServerError, err) } diff --git a/pkg/tsdb/cloudwatch/routes/metrics.go b/pkg/tsdb/cloudwatch/routes/metrics.go index 94c3cdcd841..6adf5d2794e 100644 --- a/pkg/tsdb/cloudwatch/routes/metrics.go +++ b/pkg/tsdb/cloudwatch/routes/metrics.go @@ -30,7 +30,7 @@ func MetricsHandler(ctx context.Context, pluginCtx backend.PluginContext, reqCtx case resources.MetricsByNamespaceRequestType: response, err = services.GetHardCodedMetricsByNamespace(metricsRequest.Namespace) case resources.CustomNamespaceRequestType: - response, err = service.GetMetricsByNamespace(metricsRequest) + response, err = service.GetMetricsByNamespace(ctx, metricsRequest) } if err != nil { return nil, models.NewHttpError("error in MetricsHandler", http.StatusInternalServerError, err) diff --git a/pkg/tsdb/cloudwatch/services/list_metrics.go b/pkg/tsdb/cloudwatch/services/list_metrics.go index f4f66914dfe..3f6088ce32b 100644 --- a/pkg/tsdb/cloudwatch/services/list_metrics.go +++ b/pkg/tsdb/cloudwatch/services/list_metrics.go @@ -1,6 +1,7 @@ package services import ( + "context" "fmt" "sort" @@ -18,7 +19,7 @@ func NewListMetricsService(metricsClient models.MetricsClientProvider) models.Li return &ListMetricsService{metricsClient} } -func (l *ListMetricsService) GetDimensionKeysByDimensionFilter(r resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) { +func (l *ListMetricsService) GetDimensionKeysByDimensionFilter(ctx context.Context, r resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error) { input := &cloudwatch.ListMetricsInput{} if r.Namespace != "" { input.Namespace = aws.String(r.Namespace) @@ -29,7 +30,7 @@ func (l *ListMetricsService) GetDimensionKeysByDimensionFilter(r resources.Dimen setDimensionFilter(input, r.DimensionFilter) setAccount(input, r.ResourceRequest) - metrics, err := l.ListMetricsWithPageLimit(input) + metrics, err := l.ListMetricsWithPageLimit(ctx, input) if err != nil { return nil, fmt.Errorf("%v: %w", "unable to call AWS API", err) } @@ -64,7 +65,7 @@ func (l *ListMetricsService) GetDimensionKeysByDimensionFilter(r resources.Dimen return response, nil } -func (l *ListMetricsService) GetDimensionValuesByDimensionFilter(r resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) { +func (l *ListMetricsService) GetDimensionValuesByDimensionFilter(ctx context.Context, r resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error) { input := &cloudwatch.ListMetricsInput{ Namespace: aws.String(r.Namespace), MetricName: aws.String(r.MetricName), @@ -72,7 +73,7 @@ func (l *ListMetricsService) GetDimensionValuesByDimensionFilter(r resources.Dim setDimensionFilter(input, r.DimensionFilter) setAccount(input, r.ResourceRequest) - metrics, err := l.ListMetricsWithPageLimit(input) + metrics, err := l.ListMetricsWithPageLimit(ctx, input) if err != nil { return nil, fmt.Errorf("%v: %w", "unable to call AWS API", err) } @@ -98,10 +99,10 @@ func (l *ListMetricsService) GetDimensionValuesByDimensionFilter(r resources.Dim return response, nil } -func (l *ListMetricsService) GetMetricsByNamespace(r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) { +func (l *ListMetricsService) GetMetricsByNamespace(ctx context.Context, r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error) { input := &cloudwatch.ListMetricsInput{Namespace: aws.String(r.Namespace)} setAccount(input, r.ResourceRequest) - metrics, err := l.ListMetricsWithPageLimit(input) + metrics, err := l.ListMetricsWithPageLimit(ctx, input) if err != nil { return nil, err } diff --git a/pkg/tsdb/cloudwatch/services/list_metrics_test.go b/pkg/tsdb/cloudwatch/services/list_metrics_test.go index 8d63baabcbf..7f832878443 100644 --- a/pkg/tsdb/cloudwatch/services/list_metrics_test.go +++ b/pkg/tsdb/cloudwatch/services/list_metrics_test.go @@ -1,6 +1,7 @@ package services import ( + "context" "testing" "github.com/aws/aws-sdk-go/aws" @@ -62,7 +63,7 @@ func TestListMetricsService_GetDimensionKeysByDimensionFilter(t *testing.T) { fakeMetricsClient.On("ListMetricsWithPageLimit", mock.Anything).Return(metricResponse, nil) listMetricsService := NewListMetricsService(fakeMetricsClient) - resp, err := listMetricsService.GetDimensionKeysByDimensionFilter(resources.DimensionKeysRequest{ + resp, err := listMetricsService.GetDimensionKeysByDimensionFilter(context.Background(), resources.DimensionKeysRequest{ ResourceRequest: &resources.ResourceRequest{Region: "us-east-1"}, Namespace: "AWS/EC2", MetricName: "CPUUtilization", @@ -122,7 +123,7 @@ func TestListMetricsService_GetDimensionKeysByDimensionFilter(t *testing.T) { fakeMetricsClient := &mocks.FakeMetricsClient{} fakeMetricsClient.On("ListMetricsWithPageLimit", mock.Anything).Return(metricResponse, nil) listMetricsService := NewListMetricsService(fakeMetricsClient) - res, err := listMetricsService.GetDimensionKeysByDimensionFilter(tc.input) + res, err := listMetricsService.GetDimensionKeysByDimensionFilter(context.Background(), tc.input) require.NoError(t, err) require.NotEmpty(t, res) fakeMetricsClient.AssertCalled(t, "ListMetricsWithPageLimit", tc.listMetricsWithPageLimitInput) @@ -136,7 +137,7 @@ func TestListMetricsService_GetDimensionValuesByDimensionFilter(t *testing.T) { fakeMetricsClient.On("ListMetricsWithPageLimit", mock.Anything).Return(metricResponse, nil) listMetricsService := NewListMetricsService(fakeMetricsClient) - resp, err := listMetricsService.GetDimensionValuesByDimensionFilter(resources.DimensionValuesRequest{ + resp, err := listMetricsService.GetDimensionValuesByDimensionFilter(context.Background(), resources.DimensionValuesRequest{ ResourceRequest: &resources.ResourceRequest{Region: "us-east-1"}, Namespace: "AWS/EC2", MetricName: "CPUUtilization", @@ -189,7 +190,7 @@ func TestListMetricsService_GetDimensionValuesByDimensionFilter(t *testing.T) { fakeMetricsClient := &mocks.FakeMetricsClient{} fakeMetricsClient.On("ListMetricsWithPageLimit", mock.Anything).Return(metricResponse, nil) listMetricsService := NewListMetricsService(fakeMetricsClient) - res, err := listMetricsService.GetDimensionValuesByDimensionFilter(tc.input) + res, err := listMetricsService.GetDimensionValuesByDimensionFilter(context.Background(), tc.input) require.NoError(t, err) require.Empty(t, res) fakeMetricsClient.AssertCalled(t, "ListMetricsWithPageLimit", tc.listMetricsWithPageLimitInput) diff --git a/pkg/tsdb/cloudwatch/test_utils.go b/pkg/tsdb/cloudwatch/test_utils.go index aac2434f7ac..7a22b351470 100644 --- a/pkg/tsdb/cloudwatch/test_utils.go +++ b/pkg/tsdb/cloudwatch/test_utils.go @@ -200,7 +200,7 @@ type fakeCheckHealthClient struct { describeLogGroups func(input *cloudwatchlogs.DescribeLogGroupsInput) (*cloudwatchlogs.DescribeLogGroupsOutput, error) } -func (c fakeCheckHealthClient) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error { +func (c fakeCheckHealthClient) ListMetricsPagesWithContext(ctx aws.Context, input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool, opts ...request.Option) error { if c.listMetricsPages != nil { return c.listMetricsPages(input, fn) } diff --git a/pkg/tsdb/cloudwatch/time_series_query.go b/pkg/tsdb/cloudwatch/time_series_query.go index 12a27205e53..96f7bbd1880 100644 --- a/pkg/tsdb/cloudwatch/time_series_query.go +++ b/pkg/tsdb/cloudwatch/time_series_query.go @@ -96,7 +96,7 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, logger } if e.features.IsEnabled(featuremgmt.FlagCloudWatchWildCardDimensionValues) { - requestQueries, err = e.getDimensionValuesForWildcards(req.PluginContext, region, client, requestQueries, instance.tagValueCache, logger) + requestQueries, err = e.getDimensionValuesForWildcards(ctx, req.PluginContext, region, client, requestQueries, instance.tagValueCache, logger) if err != nil { return err } diff --git a/pkg/tsdb/cloudwatch/time_series_query_test.go b/pkg/tsdb/cloudwatch/time_series_query_test.go index e18b660f706..81032778e4f 100644 --- a/pkg/tsdb/cloudwatch/time_series_query_test.go +++ b/pkg/tsdb/cloudwatch/time_series_query_test.go @@ -419,7 +419,7 @@ func Test_QueryData_response_data_frame_name_is_always_response_label(t *testing api := mocks.MetricsAPI{Metrics: []*cloudwatch.Metric{ {MetricName: aws.String(""), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("InstanceId"), Value: aws.String("i-00645d91ed77d87ac")}}}, }} - api.On("ListMetricsPages").Return(nil) + api.On("ListMetricsPagesWithContext").Return(nil) NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI { return &api