diff --git a/API.md b/API.md index 4ad62148..f8f581c3 100644 --- a/API.md +++ b/API.md @@ -1097,6 +1097,7 @@ new MonitoringFacade(scope: Construct, id: string, props?: MonitoringFacadeProps | monitorQueueProcessingEc2Service | *No description.* | | monitorQueueProcessingFargateService | *No description.* | | monitorRdsCluster | *No description.* | +| monitorRdsInstance | *No description.* | | monitorRedshiftCluster | *No description.* | | monitorS3Bucket | *No description.* | | monitorScope | Uses an aspect to automatically monitor all resources in the given scope. | @@ -1828,6 +1829,18 @@ public monitorRdsCluster(props: RdsClusterMonitoringProps): MonitoringFacade --- +##### `monitorRdsInstance` + +```typescript +public monitorRdsInstance(props: RdsInstanceMonitoringProps): MonitoringFacade +``` + +###### `props`Required + +- *Type:* RdsInstanceMonitoringProps + +--- + ##### `monitorRedshiftCluster` ```typescript @@ -33045,6 +33058,8 @@ const monitoringAspectProps: MonitoringAspectProps = { ... } | lambda | MonitoringAspectType | *No description.* | | openSearch | MonitoringAspectType | *No description.* | | rds | MonitoringAspectType | *No description.* | +| rdsCluster | MonitoringAspectType | *No description.* | +| rdsInstance | MonitoringAspectType | *No description.* | | redshift | MonitoringAspectType | *No description.* | | s3 | MonitoringAspectType | *No description.* | | secretsManager | MonitoringAspectType | *No description.* | @@ -33246,7 +33261,9 @@ public readonly openSearch: MonitoringAspectType; --- -##### `rds`Optional +##### ~~`rds`~~Optional + +- *Deprecated:* Use rdsCluster instead. ```typescript public readonly rds: MonitoringAspectType; @@ -33256,6 +33273,26 @@ public readonly rds: MonitoringAspectType; --- +##### `rdsCluster`Optional + +```typescript +public readonly rdsCluster: MonitoringAspectType; +``` + +- *Type:* MonitoringAspectType + +--- + +##### `rdsInstance`Optional + +```typescript +public readonly rdsInstance: MonitoringAspectType; +``` + +- *Type:* MonitoringAspectType + +--- + ##### `redshift`Optional ```typescript @@ -38090,6 +38127,381 @@ public readonly addMinConnectionCountAlarm: {[ key: string ]: LowConnectionCount --- +### RdsInstanceMetricFactoryProps + +#### Initializer + +```typescript +import { RdsInstanceMetricFactoryProps } from 'cdk-monitoring-constructs' + +const rdsInstanceMetricFactoryProps: RdsInstanceMetricFactoryProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| instance | aws-cdk-lib.aws_rds.IDatabaseInstance | database instance. | + +--- + +##### `instance`Required + +```typescript +public readonly instance: IDatabaseInstance; +``` + +- *Type:* aws-cdk-lib.aws_rds.IDatabaseInstance + +database instance. + +--- + +### RdsInstanceMonitoringOptions + +#### Initializer + +```typescript +import { RdsInstanceMonitoringOptions } from 'cdk-monitoring-constructs' + +const rdsInstanceMonitoringOptions: RdsInstanceMonitoringOptions = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| alarmFriendlyName | string | Plain name, used in naming alarms. | +| humanReadableName | string | Human-readable name is a freeform string, used as a caption or description. | +| localAlarmNamePrefixOverride | string | If this is defined, the local alarm name prefix used in naming alarms for the construct will be set to this value. | +| addToAlarmDashboard | boolean | Flag indicating if the widgets should be added to alarm dashboard. | +| addToDetailDashboard | boolean | Flag indicating if the widgets should be added to detailed dashboard. | +| addToSummaryDashboard | boolean | Flag indicating if the widgets should be added to summary dashboard. | +| useCreatedAlarms | IAlarmConsumer | Calls provided function to process all alarms created. | +| addCpuUsageAlarm | {[ key: string ]: UsageThreshold} | *No description.* | +| addFreeStorageSpaceAlarm | {[ key: string ]: MinUsageCountThreshold} | *No description.* | +| addMaxConnectionCountAlarm | {[ key: string ]: HighConnectionCountThreshold} | *No description.* | +| addMinConnectionCountAlarm | {[ key: string ]: LowConnectionCountThreshold} | *No description.* | + +--- + +##### `alarmFriendlyName`Optional + +```typescript +public readonly alarmFriendlyName: string; +``` + +- *Type:* string +- *Default:* derives name from the construct itself + +Plain name, used in naming alarms. + +This unique among other resources, and respect the AWS CDK restriction posed on alarm names. +The length must be 1 - 255 characters and although the validation rules are undocumented, we recommend using ASCII and hyphens. + +--- + +##### `humanReadableName`Optional + +```typescript +public readonly humanReadableName: string; +``` + +- *Type:* string +- *Default:* use alarmFriendlyName + +Human-readable name is a freeform string, used as a caption or description. + +There are no limitations on what it can be. + +--- + +##### `localAlarmNamePrefixOverride`Optional + +```typescript +public readonly localAlarmNamePrefixOverride: string; +``` + +- *Type:* string + +If this is defined, the local alarm name prefix used in naming alarms for the construct will be set to this value. + +The length must be 1 - 255 characters and although the validation rules are undocumented, we recommend using ASCII and hyphens. + +> [AlarmNamingStrategy for more details on alarm name prefixes](AlarmNamingStrategy for more details on alarm name prefixes) + +--- + +##### `addToAlarmDashboard`Optional + +```typescript +public readonly addToAlarmDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to alarm dashboard. + +--- + +##### `addToDetailDashboard`Optional + +```typescript +public readonly addToDetailDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to detailed dashboard. + +--- + +##### `addToSummaryDashboard`Optional + +```typescript +public readonly addToSummaryDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to summary dashboard. + +--- + +##### `useCreatedAlarms`Optional + +```typescript +public readonly useCreatedAlarms: IAlarmConsumer; +``` + +- *Type:* IAlarmConsumer + +Calls provided function to process all alarms created. + +--- + +##### `addCpuUsageAlarm`Optional + +```typescript +public readonly addCpuUsageAlarm: {[ key: string ]: UsageThreshold}; +``` + +- *Type:* {[ key: string ]: UsageThreshold} + +--- + +##### `addFreeStorageSpaceAlarm`Optional + +```typescript +public readonly addFreeStorageSpaceAlarm: {[ key: string ]: MinUsageCountThreshold}; +``` + +- *Type:* {[ key: string ]: MinUsageCountThreshold} + +--- + +##### `addMaxConnectionCountAlarm`Optional + +```typescript +public readonly addMaxConnectionCountAlarm: {[ key: string ]: HighConnectionCountThreshold}; +``` + +- *Type:* {[ key: string ]: HighConnectionCountThreshold} + +--- + +##### `addMinConnectionCountAlarm`Optional + +```typescript +public readonly addMinConnectionCountAlarm: {[ key: string ]: LowConnectionCountThreshold}; +``` + +- *Type:* {[ key: string ]: LowConnectionCountThreshold} + +--- + +### RdsInstanceMonitoringProps + +#### Initializer + +```typescript +import { RdsInstanceMonitoringProps } from 'cdk-monitoring-constructs' + +const rdsInstanceMonitoringProps: RdsInstanceMonitoringProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| instance | aws-cdk-lib.aws_rds.IDatabaseInstance | database instance. | +| alarmFriendlyName | string | Plain name, used in naming alarms. | +| humanReadableName | string | Human-readable name is a freeform string, used as a caption or description. | +| localAlarmNamePrefixOverride | string | If this is defined, the local alarm name prefix used in naming alarms for the construct will be set to this value. | +| addToAlarmDashboard | boolean | Flag indicating if the widgets should be added to alarm dashboard. | +| addToDetailDashboard | boolean | Flag indicating if the widgets should be added to detailed dashboard. | +| addToSummaryDashboard | boolean | Flag indicating if the widgets should be added to summary dashboard. | +| useCreatedAlarms | IAlarmConsumer | Calls provided function to process all alarms created. | +| addCpuUsageAlarm | {[ key: string ]: UsageThreshold} | *No description.* | +| addFreeStorageSpaceAlarm | {[ key: string ]: MinUsageCountThreshold} | *No description.* | +| addMaxConnectionCountAlarm | {[ key: string ]: HighConnectionCountThreshold} | *No description.* | +| addMinConnectionCountAlarm | {[ key: string ]: LowConnectionCountThreshold} | *No description.* | + +--- + +##### `instance`Required + +```typescript +public readonly instance: IDatabaseInstance; +``` + +- *Type:* aws-cdk-lib.aws_rds.IDatabaseInstance + +database instance. + +--- + +##### `alarmFriendlyName`Optional + +```typescript +public readonly alarmFriendlyName: string; +``` + +- *Type:* string +- *Default:* derives name from the construct itself + +Plain name, used in naming alarms. + +This unique among other resources, and respect the AWS CDK restriction posed on alarm names. +The length must be 1 - 255 characters and although the validation rules are undocumented, we recommend using ASCII and hyphens. + +--- + +##### `humanReadableName`Optional + +```typescript +public readonly humanReadableName: string; +``` + +- *Type:* string +- *Default:* use alarmFriendlyName + +Human-readable name is a freeform string, used as a caption or description. + +There are no limitations on what it can be. + +--- + +##### `localAlarmNamePrefixOverride`Optional + +```typescript +public readonly localAlarmNamePrefixOverride: string; +``` + +- *Type:* string + +If this is defined, the local alarm name prefix used in naming alarms for the construct will be set to this value. + +The length must be 1 - 255 characters and although the validation rules are undocumented, we recommend using ASCII and hyphens. + +> [AlarmNamingStrategy for more details on alarm name prefixes](AlarmNamingStrategy for more details on alarm name prefixes) + +--- + +##### `addToAlarmDashboard`Optional + +```typescript +public readonly addToAlarmDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to alarm dashboard. + +--- + +##### `addToDetailDashboard`Optional + +```typescript +public readonly addToDetailDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to detailed dashboard. + +--- + +##### `addToSummaryDashboard`Optional + +```typescript +public readonly addToSummaryDashboard: boolean; +``` + +- *Type:* boolean +- *Default:* true + +Flag indicating if the widgets should be added to summary dashboard. + +--- + +##### `useCreatedAlarms`Optional + +```typescript +public readonly useCreatedAlarms: IAlarmConsumer; +``` + +- *Type:* IAlarmConsumer + +Calls provided function to process all alarms created. + +--- + +##### `addCpuUsageAlarm`Optional + +```typescript +public readonly addCpuUsageAlarm: {[ key: string ]: UsageThreshold}; +``` + +- *Type:* {[ key: string ]: UsageThreshold} + +--- + +##### `addFreeStorageSpaceAlarm`Optional + +```typescript +public readonly addFreeStorageSpaceAlarm: {[ key: string ]: MinUsageCountThreshold}; +``` + +- *Type:* {[ key: string ]: MinUsageCountThreshold} + +--- + +##### `addMaxConnectionCountAlarm`Optional + +```typescript +public readonly addMaxConnectionCountAlarm: {[ key: string ]: HighConnectionCountThreshold}; +``` + +- *Type:* {[ key: string ]: HighConnectionCountThreshold} + +--- + +##### `addMinConnectionCountAlarm`Optional + +```typescript +public readonly addMinConnectionCountAlarm: {[ key: string ]: LowConnectionCountThreshold}; +``` + +- *Type:* {[ key: string ]: LowConnectionCountThreshold} + +--- + ### RecordsFailedThreshold #### Initializer @@ -49741,6 +50153,7 @@ new AwsConsoleUrlFactory(props: AwsConsoleUrlFactoryProps) | getLambdaFunctionUrl | *No description.* | | getOpenSearchClusterUrl | *No description.* | | getRdsClusterUrl | *No description.* | +| getRdsInstanceUrl | *No description.* | | getRedshiftClusterUrl | *No description.* | | getS3BucketUrl | *No description.* | | getSnsTopicUrl | *No description.* | @@ -49923,6 +50336,18 @@ public getRdsClusterUrl(clusterId: string): string --- +##### `getRdsInstanceUrl` + +```typescript +public getRdsInstanceUrl(instanceId: string): string +``` + +###### `instanceId`Required + +- *Type:* string + +--- + ##### `getRedshiftClusterUrl` ```typescript @@ -64444,6 +64869,547 @@ public readonly url: string; --- +### RdsInstanceMetricFactory + +#### Initializers + +```typescript +import { RdsInstanceMetricFactory } from 'cdk-monitoring-constructs' + +new RdsInstanceMetricFactory(metricFactory: MetricFactory, props: RdsInstanceMetricFactoryProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| metricFactory | MetricFactory | *No description.* | +| props | RdsInstanceMetricFactoryProps | *No description.* | + +--- + +##### `metricFactory`Required + +- *Type:* MetricFactory + +--- + +##### `props`Required + +- *Type:* RdsInstanceMetricFactoryProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| metricAverageCpuUsageInPercent | *No description.* | +| metricAverageFreeableMemory | *No description.* | +| metricMaxFreeStorageSpace | *No description.* | +| metricReadIops | *No description.* | +| metricReadLatencyInMillis | *No description.* | +| metricReadThroughput | *No description.* | +| metricTotalConnectionCount | *No description.* | +| metricWriteIops | *No description.* | +| metricWriteLatencyInMillis | *No description.* | +| metricWriteThroughput | *No description.* | + +--- + +##### `metricAverageCpuUsageInPercent` + +```typescript +public metricAverageCpuUsageInPercent(): Metric | MathExpression +``` + +##### `metricAverageFreeableMemory` + +```typescript +public metricAverageFreeableMemory(): Metric | MathExpression +``` + +##### `metricMaxFreeStorageSpace` + +```typescript +public metricMaxFreeStorageSpace(): Metric | MathExpression +``` + +##### `metricReadIops` + +```typescript +public metricReadIops(): Metric | MathExpression +``` + +##### `metricReadLatencyInMillis` + +```typescript +public metricReadLatencyInMillis(latencyType: LatencyType): Metric | MathExpression +``` + +###### `latencyType`Required + +- *Type:* LatencyType + +--- + +##### `metricReadThroughput` + +```typescript +public metricReadThroughput(): Metric | MathExpression +``` + +##### `metricTotalConnectionCount` + +```typescript +public metricTotalConnectionCount(): Metric | MathExpression +``` + +##### `metricWriteIops` + +```typescript +public metricWriteIops(): Metric | MathExpression +``` + +##### `metricWriteLatencyInMillis` + +```typescript +public metricWriteLatencyInMillis(latencyType: LatencyType): Metric | MathExpression +``` + +###### `latencyType`Required + +- *Type:* LatencyType + +--- + +##### `metricWriteThroughput` + +```typescript +public metricWriteThroughput(): Metric | MathExpression +``` + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| instance | aws-cdk-lib.aws_rds.IDatabaseInstance | *No description.* | +| instanceIdentifier | string | *No description.* | + +--- + +##### `instance`Required + +```typescript +public readonly instance: IDatabaseInstance; +``` + +- *Type:* aws-cdk-lib.aws_rds.IDatabaseInstance + +--- + +##### `instanceIdentifier`Required + +```typescript +public readonly instanceIdentifier: string; +``` + +- *Type:* string + +--- + + +### RdsInstanceMonitoring + +#### Initializers + +```typescript +import { RdsInstanceMonitoring } from 'cdk-monitoring-constructs' + +new RdsInstanceMonitoring(scope: MonitoringScope, props: RdsInstanceMonitoringProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| scope | MonitoringScope | *No description.* | +| props | RdsInstanceMonitoringProps | *No description.* | + +--- + +##### `scope`Required + +- *Type:* MonitoringScope + +--- + +##### `props`Required + +- *Type:* RdsInstanceMonitoringProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| addAlarm | Adds an alarm. | +| alarmWidgets | Returns widgets for all alarms. | +| createAlarmFactory | Creates a new alarm factory. | +| createdAlarms | Returns all the alarms created. | +| createMetricFactory | Creates a new metric factory. | +| createWidgetFactory | Creates a new widget factory. | +| summaryWidgets | Returns widgets to be placed on the summary dashboard. | +| widgets | Returns widgets to be placed on the main dashboard. | +| widgetsForDashboard | Returns widgets for the requested dashboard type. | +| createConnectionsWidget | *No description.* | +| createCpuAndDiskUsageWidget | *No description.* | +| createLatencyWidget | *No description.* | +| createTitleWidget | *No description.* | + +--- + +##### `addAlarm` + +```typescript +public addAlarm(alarm: AlarmWithAnnotation): void +``` + +Adds an alarm. + +###### `alarm`Required + +- *Type:* AlarmWithAnnotation + +alarm to add. + +--- + +##### `alarmWidgets` + +```typescript +public alarmWidgets(): IWidget[] +``` + +Returns widgets for all alarms. + +These can go to runbook or to service dashboard. + +##### `createAlarmFactory` + +```typescript +public createAlarmFactory(alarmNamePrefix: string): AlarmFactory +``` + +Creates a new alarm factory. + +Alarms created will be named with the given prefix, unless a local name override is present. + +###### `alarmNamePrefix`Required + +- *Type:* string + +alarm name prefix. + +--- + +##### `createdAlarms` + +```typescript +public createdAlarms(): AlarmWithAnnotation[] +``` + +Returns all the alarms created. + +##### `createMetricFactory` + +```typescript +public createMetricFactory(): MetricFactory +``` + +Creates a new metric factory. + +##### `createWidgetFactory` + +```typescript +public createWidgetFactory(): IWidgetFactory +``` + +Creates a new widget factory. + +##### `summaryWidgets` + +```typescript +public summaryWidgets(): IWidget[] +``` + +Returns widgets to be placed on the summary dashboard. + +##### `widgets` + +```typescript +public widgets(): IWidget[] +``` + +Returns widgets to be placed on the main dashboard. + +##### `widgetsForDashboard` + +```typescript +public widgetsForDashboard(name: string): IWidget[] +``` + +Returns widgets for the requested dashboard type. + +###### `name`Required + +- *Type:* string + +--- + +##### `createConnectionsWidget` + +```typescript +public createConnectionsWidget(width: number, height: number): GraphWidget +``` + +###### `width`Required + +- *Type:* number + +--- + +###### `height`Required + +- *Type:* number + +--- + +##### `createCpuAndDiskUsageWidget` + +```typescript +public createCpuAndDiskUsageWidget(width: number, height: number): GraphWidget +``` + +###### `width`Required + +- *Type:* number + +--- + +###### `height`Required + +- *Type:* number + +--- + +##### `createLatencyWidget` + +```typescript +public createLatencyWidget(width: number, height: number): GraphWidget +``` + +###### `width`Required + +- *Type:* number + +--- + +###### `height`Required + +- *Type:* number + +--- + +##### `createTitleWidget` + +```typescript +public createTitleWidget(): MonitoringHeaderWidget +``` + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| connectionAlarmFactory | ConnectionAlarmFactory | *No description.* | +| connectionAnnotations | aws-cdk-lib.aws_cloudwatch.HorizontalAnnotation[] | *No description.* | +| connectionsMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| cpuUsageMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| freeableMemoryMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| freeStorageSpaceMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| readIopsMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| readLatencyMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| readThroughputMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| title | string | *No description.* | +| usageAlarmFactory | UsageAlarmFactory | *No description.* | +| usageAnnotations | aws-cdk-lib.aws_cloudwatch.HorizontalAnnotation[] | *No description.* | +| writeIopsMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| writeLatencyMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| writeThroughputMetric | aws-cdk-lib.aws_cloudwatch.Metric \| aws-cdk-lib.aws_cloudwatch.MathExpression | *No description.* | +| url | string | *No description.* | + +--- + +##### `connectionAlarmFactory`Required + +```typescript +public readonly connectionAlarmFactory: ConnectionAlarmFactory; +``` + +- *Type:* ConnectionAlarmFactory + +--- + +##### `connectionAnnotations`Required + +```typescript +public readonly connectionAnnotations: HorizontalAnnotation[]; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.HorizontalAnnotation[] + +--- + +##### `connectionsMetric`Required + +```typescript +public readonly connectionsMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `cpuUsageMetric`Required + +```typescript +public readonly cpuUsageMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `freeableMemoryMetric`Required + +```typescript +public readonly freeableMemoryMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `freeStorageSpaceMetric`Required + +```typescript +public readonly freeStorageSpaceMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `readIopsMetric`Required + +```typescript +public readonly readIopsMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `readLatencyMetric`Required + +```typescript +public readonly readLatencyMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `readThroughputMetric`Required + +```typescript +public readonly readThroughputMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `title`Required + +```typescript +public readonly title: string; +``` + +- *Type:* string + +--- + +##### `usageAlarmFactory`Required + +```typescript +public readonly usageAlarmFactory: UsageAlarmFactory; +``` + +- *Type:* UsageAlarmFactory + +--- + +##### `usageAnnotations`Required + +```typescript +public readonly usageAnnotations: HorizontalAnnotation[]; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.HorizontalAnnotation[] + +--- + +##### `writeIopsMetric`Required + +```typescript +public readonly writeIopsMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `writeLatencyMetric`Required + +```typescript +public readonly writeLatencyMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `writeThroughputMetric`Required + +```typescript +public readonly writeThroughputMetric: Metric | MathExpression; +``` + +- *Type:* aws-cdk-lib.aws_cloudwatch.Metric | aws-cdk-lib.aws_cloudwatch.MathExpression + +--- + +##### `url`Optional + +```typescript +public readonly url: string; +``` + +- *Type:* string + +--- + + ### RedshiftClusterMetricFactory #### Initializers @@ -71459,7 +72425,7 @@ Dashboard placement override props. ### IDashboardSegment -- *Implemented By:* ApiGatewayMonitoring, ApiGatewayV2HttpApiMonitoring, AppSyncMonitoring, AuroraClusterMonitoring, AutoScalingGroupMonitoring, BillingMonitoring, CertificateManagerMonitoring, CloudFrontDistributionMonitoring, CodeBuildProjectMonitoring, CustomMonitoring, DocumentDbMonitoring, DynamoTableGlobalSecondaryIndexMonitoring, DynamoTableMonitoring, EC2Monitoring, Ec2ServiceMonitoring, ElastiCacheClusterMonitoring, FargateServiceMonitoring, FluentBitMonitoring, GlueJobMonitoring, KinesisDataAnalyticsMonitoring, KinesisDataStreamMonitoring, KinesisFirehoseMonitoring, LambdaFunctionMonitoring, LogMonitoring, Monitoring, NetworkLoadBalancerMonitoring, OpenSearchClusterMonitoring, RdsClusterMonitoring, RedshiftClusterMonitoring, S3BucketMonitoring, SecretsManagerMonitoring, SecretsManagerSecretMonitoring, SingleWidgetDashboardSegment, SnsTopicMonitoring, SqsQueueMonitoring, SqsQueueMonitoringWithDlq, StepFunctionActivityMonitoring, StepFunctionLambdaIntegrationMonitoring, StepFunctionMonitoring, StepFunctionServiceIntegrationMonitoring, SyntheticsCanaryMonitoring, WafV2Monitoring, IDashboardSegment +- *Implemented By:* ApiGatewayMonitoring, ApiGatewayV2HttpApiMonitoring, AppSyncMonitoring, AuroraClusterMonitoring, AutoScalingGroupMonitoring, BillingMonitoring, CertificateManagerMonitoring, CloudFrontDistributionMonitoring, CodeBuildProjectMonitoring, CustomMonitoring, DocumentDbMonitoring, DynamoTableGlobalSecondaryIndexMonitoring, DynamoTableMonitoring, EC2Monitoring, Ec2ServiceMonitoring, ElastiCacheClusterMonitoring, FargateServiceMonitoring, FluentBitMonitoring, GlueJobMonitoring, KinesisDataAnalyticsMonitoring, KinesisDataStreamMonitoring, KinesisFirehoseMonitoring, LambdaFunctionMonitoring, LogMonitoring, Monitoring, NetworkLoadBalancerMonitoring, OpenSearchClusterMonitoring, RdsClusterMonitoring, RdsInstanceMonitoring, RedshiftClusterMonitoring, S3BucketMonitoring, SecretsManagerMonitoring, SecretsManagerSecretMonitoring, SingleWidgetDashboardSegment, SnsTopicMonitoring, SqsQueueMonitoring, SqsQueueMonitoringWithDlq, StepFunctionActivityMonitoring, StepFunctionLambdaIntegrationMonitoring, StepFunctionMonitoring, StepFunctionServiceIntegrationMonitoring, SyntheticsCanaryMonitoring, WafV2Monitoring, IDashboardSegment #### Methods @@ -71550,7 +72516,7 @@ Gets the dashboard for the requested dashboard type. ### IDynamicDashboardSegment -- *Implemented By:* ApiGatewayMonitoring, ApiGatewayV2HttpApiMonitoring, AppSyncMonitoring, AuroraClusterMonitoring, AutoScalingGroupMonitoring, BillingMonitoring, CertificateManagerMonitoring, CloudFrontDistributionMonitoring, CodeBuildProjectMonitoring, CustomMonitoring, DocumentDbMonitoring, DynamoTableGlobalSecondaryIndexMonitoring, DynamoTableMonitoring, EC2Monitoring, Ec2ServiceMonitoring, ElastiCacheClusterMonitoring, FargateServiceMonitoring, FluentBitMonitoring, GlueJobMonitoring, KinesisDataAnalyticsMonitoring, KinesisDataStreamMonitoring, KinesisFirehoseMonitoring, LambdaFunctionMonitoring, LogMonitoring, Monitoring, NetworkLoadBalancerMonitoring, OpenSearchClusterMonitoring, RdsClusterMonitoring, RedshiftClusterMonitoring, S3BucketMonitoring, SecretsManagerMonitoring, SecretsManagerSecretMonitoring, SingleWidgetDashboardSegment, SnsTopicMonitoring, SqsQueueMonitoring, SqsQueueMonitoringWithDlq, StaticSegmentDynamicAdapter, StepFunctionActivityMonitoring, StepFunctionLambdaIntegrationMonitoring, StepFunctionMonitoring, StepFunctionServiceIntegrationMonitoring, SyntheticsCanaryMonitoring, WafV2Monitoring, IDynamicDashboardSegment +- *Implemented By:* ApiGatewayMonitoring, ApiGatewayV2HttpApiMonitoring, AppSyncMonitoring, AuroraClusterMonitoring, AutoScalingGroupMonitoring, BillingMonitoring, CertificateManagerMonitoring, CloudFrontDistributionMonitoring, CodeBuildProjectMonitoring, CustomMonitoring, DocumentDbMonitoring, DynamoTableGlobalSecondaryIndexMonitoring, DynamoTableMonitoring, EC2Monitoring, Ec2ServiceMonitoring, ElastiCacheClusterMonitoring, FargateServiceMonitoring, FluentBitMonitoring, GlueJobMonitoring, KinesisDataAnalyticsMonitoring, KinesisDataStreamMonitoring, KinesisFirehoseMonitoring, LambdaFunctionMonitoring, LogMonitoring, Monitoring, NetworkLoadBalancerMonitoring, OpenSearchClusterMonitoring, RdsClusterMonitoring, RdsInstanceMonitoring, RedshiftClusterMonitoring, S3BucketMonitoring, SecretsManagerMonitoring, SecretsManagerSecretMonitoring, SingleWidgetDashboardSegment, SnsTopicMonitoring, SqsQueueMonitoring, SqsQueueMonitoringWithDlq, StaticSegmentDynamicAdapter, StepFunctionActivityMonitoring, StepFunctionLambdaIntegrationMonitoring, StepFunctionMonitoring, StepFunctionServiceIntegrationMonitoring, SyntheticsCanaryMonitoring, WafV2Monitoring, IDynamicDashboardSegment #### Methods diff --git a/README.md b/README.md index 706da8b2..c2040ff9 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ You can browse the documentation at https://constructs.dev/packages/cdk-monitori | AWS Load Balancing (`.monitorNetworkLoadBalancer()`, `.monitorFargateApplicationLoadBalancer()`, `.monitorFargateNetworkLoadBalancer()`, `.monitorEc2ApplicationLoadBalancer()`, `.monitorEc2NetworkLoadBalancer()`) | System resources and task health | Unhealthy task count, running tasks count, (for Fargate/Ec2 apps) CPU/memory usage | Use for FargateService or Ec2Service backed by a NetworkLoadBalancer or ApplicationLoadBalancer | | AWS OpenSearch/Elasticsearch (`.monitorOpenSearchCluster()`, `.monitorElasticsearchCluster()`) | Indexing and search latency, disk/memory/CPU usage | Indexing and search latency, disk/memory/CPU usage, cluster status, KMS keys | | | AWS RDS (`.monitorRdsCluster()`) | Query duration, connections, latency, disk/CPU usage | Connections, disk and CPU usage | | +| AWS RDS (`.monitorRdsInstance()`) | Query duration, connections, latency, disk/CPU usage | Connections, disk and CPU usage | | | AWS Redshift (`.monitorRedshiftCluster()`) | Query duration, connections, latency, disk/CPU usage | Query duration, connections, disk and CPU usage | | | AWS S3 Bucket (`.monitorS3Bucket()`) | Bucket size and number of objects | | | | AWS SecretsManager (`.monitorSecretsManager()`) | Max secret count, min secret sount, secret count change | Min/max secret count or change in secret count | | diff --git a/lib/common/url/AwsConsoleUrlFactory.ts b/lib/common/url/AwsConsoleUrlFactory.ts index 2321b9e4..bf9d825b 100644 --- a/lib/common/url/AwsConsoleUrlFactory.ts +++ b/lib/common/url/AwsConsoleUrlFactory.ts @@ -119,6 +119,12 @@ export class AwsConsoleUrlFactory { return this.getAwsConsoleUrl(destinationUrl); } + getRdsInstanceUrl(instanceId: string): string | undefined { + const region = this.awsAccountRegion; + const destinationUrl = `https://${region}.console.aws.amazon.com/rds/home?region=${region}#database:id=${instanceId};is-cluster=false;tab=monitoring`; + return this.getAwsConsoleUrl(destinationUrl); + } + getRedshiftClusterUrl(clusterId: string): string | undefined { const region = this.awsAccountRegion; const destinationUrl = `https://${region}.console.aws.amazon.com/redshiftv2/home?region=${region}#cluster-details?cluster=${clusterId}`; diff --git a/lib/facade/IMonitoringAspect.ts b/lib/facade/IMonitoringAspect.ts index b30c1dd9..ceefe8b1 100644 --- a/lib/facade/IMonitoringAspect.ts +++ b/lib/facade/IMonitoringAspect.ts @@ -19,6 +19,7 @@ import { LambdaFunctionMonitoringOptions, OpenSearchClusterMonitoringOptions, RdsClusterMonitoringOptions, + RdsInstanceMonitoringOptions, RedshiftClusterMonitoringOptions, S3BucketMonitoringOptions, SecretsManagerSecretMonitoringOptions, @@ -63,7 +64,12 @@ export interface MonitoringAspectProps { readonly kinesisFirehose?: MonitoringAspectType; readonly lambda?: MonitoringAspectType; readonly openSearch?: MonitoringAspectType; + /** + * @deprecated Use rdsCluster instead. + */ readonly rds?: MonitoringAspectType; + readonly rdsCluster?: MonitoringAspectType; + readonly rdsInstance?: MonitoringAspectType; readonly redshift?: MonitoringAspectType; readonly s3?: MonitoringAspectType; readonly secretsManager?: MonitoringAspectType; diff --git a/lib/facade/MonitoringAspect.ts b/lib/facade/MonitoringAspect.ts index 49c712e7..da7e08e4 100644 --- a/lib/facade/MonitoringAspect.ts +++ b/lib/facade/MonitoringAspect.ts @@ -64,7 +64,8 @@ export class MonitoringAspect implements IAspect { this.monitorKinesisFirehose(node); this.monitorLambda(node); this.monitorOpenSearch(node); - this.monitorRds(node); + this.monitorRdsCluster(node); + this.monitorRdsInstance(node); this.monitorRedshift(node); this.monitorS3(node); this.monitorSecretsManager(node); @@ -312,8 +313,10 @@ export class MonitoringAspect implements IAspect { } } - private monitorRds(node: IConstruct) { - const [isEnabled, props] = this.getMonitoringDetails(this.props.rds); + private monitorRdsCluster(node: IConstruct) { + const [isEnabled, props] = this.getMonitoringDetails( + this.props.rdsCluster ?? this.props.rds + ); if (isEnabled && node instanceof rds.DatabaseCluster) { this.monitoringFacade.monitorRdsCluster({ cluster: node, @@ -323,6 +326,19 @@ export class MonitoringAspect implements IAspect { } } + private monitorRdsInstance(node: IConstruct) { + const [isEnabled, props] = this.getMonitoringDetails( + this.props.rdsInstance + ); + if (isEnabled && node instanceof rds.DatabaseInstance) { + this.monitoringFacade.monitorRdsInstance({ + instance: node, + alarmFriendlyName: node.node.path, + ...props, + }); + } + } + private monitorRedshift(node: IConstruct) { const [isEnabled, props] = this.getMonitoringDetails(this.props.redshift); if (isEnabled && node instanceof redshift.Cluster) { diff --git a/lib/facade/MonitoringFacade.ts b/lib/facade/MonitoringFacade.ts index 11d066bc..9f50c697 100644 --- a/lib/facade/MonitoringFacade.ts +++ b/lib/facade/MonitoringFacade.ts @@ -94,6 +94,8 @@ import { QueueProcessingFargateServiceMonitoringProps, RdsClusterMonitoring, RdsClusterMonitoringProps, + RdsInstanceMonitoring, + RdsInstanceMonitoringProps, RedshiftClusterMonitoring, RedshiftClusterMonitoringProps, S3BucketMonitoring, @@ -681,6 +683,12 @@ export class MonitoringFacade extends MonitoringScope { return this; } + monitorRdsInstance(props: RdsInstanceMonitoringProps): this { + const segment = new RdsInstanceMonitoring(this, props); + this.addSegment(segment, props); + return this; + } + monitorRedshiftCluster(props: RedshiftClusterMonitoringProps): this { const segment = new RedshiftClusterMonitoring(this, props); this.addSegment(segment, props); diff --git a/lib/monitoring/aws-rds/RdsInstanceMetricFactory.ts b/lib/monitoring/aws-rds/RdsInstanceMetricFactory.ts new file mode 100644 index 00000000..a6b13f0f --- /dev/null +++ b/lib/monitoring/aws-rds/RdsInstanceMetricFactory.ts @@ -0,0 +1,141 @@ +import { DimensionsMap } from "aws-cdk-lib/aws-cloudwatch"; +import { IDatabaseInstance } from "aws-cdk-lib/aws-rds"; + +import { + LatencyType, + MetricFactory, + MetricStatistic, + getLatencyTypeLabel, + getLatencyTypeStatistic, +} from "../../common"; + +const RdsNamespace = "AWS/RDS"; + +export interface RdsInstanceMetricFactoryProps { + /** + * database instance + */ + readonly instance: IDatabaseInstance; +} + +export class RdsInstanceMetricFactory { + readonly instanceIdentifier: string; + readonly instance: IDatabaseInstance; + protected readonly metricFactory: MetricFactory; + protected readonly dimensionsMap: DimensionsMap; + + constructor( + metricFactory: MetricFactory, + props: RdsInstanceMetricFactoryProps + ) { + this.metricFactory = metricFactory; + this.instance = props.instance; + this.instanceIdentifier = props.instance.instanceIdentifier; + this.dimensionsMap = { + DBInstanceIdentifier: this.instanceIdentifier, + }; + } + + metricTotalConnectionCount() { + return this.metricFactory.adaptMetric( + this.instance.metricDatabaseConnections({ + statistic: MetricStatistic.SUM, + label: "Connections: Sum", + }) + ); + } + + metricAverageCpuUsageInPercent() { + return this.metricFactory.adaptMetric( + this.instance.metricCPUUtilization({ + statistic: MetricStatistic.AVERAGE, + label: "CPU Usage", + }) + ); + } + + metricMaxFreeStorageSpace() { + return this.metricFactory.adaptMetric( + this.instance.metricFreeStorageSpace({ + statistic: MetricStatistic.MAX, + label: "FreeStorageSpace: MAX", + }) + ); + } + + metricAverageFreeableMemory() { + return this.metricFactory.adaptMetric( + this.instance.metricFreeableMemory({ + statistic: MetricStatistic.AVERAGE, + label: "FreeStorageSpace: Average", + }) + ); + } + + metricReadLatencyInMillis(latencyType: LatencyType) { + const label = "ReadLatency " + getLatencyTypeLabel(latencyType); + return this.metric( + "ReadLatency", + getLatencyTypeStatistic(latencyType), + label + ); + } + + metricReadThroughput() { + return this.metric( + "ReadThroughput", + MetricStatistic.AVERAGE, + "ReadThroughput: Average" + ); + } + + metricReadIops() { + return this.metricFactory.adaptMetric( + this.instance.metricReadIOPS({ + statistic: MetricStatistic.AVERAGE, + label: "ReadIOPS: Average", + }) + ); + } + + metricWriteLatencyInMillis(latencyType: LatencyType) { + const label = "WriteLatency " + getLatencyTypeLabel(latencyType); + return this.metric( + "WriteLatency", + getLatencyTypeStatistic(latencyType), + label + ); + } + + metricWriteThroughput() { + return this.metric( + "WriteThroughput", + MetricStatistic.AVERAGE, + "WriteThroughput: Average" + ); + } + + metricWriteIops() { + return this.metricFactory.adaptMetric( + this.instance.metricWriteIOPS({ + statistic: MetricStatistic.AVERAGE, + label: "WriteIOPS: Average", + }) + ); + } + + private metric( + metricName: string, + statistic: MetricStatistic, + label: string + ) { + return this.metricFactory.createMetric( + metricName, + statistic, + label, + this.dimensionsMap, + undefined, + RdsNamespace + ); + } +} diff --git a/lib/monitoring/aws-rds/RdsInstanceMonitoring.ts b/lib/monitoring/aws-rds/RdsInstanceMonitoring.ts new file mode 100644 index 00000000..324cd789 --- /dev/null +++ b/lib/monitoring/aws-rds/RdsInstanceMonitoring.ts @@ -0,0 +1,231 @@ +import { + GraphWidget, + HorizontalAnnotation, + IWidget, +} from "aws-cdk-lib/aws-cloudwatch"; + +import { + RdsInstanceMetricFactory, + RdsInstanceMetricFactoryProps, +} from "./RdsInstanceMetricFactory"; +import { + BaseMonitoringProps, + ConnectionAlarmFactory, + CountAxisFromZero, + DefaultGraphWidgetHeight, + DefaultSummaryWidgetHeight, + HalfWidth, + HighConnectionCountThreshold, + LatencyType, + LowConnectionCountThreshold, + MetricWithAlarmSupport, + MinUsageCountThreshold, + Monitoring, + MonitoringScope, + PercentageAxisFromZeroToHundred, + QuarterWidth, + ThirdWidth, + TimeAxisMillisFromZero, + UsageAlarmFactory, + UsageThreshold, +} from "../../common"; +import { + MonitoringHeaderWidget, + MonitoringNamingStrategy, +} from "../../dashboard"; + +export interface RdsInstanceMonitoringOptions extends BaseMonitoringProps { + readonly addFreeStorageSpaceAlarm?: Record; + readonly addCpuUsageAlarm?: Record; + readonly addMinConnectionCountAlarm?: Record< + string, + LowConnectionCountThreshold + >; + readonly addMaxConnectionCountAlarm?: Record< + string, + HighConnectionCountThreshold + >; +} + +export interface RdsInstanceMonitoringProps + extends RdsInstanceMetricFactoryProps, + RdsInstanceMonitoringOptions {} + +export class RdsInstanceMonitoring extends Monitoring { + readonly title: string; + readonly url?: string; + + readonly usageAlarmFactory: UsageAlarmFactory; + readonly connectionAlarmFactory: ConnectionAlarmFactory; + readonly usageAnnotations: HorizontalAnnotation[]; + readonly connectionAnnotations: HorizontalAnnotation[]; + + readonly connectionsMetric: MetricWithAlarmSupport; + readonly freeStorageSpaceMetric: MetricWithAlarmSupport; + readonly freeableMemoryMetric: MetricWithAlarmSupport; + readonly cpuUsageMetric: MetricWithAlarmSupport; + readonly readLatencyMetric: MetricWithAlarmSupport; + readonly readThroughputMetric: MetricWithAlarmSupport; + readonly readIopsMetric: MetricWithAlarmSupport; + readonly writeLatencyMetric: MetricWithAlarmSupport; + readonly writeThroughputMetric: MetricWithAlarmSupport; + readonly writeIopsMetric: MetricWithAlarmSupport; + + constructor(scope: MonitoringScope, props: RdsInstanceMonitoringProps) { + super(scope, props); + + const metricFactory = new RdsInstanceMetricFactory( + scope.createMetricFactory(), + props + ); + this.connectionsMetric = metricFactory.metricTotalConnectionCount(); + this.freeStorageSpaceMetric = metricFactory.metricMaxFreeStorageSpace(); + this.freeableMemoryMetric = metricFactory.metricAverageFreeableMemory(); + this.cpuUsageMetric = metricFactory.metricAverageCpuUsageInPercent(); + this.readLatencyMetric = metricFactory.metricReadLatencyInMillis( + LatencyType.P90 + ); + this.readThroughputMetric = metricFactory.metricReadThroughput(); + this.readIopsMetric = metricFactory.metricReadIops(); + this.writeLatencyMetric = metricFactory.metricWriteLatencyInMillis( + LatencyType.P90 + ); + this.writeThroughputMetric = metricFactory.metricWriteThroughput(); + this.writeIopsMetric = metricFactory.metricWriteIops(); + + const namingStrategy = new MonitoringNamingStrategy({ + ...props, + fallbackConstructName: metricFactory.instanceIdentifier, + namedConstruct: props.instance, + }); + this.title = namingStrategy.resolveHumanReadableName(); + this.url = scope + .createAwsConsoleUrlFactory() + .getRdsInstanceUrl(metricFactory.instanceIdentifier); + const alarmFactory = this.createAlarmFactory( + namingStrategy.resolveAlarmFriendlyName() + ); + this.usageAlarmFactory = new UsageAlarmFactory(alarmFactory); + this.connectionAlarmFactory = new ConnectionAlarmFactory(alarmFactory); + + this.usageAnnotations = []; + this.connectionAnnotations = []; + + for (const disambiguator in props.addFreeStorageSpaceAlarm) { + const alarmProps = props.addFreeStorageSpaceAlarm[disambiguator]; + const createdAlarm = this.usageAlarmFactory.addMinCountAlarm( + this.freeStorageSpaceMetric, + alarmProps, + disambiguator + ); + this.usageAnnotations.push(createdAlarm.annotation); + this.addAlarm(createdAlarm); + } + + for (const disambiguator in props.addCpuUsageAlarm) { + const alarmProps = props.addCpuUsageAlarm[disambiguator]; + const createdAlarm = this.usageAlarmFactory.addMaxCpuUsagePercentAlarm( + this.cpuUsageMetric, + alarmProps, + disambiguator + ); + this.usageAnnotations.push(createdAlarm.annotation); + this.addAlarm(createdAlarm); + } + + for (const disambiguator in props.addMinConnectionCountAlarm) { + const alarmProps = props.addMinConnectionCountAlarm[disambiguator]; + const createdAlarm = + this.connectionAlarmFactory.addMinConnectionCountAlarm( + this.connectionsMetric, + alarmProps, + disambiguator + ); + this.connectionAnnotations.push(createdAlarm.annotation); + this.addAlarm(createdAlarm); + } + + for (const disambiguator in props.addMaxConnectionCountAlarm) { + const alarmProps = props.addMaxConnectionCountAlarm[disambiguator]; + const createdAlarm = + this.connectionAlarmFactory.addMaxConnectionCountAlarm( + this.connectionsMetric, + alarmProps, + disambiguator + ); + this.connectionAnnotations.push(createdAlarm.annotation); + this.addAlarm(createdAlarm); + } + + props.useCreatedAlarms?.consume(this.createdAlarms()); + } + + summaryWidgets(): IWidget[] { + return [ + this.createTitleWidget(), + this.createCpuAndDiskUsageWidget(ThirdWidth, DefaultSummaryWidgetHeight), + this.createConnectionsWidget(ThirdWidth, DefaultSummaryWidgetHeight), + this.createLatencyWidget(ThirdWidth, DefaultSummaryWidgetHeight), + ]; + } + + widgets(): IWidget[] { + return [ + this.createTitleWidget(), + this.createCpuAndDiskUsageWidget(QuarterWidth, DefaultGraphWidgetHeight), + this.createConnectionsWidget(QuarterWidth, DefaultGraphWidgetHeight), + this.createLatencyWidget(HalfWidth, DefaultGraphWidgetHeight), + ]; + } + + createTitleWidget() { + return new MonitoringHeaderWidget({ + family: "RDS Instance", + title: this.title, + goToLinkUrl: this.url, + }); + } + + createCpuAndDiskUsageWidget(width: number, height: number) { + return new GraphWidget({ + width, + height, + title: "CPU/Disk Usage", + left: [ + this.cpuUsageMetric, + this.freeStorageSpaceMetric, + this.freeableMemoryMetric, + ], + leftYAxis: PercentageAxisFromZeroToHundred, + leftAnnotations: this.usageAnnotations, + }); + } + + createConnectionsWidget(width: number, height: number) { + return new GraphWidget({ + width, + height, + title: "Connections", + left: [this.connectionsMetric], + leftYAxis: CountAxisFromZero, + leftAnnotations: this.connectionAnnotations, + }); + } + + createLatencyWidget(width: number, height: number) { + return new GraphWidget({ + width, + height, + title: "Query Duration", + left: [ + this.readLatencyMetric, + this.readThroughputMetric, + this.readIopsMetric, + this.writeLatencyMetric, + this.writeLatencyMetric, + this.writeIopsMetric, + ], + leftYAxis: TimeAxisMillisFromZero, + }); + } +} diff --git a/lib/monitoring/aws-rds/index.ts b/lib/monitoring/aws-rds/index.ts index 0a738d86..beaf9f5b 100644 --- a/lib/monitoring/aws-rds/index.ts +++ b/lib/monitoring/aws-rds/index.ts @@ -1,3 +1,5 @@ export * from "./AuroraClusterMonitoring"; export * from "./RdsClusterMetricFactory"; export * from "./RdsClusterMonitoring"; +export * from "./RdsInstanceMetricFactory"; +export * from "./RdsInstanceMonitoring"; diff --git a/test/monitoring/aws-rds/RdsInstanceMonitoring.test.ts b/test/monitoring/aws-rds/RdsInstanceMonitoring.test.ts new file mode 100644 index 00000000..b8ace0dc --- /dev/null +++ b/test/monitoring/aws-rds/RdsInstanceMonitoring.test.ts @@ -0,0 +1,73 @@ +import { Stack } from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { Vpc } from "aws-cdk-lib/aws-ec2"; +import { DatabaseInstance, DatabaseInstanceEngine } from "aws-cdk-lib/aws-rds"; + +import { RdsInstanceMonitoring } from "../../../lib"; +import { addMonitoringDashboardsToStack } from "../../utils/SnapshotUtil"; +import { TestMonitoringScope } from "../TestMonitoringScope"; + +function createRdsInstance() { + const stack = new Stack(); + const vpc = new Vpc(stack, "Vpc"); + const instance = new DatabaseInstance(stack, "DatabaseInstance", { + instanceIdentifier: "my-rds-instance", + engine: DatabaseInstanceEngine.MYSQL, + vpc: vpc, + }); + return { instance, stack }; +} + +test.each([createRdsInstance])("snapshot test: no alarms - %#", (factory) => { + const { stack, instance } = factory(); + + const scope = new TestMonitoringScope(stack, "Scope"); + const monitoring = new RdsInstanceMonitoring(scope, { + alarmFriendlyName: "DummyRdsInstance", + instance: instance, + }); + + addMonitoringDashboardsToStack(stack, monitoring); + expect(Template.fromStack(stack)).toMatchSnapshot(); +}); + +test.each([createRdsInstance])("snapshot test: all alarms - %#", (factory) => { + const { stack, instance } = factory(); + + const scope = new TestMonitoringScope(stack, "Scope"); + + let numAlarmsCreated = 0; + + const monitoring = new RdsInstanceMonitoring(scope, { + instance: instance, + addFreeStorageSpaceAlarm: { + Warning: { + minCount: 20, + }, + }, + addCpuUsageAlarm: { + Warning: { + maxUsagePercent: 70, + }, + }, + addMinConnectionCountAlarm: { + Warning: { + minConnectionCount: 1, + }, + }, + addMaxConnectionCountAlarm: { + Warning: { + maxConnectionCount: 100, + }, + }, + useCreatedAlarms: { + consume(alarms) { + numAlarmsCreated = alarms.length; + }, + }, + }); + + addMonitoringDashboardsToStack(stack, monitoring); + expect(numAlarmsCreated).toStrictEqual(4); + expect(Template.fromStack(stack)).toMatchSnapshot(); +}); diff --git a/test/monitoring/aws-rds/__snapshots__/RdsInstanceMonitoring.test.ts.snap b/test/monitoring/aws-rds/__snapshots__/RdsInstanceMonitoring.test.ts.snap new file mode 100644 index 00000000..fc100eaf --- /dev/null +++ b/test/monitoring/aws-rds/__snapshots__/RdsInstanceMonitoring.test.ts.snap @@ -0,0 +1,1560 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snapshot test: all alarms - 0 1`] = ` +Object { + "Parameters": Object { + "BootstrapVersion": Object { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": Object { + "Alarm7103F465": Object { + "Properties": Object { + "DashboardBody": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"widgets\\":[{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":4,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"annotations\\":{\\"alarms\\":[\\"", + Object { + "Fn::GetAtt": Array [ + "ScopeTestDatabaseInstanceMinUsageCountWarning32B7AE36", + "Arn", + ], + }, + "\\"]},\\"yAxis\\":{}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":4,\\"x\\":6,\\"y\\":0,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"annotations\\":{\\"alarms\\":[\\"", + Object { + "Fn::GetAtt": Array [ + "ScopeTestDatabaseInstanceCPUUsageWarningEF3425BC", + "Arn", + ], + }, + "\\"]},\\"yAxis\\":{}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":4,\\"x\\":12,\\"y\\":0,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"annotations\\":{\\"alarms\\":[\\"", + Object { + "Fn::GetAtt": Array [ + "ScopeTestDatabaseInstanceConnectionCountLowWarning07BAA2A4", + "Arn", + ], + }, + "\\"]},\\"yAxis\\":{}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":4,\\"x\\":18,\\"y\\":0,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"annotations\\":{\\"alarms\\":[\\"", + Object { + "Fn::GetAtt": Array [ + "ScopeTestDatabaseInstanceConnectionCountHighWarningD026F033", + "Arn", + ], + }, + "\\"]},\\"yAxis\\":{}}}]}", + ], + ], + }, + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "DatabaseInstance24D16791": Object { + "DeletionPolicy": "Snapshot", + "Properties": Object { + "AllocatedStorage": "100", + "CopyTagsToSnapshot": true, + "DBInstanceClass": "db.m5.large", + "DBInstanceIdentifier": "my-rds-instance", + "DBSubnetGroupName": Object { + "Ref": "DatabaseInstanceSubnetGroupA4FFF2A4", + }, + "Engine": "mysql", + "MasterUserPassword": Object { + "Fn::Join": Array [ + "", + Array [ + "{{resolve:secretsmanager:", + Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + ":SecretString:password::}}", + ], + ], + }, + "MasterUsername": Object { + "Fn::Join": Array [ + "", + Array [ + "{{resolve:secretsmanager:", + Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + ":SecretString:username::}}", + ], + ], + }, + "StorageType": "gp2", + "VPCSecurityGroups": Array [ + Object { + "Fn::GetAtt": Array [ + "DatabaseInstanceSecurityGroup8BDF0112", + "GroupId", + ], + }, + ], + }, + "Type": "AWS::RDS::DBInstance", + "UpdateReplacePolicy": "Snapshot", + }, + "DatabaseInstanceSecret2C9E2EE4": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "Description": Object { + "Fn::Join": Array [ + "", + Array [ + "Generated by the CDK for stack: ", + Object { + "Ref": "AWS::StackName", + }, + ], + ], + }, + "GenerateSecretString": Object { + "ExcludeCharacters": " %+~\`#$&*()|[]{}:;<>?!'/@\\"\\\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\\"username\\":\\"admin\\"}", + }, + }, + "Type": "AWS::SecretsManager::Secret", + "UpdateReplacePolicy": "Delete", + }, + "DatabaseInstanceSecretAttachmentF5C7BAE8": Object { + "Properties": Object { + "SecretId": Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + "TargetId": Object { + "Ref": "DatabaseInstance24D16791", + }, + "TargetType": "AWS::RDS::DBInstance", + }, + "Type": "AWS::SecretsManager::SecretTargetAttachment", + }, + "DatabaseInstanceSecurityGroup8BDF0112": Object { + "Properties": Object { + "GroupDescription": "Security group for DatabaseInstance database", + "SecurityGroupEgress": Array [ + Object { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "DatabaseInstanceSubnetGroupA4FFF2A4": Object { + "Properties": Object { + "DBSubnetGroupDescription": "Subnet group for DatabaseInstance database", + "SubnetIds": Array [ + Object { + "Ref": "VpcPrivateSubnet1Subnet536B997A", + }, + Object { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1", + }, + ], + }, + "Type": "AWS::RDS::DBSubnetGroup", + }, + "Resource": Object { + "Properties": Object { + "DashboardBody": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### RDS Instance **[DatabaseInstance](https://eu-west-1.console.aws.amazon.com/rds/home?region=eu-west-1#database:id=", + Object { + "Ref": "DatabaseInstance24D16791", + }, + ";is-cluster=false;tab=monitoring)**\\"}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":5,\\"x\\":0,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"CPU/Disk Usage\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"CPUUtilization\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"CPU Usage\\"}],[\\"AWS/RDS\\",\\"FreeStorageSpace\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: MAX\\",\\"stat\\":\\"Maximum\\"}],[\\"AWS/RDS\\",\\"FreeableMemory\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: Average\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"FreeStorageSpace: MAX < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"CPU Usage > 70 for 3 datapoints within 15 minutes\\",\\"value\\":70,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"max\\":100,\\"label\\":\\"%\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":5,\\"x\\":6,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Connections\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"DatabaseConnections\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"Connections: Sum\\",\\"stat\\":\\"Sum\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Connections: Sum < 1 for 3 datapoints within 15 minutes\\",\\"value\\":1,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"Connections: Sum > 100 for 3 datapoints within 15 minutes\\",\\"value\\":100,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":12,\\"height\\":5,\\"x\\":12,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Query Duration\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"ReadLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"ReadThroughput\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadThroughput: Average\\"}],[\\"AWS/RDS\\",\\"ReadIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadIOPS: Average\\"}],[\\"AWS/RDS\\",\\"WriteLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"WriteIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteIOPS: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"ms\\",\\"showUnits\\":false}}}}]}", + ], + ], + }, + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "ScopeTestDatabaseInstanceCPUUsageWarningEF3425BC": Object { + "Properties": Object { + "ActionsEnabled": true, + "AlarmDescription": "The CPU usage is too high.", + "AlarmName": "Test-DatabaseInstance-CPU-Usage-Warning", + "ComparisonOperator": "GreaterThanThreshold", + "DatapointsToAlarm": 3, + "EvaluationPeriods": 3, + "Metrics": Array [ + Object { + "Id": "m1", + "Label": "CPU Usage", + "MetricStat": Object { + "Metric": Object { + "Dimensions": Array [ + Object { + "Name": "DBInstanceIdentifier", + "Value": Object { + "Ref": "DatabaseInstance24D16791", + }, + }, + ], + "MetricName": "CPUUtilization", + "Namespace": "AWS/RDS", + }, + "Period": 300, + "Stat": "Average", + }, + "ReturnData": true, + }, + ], + "Threshold": 70, + "TreatMissingData": "missing", + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "ScopeTestDatabaseInstanceConnectionCountHighWarningD026F033": Object { + "Properties": Object { + "ActionsEnabled": true, + "AlarmDescription": "Number of connections is too high.", + "AlarmName": "Test-DatabaseInstance-Connection-Count-High-Warning", + "ComparisonOperator": "GreaterThanThreshold", + "DatapointsToAlarm": 3, + "EvaluationPeriods": 3, + "Metrics": Array [ + Object { + "Id": "m1", + "Label": "Connections: Sum", + "MetricStat": Object { + "Metric": Object { + "Dimensions": Array [ + Object { + "Name": "DBInstanceIdentifier", + "Value": Object { + "Ref": "DatabaseInstance24D16791", + }, + }, + ], + "MetricName": "DatabaseConnections", + "Namespace": "AWS/RDS", + }, + "Period": 300, + "Stat": "Sum", + }, + "ReturnData": true, + }, + ], + "Threshold": 100, + "TreatMissingData": "missing", + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "ScopeTestDatabaseInstanceConnectionCountLowWarning07BAA2A4": Object { + "Properties": Object { + "ActionsEnabled": true, + "AlarmDescription": "Number of connections is too low.", + "AlarmName": "Test-DatabaseInstance-Connection-Count-Low-Warning", + "ComparisonOperator": "LessThanThreshold", + "DatapointsToAlarm": 3, + "EvaluationPeriods": 3, + "Metrics": Array [ + Object { + "Id": "m1", + "Label": "Connections: Sum", + "MetricStat": Object { + "Metric": Object { + "Dimensions": Array [ + Object { + "Name": "DBInstanceIdentifier", + "Value": Object { + "Ref": "DatabaseInstance24D16791", + }, + }, + ], + "MetricName": "DatabaseConnections", + "Namespace": "AWS/RDS", + }, + "Period": 300, + "Stat": "Sum", + }, + "ReturnData": true, + }, + ], + "Threshold": 1, + "TreatMissingData": "missing", + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "ScopeTestDatabaseInstanceMinUsageCountWarning32B7AE36": Object { + "Properties": Object { + "ActionsEnabled": true, + "AlarmDescription": "The count is too low.", + "AlarmName": "Test-DatabaseInstance-Min-Usage-Count-Warning", + "ComparisonOperator": "LessThanThreshold", + "DatapointsToAlarm": 3, + "EvaluationPeriods": 3, + "Metrics": Array [ + Object { + "Id": "m1", + "Label": "FreeStorageSpace: MAX", + "MetricStat": Object { + "Metric": Object { + "Dimensions": Array [ + Object { + "Name": "DBInstanceIdentifier", + "Value": Object { + "Ref": "DatabaseInstance24D16791", + }, + }, + ], + "MetricName": "FreeStorageSpace", + "Namespace": "AWS/RDS", + }, + "Period": 300, + "Stat": "Maximum", + }, + "ReturnData": true, + }, + ], + "Threshold": 20, + "TreatMissingData": "missing", + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "Summary68521F81": Object { + "Properties": Object { + "DashboardBody": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### RDS Instance **[DatabaseInstance](https://eu-west-1.console.aws.amazon.com/rds/home?region=eu-west-1#database:id=", + Object { + "Ref": "DatabaseInstance24D16791", + }, + ";is-cluster=false;tab=monitoring)**\\"}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":0,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"CPU/Disk Usage\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"CPUUtilization\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"CPU Usage\\"}],[\\"AWS/RDS\\",\\"FreeStorageSpace\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: MAX\\",\\"stat\\":\\"Maximum\\"}],[\\"AWS/RDS\\",\\"FreeableMemory\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: Average\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"FreeStorageSpace: MAX < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"CPU Usage > 70 for 3 datapoints within 15 minutes\\",\\"value\\":70,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"max\\":100,\\"label\\":\\"%\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":8,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Connections\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"DatabaseConnections\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"Connections: Sum\\",\\"stat\\":\\"Sum\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Connections: Sum < 1 for 3 datapoints within 15 minutes\\",\\"value\\":1,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"Connections: Sum > 100 for 3 datapoints within 15 minutes\\",\\"value\\":100,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":16,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Query Duration\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"ReadLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"ReadThroughput\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadThroughput: Average\\"}],[\\"AWS/RDS\\",\\"ReadIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadIOPS: Average\\"}],[\\"AWS/RDS\\",\\"WriteLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"WriteIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteIOPS: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"ms\\",\\"showUnits\\":false}}}}]}", + ], + ], + }, + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "Vpc8378EB38": Object { + "Properties": Object { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc", + }, + ], + }, + "Type": "AWS::EC2::VPC", + }, + "VpcIGWD7BA715C": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc", + }, + ], + }, + "Type": "AWS::EC2::InternetGateway", + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": Object { + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": Object { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA", + }, + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500", + }, + "SubnetId": Object { + "Ref": "VpcPrivateSubnet1Subnet536B997A", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPrivateSubnet1RouteTableB2C5B500": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPrivateSubnet1Subnet536B997A": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPrivateSubnet2DefaultRoute060D2087": Object { + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": Object { + "Ref": "VpcPublicSubnet2NATGateway9182C01D", + }, + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet2RouteTableA678073B", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPrivateSubnet2RouteTableA678073B": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet2RouteTableA678073B", + }, + "SubnetId": Object { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPrivateSubnet2Subnet3788AAA1": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": Object { + "DependsOn": Array [ + "VpcVPCGWBF912B6E", + ], + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "RouteTableId": Object { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPublicSubnet1EIPD7E02669": Object { + "Properties": Object { + "Domain": "vpc", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "VpcPublicSubnet1NATGateway4D7517AA": Object { + "DependsOn": Array [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677", + ], + "Properties": Object { + "AllocationId": Object { + "Fn::GetAtt": Array [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId", + ], + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4", + }, + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "VpcPublicSubnet1RouteTable6C95E38E": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPublicSubnet1RouteTableAssociation97140677": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E", + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPublicSubnet1Subnet5C2D37C4": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPublicSubnet2DefaultRoute97F91067": Object { + "DependsOn": Array [ + "VpcVPCGWBF912B6E", + ], + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "RouteTableId": Object { + "Ref": "VpcPublicSubnet2RouteTable94F7E489", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPublicSubnet2EIP3C605A87": Object { + "Properties": Object { + "Domain": "vpc", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "VpcPublicSubnet2NATGateway9182C01D": Object { + "DependsOn": Array [ + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTableAssociationDD5762D8", + ], + "Properties": Object { + "AllocationId": Object { + "Fn::GetAtt": Array [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId", + ], + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet2Subnet691E08A3", + }, + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "VpcPublicSubnet2RouteTable94F7E489": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPublicSubnet2RouteTable94F7E489", + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet2Subnet691E08A3", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPublicSubnet2Subnet691E08A3": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcVPCGWBF912B6E": Object { + "Properties": Object { + "InternetGatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::VPCGatewayAttachment", + }, + }, + "Rules": Object { + "CheckBootstrapVersion": Object { + "Assertions": Array [ + Object { + "Assert": Object { + "Fn::Not": Array [ + Object { + "Fn::Contains": Array [ + Array [ + "1", + "2", + "3", + "4", + "5", + ], + Object { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + +exports[`snapshot test: no alarms - 0 1`] = ` +Object { + "Parameters": Object { + "BootstrapVersion": Object { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": Object { + "Alarm7103F465": Object { + "Properties": Object { + "DashboardBody": "{\\"widgets\\":[]}", + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "DatabaseInstance24D16791": Object { + "DeletionPolicy": "Snapshot", + "Properties": Object { + "AllocatedStorage": "100", + "CopyTagsToSnapshot": true, + "DBInstanceClass": "db.m5.large", + "DBInstanceIdentifier": "my-rds-instance", + "DBSubnetGroupName": Object { + "Ref": "DatabaseInstanceSubnetGroupA4FFF2A4", + }, + "Engine": "mysql", + "MasterUserPassword": Object { + "Fn::Join": Array [ + "", + Array [ + "{{resolve:secretsmanager:", + Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + ":SecretString:password::}}", + ], + ], + }, + "MasterUsername": Object { + "Fn::Join": Array [ + "", + Array [ + "{{resolve:secretsmanager:", + Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + ":SecretString:username::}}", + ], + ], + }, + "StorageType": "gp2", + "VPCSecurityGroups": Array [ + Object { + "Fn::GetAtt": Array [ + "DatabaseInstanceSecurityGroup8BDF0112", + "GroupId", + ], + }, + ], + }, + "Type": "AWS::RDS::DBInstance", + "UpdateReplacePolicy": "Snapshot", + }, + "DatabaseInstanceSecret2C9E2EE4": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "Description": Object { + "Fn::Join": Array [ + "", + Array [ + "Generated by the CDK for stack: ", + Object { + "Ref": "AWS::StackName", + }, + ], + ], + }, + "GenerateSecretString": Object { + "ExcludeCharacters": " %+~\`#$&*()|[]{}:;<>?!'/@\\"\\\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\\"username\\":\\"admin\\"}", + }, + }, + "Type": "AWS::SecretsManager::Secret", + "UpdateReplacePolicy": "Delete", + }, + "DatabaseInstanceSecretAttachmentF5C7BAE8": Object { + "Properties": Object { + "SecretId": Object { + "Ref": "DatabaseInstanceSecret2C9E2EE4", + }, + "TargetId": Object { + "Ref": "DatabaseInstance24D16791", + }, + "TargetType": "AWS::RDS::DBInstance", + }, + "Type": "AWS::SecretsManager::SecretTargetAttachment", + }, + "DatabaseInstanceSecurityGroup8BDF0112": Object { + "Properties": Object { + "GroupDescription": "Security group for DatabaseInstance database", + "SecurityGroupEgress": Array [ + Object { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "DatabaseInstanceSubnetGroupA4FFF2A4": Object { + "Properties": Object { + "DBSubnetGroupDescription": "Subnet group for DatabaseInstance database", + "SubnetIds": Array [ + Object { + "Ref": "VpcPrivateSubnet1Subnet536B997A", + }, + Object { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1", + }, + ], + }, + "Type": "AWS::RDS::DBSubnetGroup", + }, + "Resource": Object { + "Properties": Object { + "DashboardBody": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### RDS Instance **[DatabaseInstance](https://eu-west-1.console.aws.amazon.com/rds/home?region=eu-west-1#database:id=", + Object { + "Ref": "DatabaseInstance24D16791", + }, + ";is-cluster=false;tab=monitoring)**\\"}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":5,\\"x\\":0,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"CPU/Disk Usage\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"CPUUtilization\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"CPU Usage\\"}],[\\"AWS/RDS\\",\\"FreeStorageSpace\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: MAX\\",\\"stat\\":\\"Maximum\\"}],[\\"AWS/RDS\\",\\"FreeableMemory\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"max\\":100,\\"label\\":\\"%\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":5,\\"x\\":6,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Connections\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"DatabaseConnections\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"Connections: Sum\\",\\"stat\\":\\"Sum\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":12,\\"height\\":5,\\"x\\":12,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Query Duration\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"ReadLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"ReadThroughput\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadThroughput: Average\\"}],[\\"AWS/RDS\\",\\"ReadIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadIOPS: Average\\"}],[\\"AWS/RDS\\",\\"WriteLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"WriteIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteIOPS: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"ms\\",\\"showUnits\\":false}}}}]}", + ], + ], + }, + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "Summary68521F81": Object { + "Properties": Object { + "DashboardBody": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### RDS Instance **[DatabaseInstance](https://eu-west-1.console.aws.amazon.com/rds/home?region=eu-west-1#database:id=", + Object { + "Ref": "DatabaseInstance24D16791", + }, + ";is-cluster=false;tab=monitoring)**\\"}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":0,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"CPU/Disk Usage\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"CPUUtilization\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"CPU Usage\\"}],[\\"AWS/RDS\\",\\"FreeStorageSpace\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: MAX\\",\\"stat\\":\\"Maximum\\"}],[\\"AWS/RDS\\",\\"FreeableMemory\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"FreeStorageSpace: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"max\\":100,\\"label\\":\\"%\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":8,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Connections\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"DatabaseConnections\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"Connections: Sum\\",\\"stat\\":\\"Sum\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}},{\\"type\\":\\"metric\\",\\"width\\":8,\\"height\\":6,\\"x\\":16,\\"y\\":1,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"title\\":\\"Query Duration\\",\\"region\\":\\"", + Object { + "Ref": "AWS::Region", + }, + "\\",\\"metrics\\":[[\\"AWS/RDS\\",\\"ReadLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"ReadThroughput\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadThroughput: Average\\"}],[\\"AWS/RDS\\",\\"ReadIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"ReadIOPS: Average\\"}],[\\"AWS/RDS\\",\\"WriteLatency\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteLatency P90 (avg: \${AVG})\\",\\"stat\\":\\"p90\\"}],[\\"AWS/RDS\\",\\"WriteIOPS\\",\\"DBInstanceIdentifier\\",\\"", + Object { + "Ref": "DatabaseInstance24D16791", + }, + "\\",{\\"label\\":\\"WriteIOPS: Average\\"}]],\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"ms\\",\\"showUnits\\":false}}}}]}", + ], + ], + }, + }, + "Type": "AWS::CloudWatch::Dashboard", + }, + "Vpc8378EB38": Object { + "Properties": Object { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc", + }, + ], + }, + "Type": "AWS::EC2::VPC", + }, + "VpcIGWD7BA715C": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc", + }, + ], + }, + "Type": "AWS::EC2::InternetGateway", + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": Object { + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": Object { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA", + }, + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500", + }, + "SubnetId": Object { + "Ref": "VpcPrivateSubnet1Subnet536B997A", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPrivateSubnet1RouteTableB2C5B500": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPrivateSubnet1Subnet536B997A": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPrivateSubnet2DefaultRoute060D2087": Object { + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": Object { + "Ref": "VpcPublicSubnet2NATGateway9182C01D", + }, + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet2RouteTableA678073B", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPrivateSubnet2RouteTableA678073B": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPrivateSubnet2RouteTableA678073B", + }, + "SubnetId": Object { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPrivateSubnet2Subnet3788AAA1": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PrivateSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": Object { + "DependsOn": Array [ + "VpcVPCGWBF912B6E", + ], + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "RouteTableId": Object { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPublicSubnet1EIPD7E02669": Object { + "Properties": Object { + "Domain": "vpc", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "VpcPublicSubnet1NATGateway4D7517AA": Object { + "DependsOn": Array [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677", + ], + "Properties": Object { + "AllocationId": Object { + "Fn::GetAtt": Array [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId", + ], + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4", + }, + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "VpcPublicSubnet1RouteTable6C95E38E": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPublicSubnet1RouteTableAssociation97140677": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E", + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPublicSubnet1Subnet5C2D37C4": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet1", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcPublicSubnet2DefaultRoute97F91067": Object { + "DependsOn": Array [ + "VpcVPCGWBF912B6E", + ], + "Properties": Object { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "RouteTableId": Object { + "Ref": "VpcPublicSubnet2RouteTable94F7E489", + }, + }, + "Type": "AWS::EC2::Route", + }, + "VpcPublicSubnet2EIP3C605A87": Object { + "Properties": Object { + "Domain": "vpc", + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "VpcPublicSubnet2NATGateway9182C01D": Object { + "DependsOn": Array [ + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTableAssociationDD5762D8", + ], + "Properties": Object { + "AllocationId": Object { + "Fn::GetAtt": Array [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId", + ], + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet2Subnet691E08A3", + }, + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "VpcPublicSubnet2RouteTable94F7E489": Object { + "Properties": Object { + "Tags": Array [ + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": Object { + "Properties": Object { + "RouteTableId": Object { + "Ref": "VpcPublicSubnet2RouteTable94F7E489", + }, + "SubnetId": Object { + "Ref": "VpcPublicSubnet2Subnet691E08A3", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "VpcPublicSubnet2Subnet691E08A3": Object { + "Properties": Object { + "AvailabilityZone": Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::GetAZs": "", + }, + ], + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": Array [ + Object { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + Object { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + Object { + "Key": "Name", + "Value": "Default/Vpc/PublicSubnet2", + }, + ], + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "VpcVPCGWBF912B6E": Object { + "Properties": Object { + "InternetGatewayId": Object { + "Ref": "VpcIGWD7BA715C", + }, + "VpcId": Object { + "Ref": "Vpc8378EB38", + }, + }, + "Type": "AWS::EC2::VPCGatewayAttachment", + }, + }, + "Rules": Object { + "CheckBootstrapVersion": Object { + "Assertions": Array [ + Object { + "Assert": Object { + "Fn::Not": Array [ + Object { + "Fn::Contains": Array [ + Array [ + "1", + "2", + "3", + "4", + "5", + ], + Object { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`;