@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
JavaScript
"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.13" };
;
/**
* 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.13" };
;
/**
* 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.13" };
;
/**
* 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.13" };
;
/**
* 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.13" };
;
/**
* 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.13" };
;
/**
* 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.13" };
/**
* 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.13" };
/**
* 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.13" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZHluYW1vZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FLcUI7QUFDckIsMkNBQW1EO0FBQ25ELHFDQUFvRTtBQUVwRTs7R0FFRztBQUNILElBQVksZ0NBNkJYO0FBN0JELFdBQVksZ0NBQWdDO0lBQzFDOztPQUVHO0lBQ0gsK0VBQTJDLENBQUE7SUFDM0M7OztPQUdHO0lBQ0gsa0VBQThCLENBQUE7SUFDOUI7O09BRUc7SUFDSCxpRkFBNkMsQ0FBQTtJQUU3Qzs7T0FFRztJQUNILHVHQUFtRSxDQUFBO0lBRW5FOztPQUVHO0lBQ0gscUdBQWlFLENBQUE7SUFFakU7O09BRUc7SUFDSCwwRkFBc0QsQ0FBQTtBQUN4RCxDQUFDLEVBN0JXLGdDQUFnQyxnREFBaEMsZ0NBQWdDLFFBNkIzQztBQXVFRDs7Ozs7O0dBTUc7QUFDSCxNQUFhLG9DQUFxQyxTQUFRLDRCQUFVLENBQUMsS0FBSztJQUN4RSxZQUFZLEtBQWlCLEVBQUUsRUFBVSxFQUFFLEtBQWdEO1FBQ3pGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsTUFBTSxnQ0FBZ0MsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzNILE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ2xDLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixJQUFJLDRCQUFVLENBQUMsZ0JB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