Skip to content

Commit

Permalink
feat(cloudwatch): validate parameters for a metric dimensions (closes a…
Browse files Browse the repository at this point in the history
…ws#3116) (aws#14365)

As per aws#3116, the changes in this PR validate metric dimension values (length, and checking if the value is null or undefined) and throw errors if the values are not valid. I've also corrected a comment in the metric-types.ts to use the correct method name
  • Loading branch information
OksanaH authored and john-tipper committed May 10, 2021
1 parent 827c287 commit 5e805d7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 3 deletions.
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ 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;
}

/**
* Metric dimension
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html
*
*/
export interface Dimension {
/**
Expand Down
24 changes: 23 additions & 1 deletion packages/@aws-cdk/aws-cloudwatch/lib/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
73 changes: 73 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch/test/test.metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
},
};

0 comments on commit 5e805d7

Please sign in to comment.