Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CloudWatch: Cross-account querying support #59362

Merged
merged 45 commits into from Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
c926d4a
Lattice: Point to private prerelease of aws-sdk-go (#515)
sunker Sep 15, 2022
45c11ff
Lattice: Adding a feature toggle (#549)
sarahzinger Oct 4, 2022
b1b6270
Lattice: List accounts (#543)
sunker Oct 10, 2022
b33f728
point to version that includes metric api changes (#574)
sunker Oct 12, 2022
e086fc5
add accounts component (#575)
sunker Oct 17, 2022
4cbf6df
Test refactor: remove unneeded clientFactoryMock (#581)
fridgepoet Oct 18, 2022
28a48a7
Lattice: Add monitoring badge (#576)
sunker Oct 20, 2022
6b17f2e
solve conflict
sunker Oct 20, 2022
ce7ee23
Lattice: Add dynamic label for account display name (#579)
sunker Oct 21, 2022
ce75d0d
fix import
sunker Oct 25, 2022
9ec95e9
solve merge related problem
sunker Oct 27, 2022
f3a0828
add account info (#608)
sunker Oct 27, 2022
798bc58
add back namespaces handler
sunker Oct 27, 2022
b903846
Lattice: Parse account id and return it to frontend (#609)
sunker Oct 27, 2022
d0fb359
only show badge when feature toggle is enabled (#615)
sunker Oct 28, 2022
33a10bd
Lattice: Refactor resource response type and return account (#613)
sunker Oct 28, 2022
3411a5d
Lattice: Use account as input when listing metric names and dimension…
sunker Nov 1, 2022
6869664
rename request package (#626)
sunker Nov 2, 2022
ca512ae
Lattice: Move account component and add tooltip (#630)
sunker Nov 3, 2022
7972a16
CloudWatch: add account to GetMetricData queries (#627)
fridgepoet Nov 3, 2022
70e23a8
Lattice: Account variable support (#625)
sunker Nov 3, 2022
7eb1ade
cleanup (#629)
sunker Nov 3, 2022
75638c0
Set account Id according to crossAccountQuerying feature flag in back…
fridgepoet Nov 4, 2022
3be3932
CloudWatch: Change spelling of feature-toggle (#634)
fridgepoet Nov 7, 2022
0068846
Lattice Logs (#631)
sarahzinger Nov 9, 2022
01676f4
Lattice: Bug: fix dimension keys request (#644)
sunker Nov 10, 2022
10455a2
CloudWatch: Add tests for QueryData with AccountId (#637)
fridgepoet Nov 11, 2022
1fbdf64
Update from breaking change (#645)
sarahzinger Nov 11, 2022
9375ac5
CloudWatch: Add business logic layer for getting log groups (#642)
fridgepoet Nov 11, 2022
23308ef
Lattice: Fix - unset account id in region change handler (#646)
sunker Nov 13, 2022
524322e
Lattice: Add account id to metric stat query deep link (#656)
sunker Nov 21, 2022
f7e0885
CloudWatch: Add new log groups handler for cross-account querying (#643)
fridgepoet Nov 21, 2022
5930e9d
Lattice: Add feature tracking (#660)
sunker Nov 21, 2022
ede8a00
CloudWatch: Add route for DescribeLogGroups for cross-account queryin…
fridgepoet Nov 21, 2022
e14a31f
Lattice: Handle account id default value (#662)
sunker Nov 22, 2022
ca7caf2
Suggestions to lattice changes (#663)
fridgepoet Nov 22, 2022
c144bc1
Resolve conflicts
fridgepoet Nov 22, 2022
707447a
Add Latest SDK (#672)
sarahzinger Nov 23, 2022
2d193b8
add tooltip (#674)
sunker Nov 23, 2022
d0b4092
Docs: Add documentation for CloudWatch cross account querying (#676)
sunker Nov 24, 2022
c322054
use latest version of the aws-sdk-go
sunker Nov 28, 2022
2dcd140
Merge branch 'main' into cloudwatch/cross-account-observability
fridgepoet Nov 28, 2022
eef1fca
Fix tests' mock response type
fridgepoet Nov 28, 2022
e90b086
Merge remote-tracking branch 'origin/main' into cloudwatch/cross-acco…
fridgepoet Nov 28, 2022
840b28f
Remove change in Azure Monitor
fridgepoet Nov 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions .betterer.results
Expand Up @@ -5373,8 +5373,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/plugins/datasource/cloudwatch/components/QueryHeader.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/datasource.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
Expand Down
15 changes: 15 additions & 0 deletions docs/sources/datasources/aws-cloudwatch/_index.md
Expand Up @@ -168,6 +168,21 @@ You can attach these permissions to the IAM role or IAM user you configured in [
}
```

**Cross-account observability:**

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["oam:ListSinks", "oam:ListAttachedLinks"],
"Effect": "Allow",
"Resource": "*"
}
]
}
```

### Configure CloudWatch settings

#### Namespaces of Custom Metrics
Expand Down
27 changes: 27 additions & 0 deletions docs/sources/datasources/aws-cloudwatch/query-editor/index.md
Expand Up @@ -214,6 +214,33 @@ When making `stats` queries in [Explore]({{< relref "../../../explore/" >}}), ma

{{< figure src="/static/img/docs/v70/explore-mode-switcher.png" max-width="500px" class="docs-image--right" caption="Explore mode switcher" >}}

## Cross-account observability

The CloudWatch plugin provides the ability to monitor and troubleshoot applications that span across multiple accounts within a region. Using cross-account observability, you can seamlessly search, visualize and analyze metrics and logs, without having to worry about account boundaries.

> **Note:** This feature is currently behind the `cloudWatchCrossAccountQuerying` feature toggle.

> You can enable feature toggles through configuration file or environment variables. See configuration [docs]({{< relref "../setup-grafana/configure-grafana/#feature_toggles" >}}) for details.
> Grafana Cloud users can access this feature by [opening a support ticket in the Cloud Portal](https://grafana.com/profile/org#support).

### Getting started

To enable cross-account observability, first enable it in CloudWatch using the official [CloudWatch docs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html), then add [two new API actions]({{< relref "../#cross-account-observability" >}}) to the IAM policy attached to the role/user running the plugin.

Cross-account querying is available in the plugin through the `Logs` mode and the `Metric search` mode. Once you have it configured correctly, you'll see a "Monitoring account" badge displayed in the query editor header.

{{< figure src="/static/img/docs/cloudwatch/cloudwatch-monitoring-badge-9.3.0.png" max-width="1200px" caption="Monitoring account badge" >}}

### Metrics editor

When you select the `Builder` mode within the Metric search editor, a new Account field displays. Use the Account field to specify which of the linked accounts to target for the given query. By default, the `All` option is specified, which will target all linked accounts.

While in `Code` mode, you can specify any math expression. If the Monitoring account badge displays in the query editor header, all `SEARCH` expressions entered in this field will be cross-account by default. You can limit the search to one or a set of accounts, as documented in the [AWS documentation](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html).

### Logs editor

The Log group selector allows you to specify what log groups to target in the logs query. If the Monitoring account badge is displayed in the query editor header, it is possible to search and select log groups across multiple accounts. You can use the Account field in the Log Group Selector to filter Log Groups by Account. If you have many log groups and do not see the log group you'd like to select in the selector, use the prefix search to narrow down the possible log groups.

### Deep-link Grafana panels to the CloudWatch console

{{< figure src="/static/img/docs/v70/cloudwatch-logs-deep-linking.png" max-width="500px" class="docs-image--right" caption="CloudWatch Logs deep linking" >}}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Expand Up @@ -29,7 +29,7 @@ require (
github.com/BurntSushi/toml v1.1.0
github.com/Masterminds/semver v1.5.0
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f
github.com/aws/aws-sdk-go v1.44.109
github.com/aws/aws-sdk-go v1.44.146
github.com/beevik/etree v1.1.0
github.com/benbjohnson/clock v1.3.0
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
Expand Down Expand Up @@ -108,7 +108,7 @@ require (
go.opentelemetry.io/otel/trace v1.7.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0
golang.org/x/sync v0.1.0
golang.org/x/time v0.0.0-20220609170525-579cf78fd858
Expand Down Expand Up @@ -230,7 +230,7 @@ require (
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.12 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.0
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
13 changes: 8 additions & 5 deletions go.sum
Expand Up @@ -373,8 +373,9 @@ github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2z
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.44.109 h1:+Na5JPeS0kiEHoBp5Umcuuf+IDqXqD0lXnM920E31YI=
github.com/aws/aws-sdk-go v1.44.109/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.44.146 h1:7YdGgPxDPRJu/yYffzZp/H7yHzQ6AqmuNFZPYraaN8I=
github.com/aws/aws-sdk-go v1.44.146/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4=
github.com/aws/aws-sdk-go-v2 v1.16.2 h1:fqlCk6Iy3bnCumtrLz9r3mJ/2gUT0pJ0wLFVIdWh+JA=
Expand Down Expand Up @@ -2865,8 +2866,8 @@ golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -3087,14 +3088,16 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
1 change: 1 addition & 0 deletions packages/grafana-data/src/types/featureToggles.gen.ts
Expand Up @@ -68,6 +68,7 @@ export interface FeatureToggles {
objectStore?: boolean;
traceqlEditor?: boolean;
flameGraph?: boolean;
cloudWatchCrossAccountQuerying?: boolean;
redshiftAsyncQueryDataSupport?: boolean;
athenaAsyncQueryDataSupport?: boolean;
increaseInMemDatabaseQueryCache?: boolean;
Expand Down
5 changes: 5 additions & 0 deletions pkg/services/featuremgmt/registry.go
Expand Up @@ -295,6 +295,11 @@ var (
Description: "Show the flame graph",
State: FeatureStateAlpha,
},
{
Name: "cloudWatchCrossAccountQuerying",
Description: "Use cross-account querying in CloudWatch datasource",
State: FeatureStateAlpha,
},
{
Name: "redshiftAsyncQueryDataSupport",
Description: "Enable async query data support for Redshift",
Expand Down
4 changes: 4 additions & 0 deletions pkg/services/featuremgmt/toggles_gen.go
Expand Up @@ -215,6 +215,10 @@ const (
// Show the flame graph
FlagFlameGraph = "flameGraph"

// FlagCloudWatchCrossAccountQuerying
// Use cross-account querying in CloudWatch datasource
FlagCloudWatchCrossAccountQuerying = "cloudWatchCrossAccountQuerying"

// FlagRedshiftAsyncQueryDataSupport
// Enable async query data support for Redshift
FlagRedshiftAsyncQueryDataSupport = "redshiftAsyncQueryDataSupport"
Expand Down
13 changes: 9 additions & 4 deletions pkg/tsdb/cloudwatch/clients/metrics.go
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
)

type metricsClient struct {
Expand All @@ -17,16 +18,20 @@ func NewMetricsClient(api models.CloudWatchMetricsAPIProvider, config *setting.C
return &metricsClient{CloudWatchMetricsAPIProvider: api, config: config}
}

func (l *metricsClient) ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]*cloudwatch.Metric, error) {
var cloudWatchMetrics []*cloudwatch.Metric
func (l *metricsClient) ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) {
var cloudWatchMetrics []resources.MetricResponse
pageNum := 0
err := l.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
pageNum++
metrics.MAwsCloudWatchListMetrics.Inc()
metrics, err := awsutil.ValuesAtPath(page, "Metrics")
if err == nil {
for _, metric := range metrics {
cloudWatchMetrics = append(cloudWatchMetrics, metric.(*cloudwatch.Metric))
for idx, metric := range metrics {
metric := resources.MetricResponse{Metric: metric.(*cloudwatch.Metric)}
if len(page.OwningAccounts) >= idx && params.IncludeLinkedAccounts != nil && *params.IncludeLinkedAccounts {
metric.AccountId = page.OwningAccounts[idx]
}
cloudWatchMetrics = append(cloudWatchMetrics, metric)
}
}
return !lastPage && pageNum < l.config.AWSListMetricsPageLimit
Expand Down
30 changes: 30 additions & 0 deletions pkg/tsdb/cloudwatch/clients/metrics_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -46,4 +47,33 @@ func TestMetricsClient(t *testing.T) {

assert.Equal(t, len(metrics), len(response))
})

t.Run("Should return account id in case IncludeLinkedAccounts is set to true", func(t *testing.T) {
fakeApi := &mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{
{MetricName: aws.String("Test_MetricName1")},
{MetricName: aws.String("Test_MetricName2")},
{MetricName: aws.String("Test_MetricName3")},
}, 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)})
require.NoError(t, err)
expected := []resources.MetricResponse{
{Metric: &cloudwatch.Metric{MetricName: aws.String("Test_MetricName1")}, AccountId: stringPtr("1234567890")},
{Metric: &cloudwatch.Metric{MetricName: aws.String("Test_MetricName2")}, AccountId: stringPtr("1234567890")},
{Metric: &cloudwatch.Metric{MetricName: aws.String("Test_MetricName3")}, AccountId: stringPtr("1234567895")},
}
assert.Equal(t, expected, response)
})

t.Run("Should not return account id in case IncludeLinkedAccounts is set to false", func(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)})
require.NoError(t, err)
assert.Nil(t, response[0].AccountId)
})
}

func stringPtr(s string) *string { return &s }
29 changes: 23 additions & 6 deletions pkg/tsdb/cloudwatch/cloudwatch.go
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"regexp"
"time"

Expand All @@ -18,6 +17,7 @@ import (
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/aws/aws-sdk-go/service/oam"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
Expand All @@ -26,7 +26,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana-plugin-sdk-go/data"

"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/featuremgmt"
Expand Down Expand Up @@ -122,8 +121,11 @@ func (e *cloudWatchExecutor) getRequestContext(pluginCtx backend.PluginContext,
return models.RequestContext{}, err
}
return models.RequestContext{
OAMClientProvider: NewOAMAPI(sess),
MetricsClientProvider: clients.NewMetricsClient(NewMetricsAPI(sess), e.cfg),
LogsAPIProvider: NewLogsAPI(sess),
Settings: instance.Settings,
Features: e.features,
}, nil
}

Expand Down Expand Up @@ -178,11 +180,12 @@ func (e *cloudWatchExecutor) checkHealthMetrics(pluginCtx backend.PluginContext)
}

func (e *cloudWatchExecutor) checkHealthLogs(pluginCtx backend.PluginContext) error {
parameters := url.Values{
"limit": []string{"1"},
session, err := e.newSession(pluginCtx, defaultRegion)
if err != nil {
return err
}

_, err := e.handleGetLogGroups(pluginCtx, parameters)
logsClient := NewLogsAPI(session)
_, err = logsClient.DescribeLogGroups(&cloudwatchlogs.DescribeLogGroupsInput{Limit: aws.Int64(1)})
return err
}

Expand Down Expand Up @@ -423,6 +426,20 @@ var NewMetricsAPI = func(sess *session.Session) models.CloudWatchMetricsAPIProvi
return cloudwatch.New(sess)
}

// NewLogsAPI is a CloudWatch logs api factory.
//
// Stubbable by tests.
var NewLogsAPI = func(sess *session.Session) models.CloudWatchLogsAPIProvider {
return cloudwatchlogs.New(sess)
}

// NewOAMAPI is a CloudWatch OAM api factory.
//
// Stubbable by tests.
var NewOAMAPI = func(sess *session.Session) models.OAMClientProvider {
return oam.New(sess)
}

// NewCWClient is a CloudWatch client factory.
//
// Stubbable by tests.
Expand Down