Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/databases/rds-aurora-mysql-dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';;
import { Construct } from 'constructs';

interface TmRdsAuroraMysqlDashboardProps {
clusterIdentifier: string;
dashboardName?: string;
}

export class TmRdsAuroraMysqlDashboard extends Construct {
constructor(scope: Construct, id: string, props: TmRdsAuroraMysqlDashboardProps) {
super(scope, id);

const logGroupName = `/aws/rds/cluster/${props.clusterIdentifier}/slowquery`;

// Dashboard creation
const dashboard = new cloudwatch.Dashboard(this, 'RdsAuroraMysqlDashboard', {
dashboardName: props.dashboardName || 'MysqlDashboard',
});

// 2. Widget : Top 20 slowest queries (Table)
const slowQueryList = new cloudwatch.LogQueryWidget({
title: 'Top 20 Slowest Queries',
logGroupNames: [logGroupName],
view: cloudwatch.LogQueryVisualizationType.TABLE,
width: 24,
height: 8,
queryString: `
fields @timestamp
| filter @message like /Query_time:/
| parse @message "# Query_time: * Lock_time: * Rows_sent: * Rows_examined: *"
as query_time, lock_time, rows_sent, rows_examined
| sort query_time desc
| limit 20
`,
});


// 3. Widget : average response time (Graphic)
const latencyOverTime = new cloudwatch.LogQueryWidget({
title: 'Average Latency (seconds) over time',
logGroupNames: [logGroupName],
view: cloudwatch.LogQueryVisualizationType.LINE,
width: 12,
height: 6,
queryString: `
fields @timestamp, @message
| parse @message "Query_time: * " as duration
| stats avg(duration) by bin(5m)
`,
});

// 4. Widget : slow queries volume per minute
const volumeWidget = new cloudwatch.LogQueryWidget({
title: 'Slow Query Count per minute',
logGroupNames: [logGroupName],
view: cloudwatch.LogQueryVisualizationType.BAR,
width: 12,
height: 6,
queryString: `
stats count(*) by bin(1m)
`,
});

dashboard.addWidgets(latencyOverTime, volumeWidget);
dashboard.addWidgets(slowQueryList);
}
}
24 changes: 21 additions & 3 deletions src/databases/rds-aurora-mysql-serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ export class TmRdsAuroraMysqlServerless extends rds.DatabaseCluster {
props?: TmRdsAuroraMysqlServerlessProps,
) {

// Define default engine
const clusterEngine = rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_08_1,
});

// Default Parameter group
const defaultParameterGroup = new rds.ParameterGroup(scope, `${id}ParametersGroup`, {
engine: clusterEngine,
parameters: {
sql_mode: 'NO_ENGINE_SUBSTITUTION',
max_connections: '500',
wait_timeout: '60',
// Enable slow query logs
slow_query_log: '1',
long_query_time: '3',
log_output: 'FILE',
},
});

const performanceInsightRetention = rds.PerformanceInsightRetention.DEFAULT;
// Conditionally create the writer instance props
const writerProps = props?.provisionedInstanceType
Expand All @@ -47,9 +66,8 @@ export class TmRdsAuroraMysqlServerless extends rds.DatabaseCluster {
* The default properties for the RDS Aurora MySQL Serverless database cluster.
*/
const defaultProps: rds.DatabaseClusterProps = {
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_05_2,
}),
engine: clusterEngine,
parameterGroup: defaultParameterGroup,
writer: writerProps,
credentials: rds.Credentials.fromUsername('admin'), // The master credentials for the database
// to true in production
Expand Down
Loading