visit
When you run a CDK command, it starts by executing your code. Usually, this is some file in the project's bin/
directory where your App is created. This will create all of the constructs that you've added to your project, keeping only the level 1 or Cfn*
constructs for the next step.
mkdir dynamo-dashboard
cd dynamo-dashboard
cdk init app --language typescript
First, create a new construct called DynamoDashboard
. Create the class in lib/dynamoDashboard.ts
and make sure it implements IAspect
.
Next, you'll need to add some properties to store the dashboard's state between calls to its visit
method. The first property is a reference to the CloudWatch dashboard that will be updated. The second property will store all of the widgets that you create.
private dashboard: cw.CfnDashboard;
widgets: Array<Widget> = [];
constructor(scope: cdk.Construct, id: string) {
super(scope, id);
// Register this as an aspect
cdk.Aspects.of(scope).add(this);
this.dashboard = new cw.CfnDashboard(this, `Dashboard`, {
dashboardBody: ""
});
}
Adding a widget to the dashboard requires three steps: find a free spot, add a widget object to the widgets
array, and update the dashboard body definition. Use the following method to figure out where the next available spot is. You can change the width/height values, but keep in mind that the dashboard is 24 units wide.
getNextPosition(): {x: number; y: number; width: number; height: number;} {
let x = 0;
let y = 0;
if (this.widgets.length > 0) {
const lastWidget = this.widgets[this.widgets.length - 1];
x = lastWidget.x + lastWidget.width;
y = lastWidget.y;
if (x >= DASHBOARD_WIDTH - 1) {
x = 0;
y += this.props.widgetHeight + 1;
}
}
return {x, y, width: 12, height: 6};
}
Now you can implement the actual visit
method. The first thing you need to do is make sure the node is a DynamoDB table. Since every construct passed into the visit method will be level 1, you will be checking if the node is a CfnTable
instance.
visit(node: cdk.IConstruct): void {
if(node instanceof dynamodb.CfnTable) {
}
}
visit(node: cdk.IConstruct): void {
if (node instanceof dynamo.CfnTable) {
const position = this.getNextPosition();
this.widgets.push({
...position,
type: "metric",
properties: {
metrics: [
[
"AWS/DynamoDB",
"ConsumedReadCapacityUnits",
"TableName",
node.ref,
{ label: "Read (max)" },
],
[".", "ConsumedWriteCapacityUnits", ".", ".", { label: "Write (max)" }],
],
view: "timeSeries",
stacked: false,
region: node.stack.region,
title: node.logicalId,
stat: "Maximum",
period: 300,
liveData: true,
},
});
this.dashboard.dashboardBody = JSON.stringify({ widgets: this.widgets });
}
}
Now comes the fun part, it's time to test your component. Go to your project's default stack and create an instance of the component. Next, add a couple of DynamoDB tables. Even though your visit
method is looking for CfnTable
instances you can use the Table
class since it creates a CfnTable
instance in its constructor.
export class DynamoDashboardStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new DynamoDashboard(this, `DynamoDashboard`);
new dynamo.Table(this, `FirstTable`, {
partitionKey: {
name: "pk",
type: dynamo.AttributeType.STRING,
},
});
new dynamo.Table(this, `SecondTable`, {
partitionKey: {
name: "pk",
type: dynamo.AttributeType.STRING,
},
});
}
}
Everything should be good to go at this point; run cdk deploy
to send your stack to the cloud. Once it's done deploying, open up CloudWatch and find your dashboard. Now enjoy the fact that you don't have to manually add every table to it!
Also Published At:
You can find the final source for this tutorial at