UNPKG

@renovosolutions/cdk-library-cloudwatch-alarms

Version:

AWS CDK Construct Library to automatically create CloudWatch Alarms for resources in a CDK app based on resource type.

568 lines 104 kB
"use strict"; var _a, _b, _c, _d, _e, _f, _g, _h, _j; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamoDbRecommendedAlarmsAspect = exports.Table = exports.DynamoDbTableRecommendedAlarms = exports.DynamoDbTableThrottledPutRecordCountAlarm = exports.DynamoDbTableFailedToReplicateRecordCountAlarm = exports.DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm = exports.DynamoDbTableWriteThrottleEventsAlarm = exports.DynamoDbTableSystemErrorsAlarm = exports.DynamoDbTableReadThrottleEventsAlarm = exports.DynamoDbRecommendedAlarmsMetrics = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const constructs_1 = require("constructs"); const common_1 = require("./common"); /** * The recommended metrics for DynamoDb alarms. */ var DynamoDbRecommendedAlarmsMetrics; (function (DynamoDbRecommendedAlarmsMetrics) { /** * Requests to DynamoDB that exceed the provisioned read capacity units for a table or a global secondary index. */ DynamoDbRecommendedAlarmsMetrics["READ_THROTTLE_EVENTS"] = "ReadThrottleEvents"; /** * The requests to DynamoDB or Amazon DynamoDB Streams that generate an HTTP 500 status code during the specified * time period. An HTTP 500 usually indicates an internal service error. */ DynamoDbRecommendedAlarmsMetrics["SYSTEM_ERRORS"] = "SystemErrors"; /** * Requests to DynamoDB that exceed the provisioned write capacity units for a table or a global secondary index. */ DynamoDbRecommendedAlarmsMetrics["WRITE_THROTTLE_EVENTS"] = "WriteThrottleEvents"; /** * The elapsed time since a record yet to be replicated to the Kinesis data stream first appeared in the DynamoDB table. */ DynamoDbRecommendedAlarmsMetrics["AGE_OF_OLDEST_UNREPLICATED_RECORD"] = "AgeOfOldestUnreplicatedRecord"; /** * The number of records that DynamoDB failed to replicate to your Kinesis data stream. */ DynamoDbRecommendedAlarmsMetrics["FAILED_TO_REPLICATE_RECORD_COUNT"] = "FailedToReplicateRecordCount"; /** * The number of records that were throttled by your Kinesis data stream due to insufficient Kinesis Data Streams capacity. */ DynamoDbRecommendedAlarmsMetrics["THROTTLED_PUT_RECORD_COUNT"] = "ThrottledPutRecordCount"; })(DynamoDbRecommendedAlarmsMetrics || (exports.DynamoDbRecommendedAlarmsMetrics = DynamoDbRecommendedAlarmsMetrics = {})); /** * This alarm detects if there are high number of read requests getting throttled for the DynamoDB table. * * To troubleshoot the issue, see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TroubleshootingThrottling.html|Troubleshooting throttling issues in Amazon DynamoDB}. * * The alarm is triggered when the number of read requests exceeds the threshold. */ class DynamoDbTableReadThrottleEventsAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.READ_THROTTLE_EVENTS}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can detect sustained throttling for read requests to the DynamoDB' + ' table. Sustained throttling of read requests can negatively impact your workload read operations and reduce the overall' + ' efficiency of the system.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.READ_THROTTLE_EVENTS, dimensionsMap: { TableName: props.table.tableName, }, period, statistic: 'Sum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableReadThrottleEventsAlarm = DynamoDbTableReadThrottleEventsAlarm; _a = JSII_RTTI_SYMBOL_1; DynamoDbTableReadThrottleEventsAlarm[_a] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableReadThrottleEventsAlarm", version: "0.0.17" }; ; /** * This alarm detects a sustained high number of system errors for the DynamoDB table requests. * * If you continue to get 5xx errors, open the {@link https://status.aws.amazon.com/|AWS Service Health Dashboard} * to check for operational issues with the service. You can use this alarm to get notified in case there is a prolonged * internal service issue from DynamoDB and it helps you correlate with the issue your client application is facing. * Refer {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.MessagesAndCodes.http5xx|Error handling for DynamoDB} for more information. * * The alarm is triggered when the number of system errors exceeds threshold. */ class DynamoDbTableSystemErrorsAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.SYSTEM_ERRORS}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 15; const datapointsToAlarm = props.datapointsToAlarm ?? 15; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can detect sustained system errors for the DynamoDB table' + ' requests. System errors indicate internal service errors from DynamoDB and helps correlate to the issue that the client is having.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.SYSTEM_ERRORS, dimensionsMap: { TableName: props.table.tableName, }, period, statistic: 'Sum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableSystemErrorsAlarm = DynamoDbTableSystemErrorsAlarm; _b = JSII_RTTI_SYMBOL_1; DynamoDbTableSystemErrorsAlarm[_b] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableSystemErrorsAlarm", version: "0.0.17" }; ; /** * This alarm detects if there are high number of read requests getting throttled for the DynamoDB table. * * To troubleshoot the issue, see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TroubleshootingThrottling.html|Troubleshooting throttling issues in Amazon DynamoDB}. * * The alarm is triggered when the number of read requests exceeds the threshold. */ class DynamoDbTableWriteThrottleEventsAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.WRITE_THROTTLE_EVENTS}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can detect sustained throttling for write requests to the DynamoDB' + ' table. Sustained throttling of write requests can negatively impact your workload write operations and reduce the overall' + ' efficiency of the system.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.WRITE_THROTTLE_EVENTS, dimensionsMap: { TableName: props.table.tableName, }, period, statistic: 'Sum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableWriteThrottleEventsAlarm = DynamoDbTableWriteThrottleEventsAlarm; _c = JSII_RTTI_SYMBOL_1; DynamoDbTableWriteThrottleEventsAlarm[_c] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableWriteThrottleEventsAlarm", version: "0.0.17" }; ; /** * This alarm detects the delay in replication to a Kinesis data stream. * * Under normal operation, `AgeOfOldestUnreplicatedRecord` should be only milliseconds. * This number grows based on unsuccessful replication attempts caused by customer-controlled * configuration choices. Customer-controlled configuration examples that lead to unsuccessful * replication attempts are an under-provisioned Kinesis data stream capacity that leads to * excessive throttling. or a manual update to the Kinesis data stream's access policies that * prevents DynamoDB from adding data to the data stream. To keep this metric as low as possible, * you need to ensure the right provisioning of Kinesis data stream capacity and make sure that * DynamoDB's permissions are unchanged. * * The alarm is triggered when the elapsed time since a record yet to be replicated exceeds the threshold. */ class DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.AGE_OF_OLDEST_UNREPLICATED_RECORD}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(5); const evaluationPeriods = props.evaluationPeriods ?? 3; const datapointsToAlarm = props.datapointsToAlarm ?? 3; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can monitor unsuccessful replication attempts and' + ' the resulting delay in replication to the Kinesis data stream.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.AGE_OF_OLDEST_UNREPLICATED_RECORD, dimensionsMap: { TableName: props.table.tableName, DelegatedOperation: 'StreamRecords', }, period, statistic: 'Maximum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm = DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm; _d = JSII_RTTI_SYMBOL_1; DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm[_d] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm", version: "0.0.17" }; ; /** * This alarm detects the number of records that DynamoDB failed to replicate to your Kinesis data stream. * * Certain items larger than 34 KB might expand in size to change data records that are larger than the 1 MB * item size limit of Kinesis Data Streams. This size expansion occurs when these larger than 34 KB items include * a large number of Boolean or empty attribute values. Boolean and empty attribute values are stored as 1 byte * in DynamoDB, but expand up to 5 bytes when they're serialized using standard JSON for Kinesis Data Streams * replication. DynamoDB can't replicate such change records to your Kinesis data stream. DynamoDB skips these * change data records, and automatically continues replicating subsequent records. * * The alarm is triggered when the the number of records failed to be replicated exceeds the threshold. */ class DynamoDbTableFailedToReplicateRecordCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.FAILED_TO_REPLICATE_RECORD_COUNT}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 1; const datapointsToAlarm = props.datapointsToAlarm ?? 1; const threshold = props.threshold ?? 0; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can monitor the number of records that DynamoDB' + ' failed to replicate to your Kinesis data stream because of the item size limit of Kinesis Data Streams.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.FAILED_TO_REPLICATE_RECORD_COUNT, dimensionsMap: { TableName: props.table.tableName, DelegatedOperation: 'StreamRecords', }, period, statistic: 'Sum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableFailedToReplicateRecordCountAlarm = DynamoDbTableFailedToReplicateRecordCountAlarm; _e = JSII_RTTI_SYMBOL_1; DynamoDbTableFailedToReplicateRecordCountAlarm[_e] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableFailedToReplicateRecordCountAlarm", version: "0.0.17" }; ; /** * This alarm detects the records getting throttled by your Kinesis data stream during the * replication of change data capture to Kinesis. * * This throttling happens because of insufficient Kinesis data stream capacity. If you experience excessive * and regular throttling, you might need to increase the number of Kinesis stream shards proportionally to * the observed write throughput of your table. To learn more about determining the size of a Kinesis data stream, * see {@link https://docs.aws.amazon.com/streams/latest/dev/amazon-kinesis-streams.html#how-do-i-size-a-stream|Determining the Initial Size of a Kinesis Data Stream}. * * The alarm is triggered when the number or records that were throttled exceeds the threshold. */ class DynamoDbTableThrottledPutRecordCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.table.tableName} - ${DynamoDbRecommendedAlarmsMetrics.THROTTLED_PUT_RECORD_COUNT}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 10; const datapointsToAlarm = props.datapointsToAlarm ?? 10; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm can monitor the number of records that that were' + ' throttled by your Kinesis data stream because of insufficient Kinesis data stream capacity.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'AWS/DynamoDB', metricName: DynamoDbRecommendedAlarmsMetrics.THROTTLED_PUT_RECORD_COUNT, dimensionsMap: { TableName: props.table.tableName, DelegatedOperation: 'PutItem', }, period, statistic: 'Maximum', }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.DynamoDbTableThrottledPutRecordCountAlarm = DynamoDbTableThrottledPutRecordCountAlarm; _f = JSII_RTTI_SYMBOL_1; DynamoDbTableThrottledPutRecordCountAlarm[_f] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableThrottledPutRecordCountAlarm", version: "0.0.17" }; ; /** * A construct that creates the recommended alarms for an DynamoDb Table. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB */ class DynamoDbTableRecommendedAlarms extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); if (!props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.READ_THROTTLE_EVENTS)) { this.alarmReadThrottleEvents = new DynamoDbTableReadThrottleEventsAlarm(this, `${props.table.node.id}_ReadThrottleEvents`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configReadThrottleEventsAlarm, }); if (props.defaultAlarmAction && !props.configReadThrottleEventsAlarm.alarmAction) { this.alarmReadThrottleEvents.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configReadThrottleEventsAlarm.okAction) { this.alarmReadThrottleEvents.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configReadThrottleEventsAlarm.insufficientDataAction) { this.alarmReadThrottleEvents.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (!props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.SYSTEM_ERRORS)) { this.alarmSystemErrors = new DynamoDbTableSystemErrorsAlarm(this, `${props.table.node.id}_SystemErrors`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configSystemErrorsAlarm, }); if (props.defaultAlarmAction && !props.configSystemErrorsAlarm.alarmAction) { this.alarmSystemErrors.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configSystemErrorsAlarm.okAction) { this.alarmSystemErrors.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configSystemErrorsAlarm.insufficientDataAction) { this.alarmSystemErrors.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (!props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.WRITE_THROTTLE_EVENTS)) { this.alarmWriteThrottleEvents = new DynamoDbTableWriteThrottleEventsAlarm(this, `${props.table.node.id}_WriteThrottleEvents`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configWriteThrottleEventsAlarm, }); if (props.defaultAlarmAction && !props.configWriteThrottleEventsAlarm.alarmAction) { this.alarmWriteThrottleEvents.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configWriteThrottleEventsAlarm.okAction) { this.alarmWriteThrottleEvents.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configWriteThrottleEventsAlarm.insufficientDataAction) { this.alarmWriteThrottleEvents.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (props.configAgeOfOldestUnreplicatedRecordAlarm && !props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.AGE_OF_OLDEST_UNREPLICATED_RECORD)) { this.alarmAgeOfOldestUnreplicatedRecord = new DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm(this, `${props.table.node.id}_AgeOfOldestUnreplicatedRecord`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configAgeOfOldestUnreplicatedRecordAlarm, }); if (props.defaultAlarmAction && !props.configAgeOfOldestUnreplicatedRecordAlarm.alarmAction) { this.alarmAgeOfOldestUnreplicatedRecord.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configAgeOfOldestUnreplicatedRecordAlarm.okAction) { this.alarmAgeOfOldestUnreplicatedRecord.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configAgeOfOldestUnreplicatedRecordAlarm.insufficientDataAction) { this.alarmAgeOfOldestUnreplicatedRecord.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (props.configFailedToReplicateRecordCountAlarm && !props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.FAILED_TO_REPLICATE_RECORD_COUNT)) { this.alarmFailedToReplicateRecordCount = new DynamoDbTableFailedToReplicateRecordCountAlarm(this, `${props.table.node.id}_FailedToReplicateRecordCount`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configFailedToReplicateRecordCountAlarm, }); if (props.defaultAlarmAction && !props.configFailedToReplicateRecordCountAlarm.alarmAction) { this.alarmFailedToReplicateRecordCount.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configFailedToReplicateRecordCountAlarm.okAction) { this.alarmFailedToReplicateRecordCount.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configFailedToReplicateRecordCountAlarm.insufficientDataAction) { this.alarmFailedToReplicateRecordCount.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (props.configThrottledPutRecordCountAlarm && !props.excludeAlarms?.includes(DynamoDbRecommendedAlarmsMetrics.THROTTLED_PUT_RECORD_COUNT)) { this.alarmThrottledPutRecordCount = new DynamoDbTableThrottledPutRecordCountAlarm(this, `${props.table.node.id}_ThrottledPutRecordCount`, { table: props.table, treatMissingData: props.treatMissingData, ...props.configThrottledPutRecordCountAlarm, }); if (props.defaultAlarmAction && !props.configThrottledPutRecordCountAlarm.alarmAction) { this.alarmThrottledPutRecordCount.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configThrottledPutRecordCountAlarm.okAction) { this.alarmThrottledPutRecordCount.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configThrottledPutRecordCountAlarm.insufficientDataAction) { this.alarmThrottledPutRecordCount.addInsufficientDataAction(props.defaultInsufficientDataAction); } } } } exports.DynamoDbTableRecommendedAlarms = DynamoDbTableRecommendedAlarms; _g = JSII_RTTI_SYMBOL_1; DynamoDbTableRecommendedAlarms[_g] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbTableRecommendedAlarms", version: "0.0.17" }; /** * An extension for the Table construct that provides methods * to create recommended alarms. */ class Table extends aws_cdk_lib_1.aws_dynamodb.Table { constructor(scope, id, props) { super(scope, id, props); } /** * Creates an alarm that monitors the ReadThrottleEvents for the DynamoDb table. */ alarmReadThrottleEvents(props) { return new DynamoDbTableReadThrottleEventsAlarm(this, 'ReadThrottleEventsAlarm', { table: this, ...props, }); } /** * Creates an alarm that monitors the SystemErrors for the DynamoDb table. */ alarmSystemErrors(props) { return new DynamoDbTableSystemErrorsAlarm(this, 'SystemErrorsAlarm', { table: this, ...props, }); } /** * Creates an alarm that monitors the WriteThrottleEvents for the DynamoDb table. */ alarmWriteThrottleEvents(props) { return new DynamoDbTableWriteThrottleEventsAlarm(this, 'WriteThrottleEventsAlarm', { table: this, ...props, }); } /** * Creates an alarm that monitors the AgeOfOldestUnreplicatedRecord for the DynamoDb table. */ alarmAgeOfOldestUnreplicatedRecord(props) { return new DynamoDbTableAgeOfOldestUnreplicatedRecordAlarm(this, 'AgeOfOldestUnreplicatedRecordAlarm', { table: this, ...props, }); } /** * Creates an alarm that monitors the FailedToReplicateRecordCount for the DynamoDb table. */ alarmFailedToReplicateRecordCount(props) { return new DynamoDbTableFailedToReplicateRecordCountAlarm(this, 'FailedToReplicateRecordCountAlarm', { table: this, ...props, }); } /** * Creates an alarm that monitors the ThrottledPutRecordCount for the DynamoDb table. */ alarmThrottledPutRecordCount(props) { return new DynamoDbTableThrottledPutRecordCountAlarm(this, 'ThrottledPutRecordCountAlarm', { table: this, ...props, }); } /** * Creates the recommended alarms for the DynamoDb Table. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB */ applyRecommendedAlarms(props) { return new DynamoDbTableRecommendedAlarms(this, 'DynamoDbTableRecommendedAlarms', { table: this, ...props, }); } } exports.Table = Table; _h = JSII_RTTI_SYMBOL_1; Table[_h] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.Table", version: "0.0.17" }; /** * Configures the recommended alarms for an DynamoDb Table. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB */ class DynamoDbRecommendedAlarmsAspect { constructor(props) { this.props = props; } visit(node) { if (node instanceof aws_cdk_lib_1.aws_dynamodb.Table) { if (this.props.excludeResources && this.props.excludeResources.includes(node.node.id)) { return; } else { const table = node; new DynamoDbTableRecommendedAlarms(table, 'DynamoDbTableRecommendedAlarmsFromAspect', { table, ...this.props, }); } } } } exports.DynamoDbRecommendedAlarmsAspect = DynamoDbRecommendedAlarmsAspect; _j = JSII_RTTI_SYMBOL_1; DynamoDbRecommendedAlarmsAspect[_j] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.DynamoDbRecommendedAlarmsAspect", version: "0.0.17" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZHluYW1vZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FLcUI7QUFDckIsMkNBQW1EO0FBQ25ELHFDQUFvRTtBQUVwRTs7R0FFRztBQUNILElBQVksZ0NBNkJYO0FBN0JELFdBQVksZ0NBQWdDO0lBQzFDOztPQUVHO0lBQ0gsK0VBQTJDLENBQUE7SUFDM0M7OztPQUdHO0lBQ0gsa0VBQThCLENBQUE7SUFDOUI7O09BRUc7SUFDSCxpRkFBNkMsQ0FBQTtJQUU3Qzs7T0FFRztJQUNILHVHQUFtRSxDQUFBO0lBRW5FOztPQUVHO0lBQ0gscUdBQWlFLENBQUE7SUFFakU7O09BRUc7SUFDSCwwRkFBc0QsQ0FBQTtBQUN4RCxDQUFDLEVBN0JXLGdDQUFnQyxnREFBaEMsZ0NBQWdDLFFBNkIzQztBQXVFRDs7Ozs7O0dBTUc7QUFDSCxNQUFhLG9DQUFxQyxTQUFRLDRCQUFVLENBQUMsS0FBSztJQUN4RSxZQUFZLEtBQWlCLEVBQUUsRUFBVSxFQUFFLEtBQWdEO1FBQ3pGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsTUFBTSxnQ0FBZ0MsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzNILE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ2xDLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixJQUFJLDRCQUFVLENBQUMsZ0JB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