diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts index eaa48446672f9..296400ee7f910 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts @@ -12,14 +12,14 @@ export interface IMetric { /** * Turn this metric object into an alarm configuration * - * @deprecated Use `toMetricsConfig()` instead. + * @deprecated Use `toMetricConfig()` instead. */ toAlarmConfig(): MetricAlarmConfig; /** * Turn this metric object into a graph configuration * - * @deprecated Use `toMetricsConfig()` instead. + * @deprecated Use `toMetricConfig()` instead. */ toGraphConfig(): MetricGraphConfig; } @@ -27,6 +27,8 @@ export interface IMetric { /** * Metric dimension * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html + * */ export interface Dimension { /** diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 0590a592da502..3bb3d512c86d0 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -216,7 +216,9 @@ export class Metric implements IMetric { if (periodSec !== 1 && periodSec !== 5 && periodSec !== 10 && periodSec !== 30 && periodSec % 60 !== 0) { throw new Error(`'period' must be 1, 5, 10, 30, or a multiple of 60 seconds, received ${periodSec}`); } - + if (props.dimensions) { + this.validateDimensions(props.dimensions); + } this.dimensions = props.dimensions; this.namespace = props.namespace; this.metricName = props.metricName; @@ -395,6 +397,26 @@ export class Metric implements IMetric { return list; } + + private validateDimensions(dims: DimensionHash): void { + var dimsArray = Object.keys(dims); + if (dimsArray?.length > 10) { + throw new Error(`The maximum number of dimensions is 10, received ${dimsArray.length}`); + } + + dimsArray.map(key => { + if (dims[key] === undefined || dims[key] === null) { + throw new Error(`Dimension value of '${dims[key]}' is invalid`); + }; + if (key.length < 1 || key.length > 255) { + throw new Error(`Dimension name must be at least 1 and no more than 255 characters; received ${key}`); + }; + + if (dims[key].length < 1 || dims[key].length > 255) { + throw new Error(`Dimension value must be at least 1 and no more than 255 characters; received ${dims[key]}`); + }; + }); + } } function asString(x?: unknown): string | undefined { diff --git a/packages/@aws-cdk/aws-cloudwatch/test/test.metrics.ts b/packages/@aws-cdk/aws-cloudwatch/test/test.metrics.ts index 18e1840e35cb6..e1dc9230e1404 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/test.metrics.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/test.metrics.ts @@ -51,4 +51,77 @@ export = { test.done(); }, + + 'cannot use null dimension value'(test: Test) { + test.throws(() => { + new Metric({ + namespace: 'Test', + metricName: 'ACount', + period: cdk.Duration.minutes(10), + dimensions: { + DimensionWithNull: null, + }, + }); + }, /Dimension value of 'null' is invalid/); + + test.done(); + }, + + 'cannot use undefined dimension value'(test: Test) { + test.throws(() => { + new Metric({ + namespace: 'Test', + metricName: 'ACount', + period: cdk.Duration.minutes(10), + dimensions: { + DimensionWithUndefined: undefined, + }, + }); + }, /Dimension value of 'undefined' is invalid/); + + test.done(); + }, + + 'cannot use long dimension values'(test: Test) { + const arr = new Array(256); + const invalidDimensionValue = arr.fill('A', 0).join(''); + + test.throws(() => { + new Metric({ + namespace: 'Test', + metricName: 'ACount', + period: cdk.Duration.minutes(10), + dimensions: { + DimensionWithLongValue: invalidDimensionValue, + }, + }); + }, `Dimension value must be at least 1 and no more than 255 characters; received ${invalidDimensionValue}`); + + test.done(); + }, + + 'throws error when there are more than 10 dimensions'(test: Test) { + test.throws(() => { + new Metric({ + namespace: 'Test', + metricName: 'ACount', + period: cdk.Duration.minutes(10), + dimensions: { + dimensionA: 'value1', + dimensionB: 'value2', + dimensionC: 'value3', + dimensionD: 'value4', + dimensionE: 'value5', + dimensionF: 'value6', + dimensionG: 'value7', + dimensionH: 'value8', + dimensionI: 'value9', + dimensionJ: 'value10', + dimensionK: 'value11', + }, + } ); + }, /The maximum number of dimensions is 10, received 11/); + + test.done(); + }, };