Skip to content

Commit

Permalink
feat(rds): add support for Aurora Serverless Clusters (#395)
Browse files Browse the repository at this point in the history
Added new AuroraCluster Monitoring with Aurora specific metrics/alarms.

Fixes #217

---

_By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache-2.0 license_
  • Loading branch information
zqumei0 authored Nov 9, 2023
1 parent 84609a4 commit 3c1f088
Show file tree
Hide file tree
Showing 13 changed files with 2,415 additions and 10 deletions.
1,235 changes: 1,227 additions & 8 deletions API.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ You can browse the documentation at https://constructs.dev/packages/cdk-monitori
| AWS API Gateway (REST API) (`.monitorApiGateway()`) | TPS, latency, errors | Latency, error count/rate, low/high TPS | To see metrics, you have to enable Advanced Monitoring |
| AWS API Gateway V2 (HTTP API) (`.monitorApiGatewayV2HttpApi()`) | TPS, latency, errors | Latency, error count/rate, low/high TPS | To see route level metrics, you have to enable Advanced Monitoring |
| AWS AppSync (GraphQL API) (`.monitorAppSyncApi()`) | TPS, latency, errors | Latency, error count/rate, low/high TPS | |
| Amazon Aurora (`.monitorAuroraCluster()`) | Query duration, connections, latency, CPU usage, Serverless Database Capacity | Connections, Serverless Database Capacity and CPU usage | |
| AWS Billing (`.monitorBilling()`) | AWS account cost | Total cost (anomaly) | [Requires enabling](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/gs_monitor_estimated_charges_with_cloudwatch.html#gs_turning_on_billing_metrics) the **Receive Billing Alerts** option in AWS Console / Billing Preferences |
| AWS Certificate Manager (`.monitorCertificate()`) | Certificate expiration | Days until expiration | |
| AWS CloudFront (`.monitorCloudFrontDistribution()`) | TPS, traffic, latency, errors | Error rate, low/high TPS | |
Expand Down
39 changes: 39 additions & 0 deletions lib/common/monitoring/alarms/AuroraAlarmFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
ComparisonOperator,
TreatMissingData,
} from "aws-cdk-lib/aws-cloudwatch";

import { AlarmFactory, CustomAlarmThreshold } from "../../alarm";
import { MetricWithAlarmSupport } from "../../metric";

export interface HighServerlessDatabaseCapacityThreshold
extends CustomAlarmThreshold {
readonly maxServerlessDatabaseCapacity: number;
}

export class AuroraAlarmFactory {
protected readonly alarmFactory: AlarmFactory;

constructor(alarmFactory: AlarmFactory) {
this.alarmFactory = alarmFactory;
}

addMaxServerlessDatabaseCapacity(
metric: MetricWithAlarmSupport,
props: HighServerlessDatabaseCapacityThreshold,
disambiguator?: string
) {
return this.alarmFactory.addAlarm(metric, {
treatMissingData:
props.treatMissingDataOverride ?? TreatMissingData.MISSING,
comparisonOperator:
props.comparisonOperatorOverride ??
ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxServerlessDatabaseCapacity,
alarmNameSuffix: "Serverless-Database-Capacity-High",
alarmDescription: "Serverless Database Capacity usage is too high.",
});
}
}
19 changes: 19 additions & 0 deletions lib/common/monitoring/alarms/UsageAlarmFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ export class UsageAlarmFactory {
this.alarmFactory = alarmFactory;
}

addMaxUsageCountAlarm(
metric: MetricWithAlarmSupport,
props: UsageCountThreshold,
disambiguator?: string
) {
return this.alarmFactory.addAlarm(metric, {
treatMissingData:
props.treatMissingDataOverride ?? TreatMissingData.MISSING,
comparisonOperator:
props.comparisonOperatorOverride ??
ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxUsageCount,
alarmNameSuffix: "Usage-Count",
alarmDescription: "The count is too high.",
});
}

addMinUsageCountAlarm(
percentMetric: MetricWithAlarmSupport,
props: MinUsageCountThreshold,
Expand Down
1 change: 1 addition & 0 deletions lib/common/monitoring/alarms/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from "./AgeAlarmFactory";
export * from "./AnomalyDetectingAlarmFactory";
export * from "./AuroraAlarmFactory";
export * from "./CustomAlarmFactory";
export * from "./ConnectionAlarmFactory";
export * from "./DynamoAlarmFactory";
Expand Down
2 changes: 2 additions & 0 deletions lib/facade/IMonitoringAspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ApiGatewayMonitoringOptions,
ApiGatewayV2MonitoringOptions,
AppSyncMonitoringOptions,
AuroraClusterMonitoringOptions,
AutoScalingGroupMonitoringOptions,
BillingMonitoringOptions,
CertificateManagerMonitoringOptions,
Expand Down Expand Up @@ -47,6 +48,7 @@ export interface MonitoringAspectProps {
readonly apiGateway?: MonitoringAspectType<ApiGatewayMonitoringOptions>;
readonly apiGatewayV2?: MonitoringAspectType<ApiGatewayV2MonitoringOptions>;
readonly appSync?: MonitoringAspectType<AppSyncMonitoringOptions>;
readonly auroraCluster?: MonitoringAspectType<AuroraClusterMonitoringOptions>;
readonly autoScalingGroup?: MonitoringAspectType<AutoScalingGroupMonitoringOptions>;
readonly billing?: MonitoringAspectType<BillingMonitoringOptions>;
readonly cloudFront?: MonitoringAspectType<CloudFrontDistributionMonitoringOptions>;
Expand Down
14 changes: 14 additions & 0 deletions lib/facade/MonitoringAspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class MonitoringAspect implements IAspect {
this.monitorApiGateway(node);
this.monitorApiGatewayV2(node);
this.monitorAppSync(node);
this.monitorAuroraCluster(node);
this.monitorAutoScalingGroup(node);
this.monitorCloudFront(node);
this.monitorCodeBuild(node);
Expand Down Expand Up @@ -135,6 +136,19 @@ export class MonitoringAspect implements IAspect {
}
}

private monitorAuroraCluster(node: IConstruct) {
const [isEnabled, props] = this.getMonitoringDetails(
this.props.auroraCluster
);
if (isEnabled && node instanceof rds.ServerlessCluster) {
this.monitoringFacade.monitorAuroraCluster({
cluster: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}

private monitorAutoScalingGroup(node: IConstruct) {
const [isEnabled, props] = this.getMonitoringDetails(
this.props.autoScalingGroup
Expand Down
8 changes: 8 additions & 0 deletions lib/facade/MonitoringFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import {
ApiGatewayV2HttpApiMonitoringProps,
AppSyncMonitoring,
AppSyncMonitoringProps,
AuroraClusterMonitoring,
AuroraClusterMonitoringProps,
AutoScalingGroupMonitoring,
AutoScalingGroupMonitoringProps,
BillingMonitoring,
Expand Down Expand Up @@ -415,6 +417,12 @@ export class MonitoringFacade extends MonitoringScope {
return this;
}

monitorAuroraCluster(props: AuroraClusterMonitoringProps) {
const segment = new AuroraClusterMonitoring(this, props);
this.addSegment(segment, props);
return this;
}

monitorCertificate(props: CertificateManagerMonitoringProps) {
const segment = new CertificateManagerMonitoring(this, props);
this.addSegment(segment, props);
Expand Down
Loading

0 comments on commit 3c1f088

Please sign in to comment.