Skip to content

Instantly share code, notes, and snippets.

@braska
Last active July 29, 2023 23:17
Show Gist options
  • Save braska/6f622fdac92d8c66d9d69300d480fbed to your computer and use it in GitHub Desktop.
Save braska/6f622fdac92d8c66d9d69300d480fbed to your computer and use it in GitHub Desktop.
Cross-stage Cloudwatch dashboard
interface ApplicationStackProps extends StackProps {
dashboardStack: DashboardStack;
}
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props: ApplicationStackProps) {
super(scope, id, props);
const myFunction = new NodejsFunction(this, 'MyFunction', {
functionName: PhysicalName.GENERATE_IF_NEEDED,
// ... other attrs goes here
});
props.dashboardStack.createLambdaObservability('MyFunction', myFunction);
}
}
export class DashboardDeploymentStage extends Stage {
readonly dashboardStack;
constructor(scope: Construct, id: string, props?: StageProps) {
super(scope, id, props);
this.dashboardStack = new DashboardStack(this, 'dashboard');
}
}
export class DashboardStack extends Stack {
readonly dashboard: Dashboard;
readonly widgets: Record<string, cloudwatch.GraphWidget> = {};
constructor(scope: Construct, id: string, props: DashboardProps) {
super(scope, id, props);
this.dashboard = new cloudwatch.Dashboard(this, 'dashboard');
}
createLambdaObservability(name: string, lambdaToMonitor: IFunction) {
let errorsWidget = this.widgets[`${name} Errors`];
const widgetsToAdd: IWidget[] = [];
if (!errorsWidget) {
errorsWidget = new cloudwatch.GraphWidget({
title: `${name} Errors`,
leftYAxis: {
showUnits: true,
},
height: 6,
width: 6,
});
this.widgets[`${name} Errors`] = errorsWidget;
widgetsToAdd.push(errorsWidget as IWidget);
}
errorsWidget.addLeftMetric(
lambdaToMonitor.metricErrors({
label: lambdaToMonitor.env.region,
})
);
let throttlesWidget = this.widgets[`${name} Throttles`];
if (!throttlesWidget) {
throttlesWidget = new cloudwatch.GraphWidget({
title: `${name} Throttles`,
leftYAxis: {
showUnits: true,
},
height: 6,
width: 6,
});
this.widgets[`${name} Throttles`] = throttlesWidget;
widgetsToAdd.push(throttlesWidget as IWidget);
}
throttlesWidget.addLeftMetric(
lambdaToMonitor.metricThrottles({
label: lambdaToMonitor.env.region,
})
);
let invocationsWidget = this.widgets[`${name} Invocations`];
if (!invocationsWidget) {
invocationsWidget = new cloudwatch.GraphWidget({
title: `${name} Invocations`,
leftYAxis: {
showUnits: true,
},
height: 6,
width: 6,
});
this.widgets[`${name} Invocations`] = invocationsWidget;
widgetsToAdd.push(invocationsWidget as IWidget);
}
invocationsWidget.addLeftMetric(
lambdaToMonitor.metricInvocations({
label: lambdaToMonitor.env.region,
})
);
let durationsWidget = this.widgets[`${name} Durations`];
if (!durationsWidget) {
durationsWidget = new cloudwatch.GraphWidget({
title: `${name} Durations`,
leftYAxis: {
showUnits: true,
},
height: 6,
width: 6,
});
this.widgets[`${name} Durations`] = durationsWidget;
widgetsToAdd.push(durationsWidget as IWidget);
}
durationsWidget.addLeftMetric(
lambdaToMonitor.metricDuration({
label: lambdaToMonitor.env.region,
})
);
if (widgetsToAdd.length > 0) {
this.dashboard.addWidgets(...widgetsToAdd);
}
}
}
interface DeploymentStageProps extends StageProps {
dashboardStack: DashboardStack;
}
export class DeploymentStage extends Stage {
constructor(scope: Construct, id: string, props: DeploymentStageProps) {
super(scope, id, props);
new ApplicationStack(this, "ApplicationStack", { dashboardStack: props.dashboardStack });
}
}
export class PipelineStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const source = CodePipelineSource.connection(`${GITHUB_ORGANIZATION}/${GITHUB_REPOSITORY}`, 'main', {
connectionArn: '...',
});
const pipeline = new CodePipeline(this, "Pipeline", {
crossAccountKeys: true,
synth: new CodeBuildStep(this, "SynthStep", {
input: source,
installCommands: ["n auto", "corepack enable", "pnpm install"],
commands: ['pnpm cdk synth'],
}),
});
const dashboardDeploymentStage = new DashboardDeploymentStage(pipelineStack, "dashboard", {
env: { account: '123456789', region: "us-west-2" },
});
const caDeploymentStage = new DeploymentStage(pipelineStack, "ca", {
env: { account: '123456789', region: "ca-central-1" },
dashboardStack: dashboardDeploymentStage.dashboardStack,
});
const usDeploymentStage = new DeploymentStage(pipelineStack, "ca", {
env: { account: '123456789', region: "us-east-1" },
dashboardStack: dashboardDeploymentStage.dashboardStack,
});
dashboardDeploymentStage.synth();
const production = pipeline.addWave("production");
production.addStage(caDeploymentStage);
production.addStage(usDeploymentStage);
pipeline.addStage(dashboardDeploymentStage);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment