diff --git a/src/databases/rds-aurora-mysql-dashboard.ts b/src/databases/rds-aurora-mysql-dashboard.ts new file mode 100644 index 0000000..94b599d --- /dev/null +++ b/src/databases/rds-aurora-mysql-dashboard.ts @@ -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); + } +} \ No newline at end of file diff --git a/src/databases/rds-aurora-mysql-serverless.ts b/src/databases/rds-aurora-mysql-serverless.ts index 30633ae..44b6fe0 100644 --- a/src/databases/rds-aurora-mysql-serverless.ts +++ b/src/databases/rds-aurora-mysql-serverless.ts @@ -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 @@ -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