cloudwatch: Explicitly set region and accountId fields are removed from metrics when they match the stack #28731
Description
Describe the bug
In my dashboard created from the CDK, I noticed that the region
property was missing from metrics when that metric matched the stack. For example, for a stack in us-east-1, the metrics would look like this:
[
{
"label": "My metric [us-west-2]",
"region": "us-west-2",
"period": 60,
"stat": "Maximum"
},
{
"label": "My metric [us-east-1]",
"period": 60,
"stat": "Maximum"
},
// ...
]
This broke some region-based filtering logic in my UI application.
Expected Behavior
I expected the region
field to exist for all of my metrics, since I was setting it explicitly:
new Metric({
label: `My metric [${region}]`,
region: region,
period: 60,
stat: 'Maximum'
})
Current Behavior
During serialization, the region
and accountId
fields are removed if they match the corresponding region
and account
values on the stack.
Reproduction Steps
You can confirm the behavior by adding this unit test to cross-environment.test.ts
:
test('metric with explicit account and region will render as-is in stack with same region and account', () => {
// GIVEN
const graph = new GraphWidget({
left: [
a.with({ account: '1234', region: 'us-north-5' }),
],
});
// THEN
// Assertion fails. It would pass if the stack had different region and account values.
graphMetricsAre(new Stack(undefined, undefined, { env: { region: 'us-north-5', account: '1234' } }), graph, [
['Test', 'ACount', { accountId: '1234', region: 'us-north-5' }],
]);
});
Possible Solution
The problem arises from these two lines in the metricGraphJson
function:
aws-cdk/packages/aws-cdk-lib/aws-cloudwatch/lib/private/rendering.ts
Lines 50 to 51 in 109b2ab
I'm not sure, but I think the intent here is to prevent the region
and account
from being included in the output if they were set implicitly by the attachTo
function. As that function's description says:
If the metric is subsequently used in a Dashboard or Alarm in a different Stack defined in a different account or region, the appropriate 'region' and 'account' fields will be added to it.
I'm not sure why it's so important to prevent the region
and account
fields from being included when they match the stack, but if it is, you could have attachTo
attach a placeholder that metricGraphJson
can process appropriately (e.g. "${ifDifferentFromStack(us-east-1)}"
) rather than attaching a value that's indistinguishable from one that's been explicitly set.
Additional Information/Context
No response
CDK CLI Version
2.121.1
Framework Version
No response
Node.js Version
18.15.0
OS
macOS 13.6.3
Language
TypeScript
Language Version
No response
Other information
Possibly related to #18951?