Skip to content

Commit fb31a6b

Browse files
perkerssensPer Kerssens
authored andcommitted
feat: Add support for cross-account metrics in CloudWatch Metrics (#2881)
Co-authored-by: Per Kerssens <[email protected]>
1 parent 38eb23b commit fb31a6b

File tree

5 files changed

+63
-8
lines changed

5 files changed

+63
-8
lines changed

athena-cloudwatch-metrics/athena-cloudwatch-metrics-package.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Parameters:
4040
Description: "(Optional) An IAM policy ARN to use as the PermissionsBoundary for the created Lambda function's execution role"
4141
Default: ''
4242
Type: String
43+
IncludeLinkedAccounts:
44+
Description: "If set to 'true', metrics from linked accounts will be included in the results."
45+
Default: 'false'
46+
Type: String
4347
Conditions:
4448
HasPermissionsBoundary: !Not [ !Equals [ !Ref PermissionsBoundaryARN, "" ] ]
4549
Resources:
@@ -51,6 +55,7 @@ Resources:
5155
disable_spill_encryption: !Ref DisableSpillEncryption
5256
spill_bucket: !Ref SpillBucket
5357
spill_prefix: !Ref SpillPrefix
58+
include_linked_accounts: !Ref IncludeLinkedAccounts
5459
FunctionName: !Ref AthenaCatalogName
5560
Handler: "com.amazonaws.athena.connectors.cloudwatch.metrics.MetricsCompositeHandler"
5661
CodeUri: "./target/athena-cloudwatch-metrics-2022.47.1.jar"

athena-cloudwatch-metrics/athena-cloudwatch-metrics.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Parameters:
4040
Description: "(Optional) An IAM policy ARN to use as the PermissionsBoundary for the created Lambda function's execution role"
4141
Default: ''
4242
Type: String
43+
IncludeLinkedAccounts:
44+
Description: "If set to 'true', metrics from linked accounts will be included in the results."
45+
Default: 'false'
46+
Type: String
4347
Conditions:
4448
HasPermissionsBoundary: !Not [ !Equals [ !Ref PermissionsBoundaryARN, "" ] ]
4549
IsRegionBAH: !Equals [!Ref "AWS::Region", "me-south-1"]
@@ -53,6 +57,7 @@ Resources:
5357
disable_spill_encryption: !Ref DisableSpillEncryption
5458
spill_bucket: !Ref SpillBucket
5559
spill_prefix: !Ref SpillPrefix
60+
include_linked_accounts: !Ref IncludeLinkedAccounts
5661
FunctionName: !Ref AthenaCatalogName
5762
PackageType: "Image"
5863
ImageUri: !Sub

athena-cloudwatch-metrics/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@
6262
<version>${log4j2Version}</version>
6363
<scope>runtime</scope>
6464
</dependency>
65+
<dependency>
66+
<groupId>org.junit-pioneer</groupId>
67+
<artifactId>junit-pioneer</artifactId>
68+
<version>2.3.0</version>
69+
<scope>test</scope>
70+
</dependency>
6571
</dependencies>
6672
<build>
6773
<plugins>

athena-cloudwatch-metrics/src/main/java/com/amazonaws/athena/connectors/cloudwatch/metrics/MetricUtils.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,22 @@ public class MetricUtils
5959
//this is a format required by Cloudwatch Metrics
6060
private static final String METRIC_ID = "m1";
6161

62+
// Environment variable to control cross-account metrics inclusion
63+
private static final String INCLUDE_LINKED_ACCOUNTS_ENV_VAR = "include_linked_accounts";
64+
6265
private MetricUtils() {}
6366

67+
/**
68+
* Checks if cross-account metrics should be included based on environment variable
69+
*
70+
* @return True if cross-account metrics should be included, false otherwise
71+
*/
72+
private static boolean shouldIncludeLinkedAccounts()
73+
{
74+
String includeLinkedAccounts = System.getenv(INCLUDE_LINKED_ACCOUNTS_ENV_VAR);
75+
return Boolean.parseBoolean(includeLinkedAccounts);
76+
}
77+
6478
/**
6579
* Filters metrics who have at least 1 metric dimension that matches DIMENSION_NAME_FIELD and DIMENSION_VALUE_FIELD filters.
6680
* This is just an optimization and isn't fully correct. We depend on the calling engine to apply full constraints. Also
@@ -104,6 +118,8 @@ protected static void pushDownPredicate(Constraints constraints, ListMetricsRequ
104118
{
105119
Map<String, ValueSet> summary = constraints.getSummary();
106120

121+
listMetricsRequest.includeLinkedAccounts(shouldIncludeLinkedAccounts());
122+
107123
ValueSet namespaceConstraint = summary.get(NAMESPACE_FIELD);
108124
if (namespaceConstraint != null && namespaceConstraint.isSingleValue()) {
109125
listMetricsRequest.namespace(namespaceConstraint.getSingleValue().toString());

athena-cloudwatch-metrics/src/test/java/com/amazonaws/athena/connectors/cloudwatch/metrics/MetricUtilsTest.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
* Licensed under the Apache License, Version 2.0 (the "License");
88
* you may not use this file except in compliance with the License.
99
* You may obtain a copy of the License at
10-
*
10+
*
1111
* http://www.apache.org/licenses/LICENSE-2.0
12-
*
12+
*
1313
* Unless required by applicable law or agreed to in writing, software
1414
* distributed under the License is distributed on an "AS IS" BASIS,
1515
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -34,9 +34,10 @@
3434
import org.apache.arrow.vector.types.pojo.Schema;
3535
import com.google.common.collect.ImmutableList;
3636
import org.apache.arrow.vector.types.Types;
37-
import org.junit.After;
38-
import org.junit.Before;
39-
import org.junit.Test;
37+
import org.junit.jupiter.api.AfterEach;
38+
import org.junit.jupiter.api.BeforeEach;
39+
import org.junit.jupiter.api.Test;
40+
import org.junitpioneer.jupiter.SetEnvironmentVariable;
4041
import software.amazon.awssdk.services.cloudwatch.model.Dimension;
4142
import software.amazon.awssdk.services.cloudwatch.model.DimensionFilter;
4243
import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest;
@@ -60,21 +61,21 @@
6061
import static com.amazonaws.athena.connectors.cloudwatch.metrics.tables.Table.STATISTIC_FIELD;
6162
import static com.amazonaws.athena.connectors.cloudwatch.metrics.tables.Table.TIMESTAMP_FIELD;
6263
import static com.amazonaws.athena.connector.lambda.domain.predicate.Constraints.DEFAULT_NO_LIMIT;
63-
import static org.junit.Assert.*;
64+
import static org.junit.jupiter.api.Assertions.*;
6465

6566
public class MetricUtilsTest
6667
{
6768
private FederatedIdentity identity = new FederatedIdentity("arn", "account", Collections.emptyMap(), Collections.emptyList(), Collections.emptyMap());
6869
private String catalog = "default";
6970
private BlockAllocator allocator;
7071

71-
@Before
72+
@BeforeEach
7273
public void setup()
7374
{
7475
allocator = new BlockAllocatorImpl();
7576
}
7677

77-
@After
78+
@AfterEach
7879
public void tearDown()
7980
{
8081
allocator.close();
@@ -137,6 +138,28 @@ public void pushDownPredicate()
137138
assertEquals(DimensionFilter.builder().name("match4").value("match5").build(), request.dimensions().get(0));
138139
}
139140

141+
@Test
142+
@SetEnvironmentVariable(key = "include_linked_accounts", value = "true")
143+
public void pushDownPredicateWithLinkedAccountsTrue() throws Exception
144+
{
145+
ListMetricsRequest.Builder requestBuilder = ListMetricsRequest.builder();
146+
MetricUtils.pushDownPredicate(new Constraints(new HashMap<>(), Collections.emptyList(), Collections.emptyList(), DEFAULT_NO_LIMIT, Collections.emptyMap(), null), requestBuilder);
147+
ListMetricsRequest request = requestBuilder.build();
148+
149+
assertTrue(request.includeLinkedAccounts());
150+
}
151+
152+
@Test
153+
@SetEnvironmentVariable(key = "include_linked_accounts", value = "false")
154+
public void pushDownPredicateWithLinkedAccountsFalse() throws Exception
155+
{
156+
ListMetricsRequest.Builder requestBuilder = ListMetricsRequest.builder();
157+
MetricUtils.pushDownPredicate(new Constraints(new HashMap<>(), Collections.emptyList(), Collections.emptyList(), DEFAULT_NO_LIMIT, Collections.emptyMap(), null), requestBuilder);
158+
ListMetricsRequest request = requestBuilder.build();
159+
160+
assertFalse(request.includeLinkedAccounts());
161+
}
162+
140163
@Test
141164
public void makeGetMetricDataRequest()
142165
{

0 commit comments

Comments
 (0)