Cloudwatch Synthetic Canaries

1 minute read

What are canaries?

Canaries are designed to integrate in your cloudwatch infrastructure to continually verify customer experience even when your applications aren’t experiencing real traffic.

cloudwatchcanary

Canaries are Node.js scripts. They create Lambda functions in your account that use Node.js as a framework. Canaries can use the Puppeteer Node.js library to perform functions on your applications. Canaries work over HTTP and HTTPS protocols.

Dashboard and Canary setup

The following canary was created through the dashboard and the nodeJS script was generated by the AWS dashboard.

dashboard

How difficult is this to build?

Generally, building the first user journey is easy with the GUI workflow wizard.

However, the synthetics library is quite simple as far as standard functions go. You can click, verify text, wait, navigate, input text and click-navigate. There are additional plugins for logging.

The API and the CLI

You can review the CLI documents here. https://docs.aws.amazon.com/cli/latest/reference/synthetics/index.html

The additional library functions can be accessed here. https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Function_Library.html

Template

var synthetics = require('Synthetics');
const log = require('SyntheticsLogger');
const flowBuilderBlueprint = async function () {
    // INSERT URL here
    let url = "https://yourdomainhere.com";
    let page = await synthetics.getPage();
    // Navigate to the initial url
    await synthetics.executeStep('navigateToUrl', async function (timeoutInMillis = 15000) {
        await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis});
    });
    // Execute customer steps
    await synthetics.executeStep('customerActions', async function () {
        await page.type("input[id='email-address']", "youremailaddress");
        try {
            await synthetics.takeScreenshot("input", 'result');
        } catch(ex) {
            synthetics.addExecutionError('Unable to capture screenshot.', ex);
        }
        await page.type("input[id='password']", "yourrealpassword");
        try {
            await synthetics.takeScreenshot("input", 'result');
        } catch(ex) {
            synthetics.addExecutionError('Unable to capture screenshot.', ex);
        }
        await page.waitForSelector("[id='some-sign-in-button']", { timeout: 15000 });
        await page.click("[id='some-sign-in-button']");
        try {
            await synthetics.takeScreenshot("click", 'result');
        } catch(ex) {
            synthetics.addExecutionError('Unable to capture screenshot.', ex);
        }
    });
};
exports.handler = async () => {
    return await flowBuilderBlueprint();
};