Namespace Amazon.CDK.AWS.Synthetics
Amazon CloudWatch Synthetics Construct Library
Amazon CloudWatch Synthetics allow you to monitor your application by generating synthetic traffic. The traffic is produced by a canary: a configurable script that runs on a schedule. You configure the canary script to follow the same routes and perform the same actions as a user, which allows you to continually verify your user experience even when you don't have any traffic on your applications.
Canary
To illustrate how to use a canary, assume your application defines the following endpoint:
% curl "https://api.example.com/user/books/topbook/"
The Hitchhikers Guide to the Galaxy
The below code defines a canary that will hit the books/topbook
endpoint every 5 minutes:
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
EnvironmentVariables = new Dictionary<string, string> {
{ "stage", "prod" }
}
});
The following is an example of an index.js
file which exports the handler
function:
const synthetics = require('Synthetics');
const log = require('SyntheticsLogger');
const pageLoadBlueprint = async function () {
// Configure the stage of the API using environment variables
const url = `https://api.example.com/${process.env.stage}/user/books/topbook/`;
const page = await synthetics.getPage();
const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
// Wait for page to render. Increase or decrease wait time based on endpoint being monitored.
await page.waitFor(15000);
// This will take a screenshot that will be included in test output artifacts.
await synthetics.takeScreenshot('loaded', 'loaded');
const pageTitle = await page.title();
log.info('Page title: ' + pageTitle);
if (response.status() !== 200) {
throw 'Failed to load page!';
}
};
exports.handler = async () => {
return await pageLoadBlueprint();
};
Note: The function must be called handler
.
The canary will automatically produce a CloudWatch Dashboard:
The Canary code will be executed in a lambda function created by Synthetics on your behalf. The Lambda function includes a custom runtime provided by Synthetics. The provided runtime includes a variety of handy tools such as Puppeteer (for nodejs based one) and Chromium.
To learn more about Synthetics capabilities, check out the docs.
Canary Schedule
You can specify the schedule on which a canary runs by providing a
Schedule
object to the schedule
property.
Configure a run rate of up to 60 minutes with Schedule.rate
:
var schedule = Schedule.Rate(Duration.Minutes(5));
You can also specify a cron expression with Schedule.cron
:
var schedule = Schedule.Cron(new CronOptions {
Hour = "0,8,16"
});
If you want the canary to run just once upon deployment, you can use Schedule.once()
.
Active Tracing
You can choose to enable active AWS X-Ray tracing on canaries that use the syn-nodejs-2.0
or later runtime by setting activeTracing
to true
.
With tracing enabled, traces are sent for all calls made by the canary that use the browser, the AWS SDK, or HTTP or HTTPS modules.
For more information, see Canaries and X-Ray tracing.
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
ActiveTracing = true
});
Memory
You can set the maximum amount of memory the canary can use while running with the memory
property.
using Amazon.CDK;
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
Memory = Size.Mebibytes(1024)
});
Timeout
You can set how long the canary is allowed to run before it must stop with the timeout
property.
using Amazon.CDK;
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
Timeout = Duration.Seconds(60)
});
Deleting underlying resources on canary deletion
When you delete a lambda, the following underlying resources are isolated in your AWS account:
To learn more about these underlying resources, see Synthetics Canaries Deletion.
In the CDK, you can configure your canary to delete the underlying lambda function when the canary is deleted.
This can be provisioned by setting cleanup: Cleanup.LAMBDA
. Note that this
will create a custom resource under the hood that takes care of the lambda deletion for you.
var canary = new Canary(this, "Canary", new CanaryProps {
Test = Test.Custom(new CustomTestOptions {
Handler = "index.handler",
Code = Code.FromInline("/* Synthetics handler code")
}),
Cleanup = Cleanup.LAMBDA,
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2
});
Note: To properly clean up your canary on deletion, you still have to manually delete other resources
like S3 buckets and CloudWatch logs.
Configuring the Canary Script
To configure the script the canary executes, use the test
property. The test
property accepts a Test
instance that can be initialized by the Test
class static methods. Currently, the only implemented method is Test.custom()
, which allows you to bring your own code. In the future, other methods will be added. Test.custom()
accepts code
and handler
properties -- both are required by Synthetics to create a lambda function on your behalf.
The synthetics.Code
class exposes static methods to bundle your code artifacts:
Using the Code
class static initializers:
// To supply the code from a S3 bucket:
using Amazon.CDK.AWS.S3;
// To supply the code inline:
// To supply the code inline:
new Canary(this, "Inline Canary", new CanaryProps {
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromInline("/* Synthetics handler code */"),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2
});
// To supply the code from your local filesystem:
// To supply the code from your local filesystem:
new Canary(this, "Asset Canary", new CanaryProps {
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2
});
var bucket = new Bucket(this, "Code Bucket");
new Canary(this, "Bucket Canary", new CanaryProps {
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromBucket(bucket, "canary.zip"),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2
});
Note: Synthetics have a specified folder structure for canaries. For Node scripts supplied via code.fromAsset()
or code.fromBucket()
, the canary resource requires the following folder structure:
canary/
├── nodejs/
├── node_modules/
├── <filename>.js
For Python scripts supplied via code.fromAsset()
or code.fromBucket()
, the canary resource requires the following folder structure:
canary/
├── python/
├── <filename>.py
See Synthetics docs.
Running a canary on a VPC
You can specify what VPC a canary executes in.
This can allow for monitoring services that may be internal to a specific VPC. To place a canary within a VPC, you can specify the vpc
property with the desired VPC
to place then canary in.
This will automatically attach the appropriate IAM permissions to attach to the VPC. This will also create a Security Group and attach to the default subnets for the VPC unless specified via vpcSubnets
and securityGroups
.
using Amazon.CDK.AWS.EC2;
IVpc vpc;
new Canary(this, "Vpc Canary", new CanaryProps {
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
Vpc = vpc
});
Note: By default, the Synthetics runtime needs access to the S3 and CloudWatch APIs, which will fail in a private subnet without internet access enabled (e.g. an isolated subnnet).
Ensure that the Canary is placed in a VPC either with internet connectivity or with VPC Endpoints for S3 and CloudWatch enabled and configured.
See Synthetics VPC docs.
Alarms
You can configure a CloudWatch Alarm on a canary metric. Metrics are emitted by CloudWatch automatically and can be accessed by the following APIs:
Create an alarm that tracks the canary metric:
using Amazon.CDK.AWS.CloudWatch;
Canary canary;
new Alarm(this, "CanaryAlarm", new AlarmProps {
Metric = canary.MetricSuccessPercent(),
EvaluationPeriods = 2,
Threshold = 90,
ComparisonOperator = ComparisonOperator.LESS_THAN_THRESHOLD
});
Artifacts
You can pass an S3 bucket to store artifacts from canary runs. If you do not, one will be auto-generated when the canary is created. You may add lifecycle rules to the auto-generated bucket.
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2,
ArtifactsBucketLifecycleRules = new [] { new LifecycleRule {
Expiration = Duration.Days(30)
} }
});
Canary artifacts are encrypted at rest using an AWS-managed key by default.
You can choose the encryption options SSE-S3 or SSE-KMS by setting the artifactS3EncryptionMode
property.
When you use SSE-KMS, you can also supply your own external KMS key by specifying the kmsKey
property. If you don't, a KMS key will be automatically created and associated with the canary.
using Amazon.CDK.AWS.KMS;
var key = new Key(this, "myKey");
var canary = new Canary(this, "MyCanary", new CanaryProps {
Schedule = Schedule.Rate(Duration.Minutes(5)),
Test = Test.Custom(new CustomTestOptions {
Code = Code.FromAsset(Join(__dirname, "canary")),
Handler = "index.handler"
}),
Runtime = Runtime.SYNTHETICS_NODEJS_PUPPETEER_7_0,
ArtifactsBucketLifecycleRules = new [] { new LifecycleRule {
Expiration = Duration.Days(30)
} },
ArtifactS3EncryptionMode = ArtifactsEncryptionMode.KMS,
ArtifactS3KmsKey = key
});
Classes
ArtifactsBucketLocation | Options for specifying the s3 location that stores the data of each canary run. |
ArtifactsEncryptionMode | Encryption mode for canary artifacts. |
AssetCode | Canary code from an Asset. |
Canary | Define a new Canary. |
CanaryProps | Properties for a canary. |
CfnCanary | Creates or updates a canary. |
CfnCanary.ArtifactConfigProperty | A structure that contains the configuration for canary artifacts, including the encryption-at-rest settings for artifacts that the canary uploads to Amazon S3 . |
CfnCanary.BaseScreenshotProperty | A structure representing a screenshot that is used as a baseline during visual monitoring comparisons made by the canary. |
CfnCanary.CodeProperty | Use this structure to input your script code for the canary. |
CfnCanary.RunConfigProperty | A structure that contains input information for a canary run. |
CfnCanary.S3EncryptionProperty | A structure that contains the configuration of the encryption-at-rest settings for artifacts that the canary uploads to Amazon S3 . |
CfnCanary.ScheduleProperty | This structure specifies how often a canary is to make runs and the date and time when it should stop making runs. |
CfnCanary.VisualReferenceProperty | Defines the screenshots to use as the baseline for comparisons during visual monitoring comparisons during future runs of this canary. |
CfnCanary.VPCConfigProperty | If this canary is to test an endpoint in a VPC, this structure contains information about the subnet and security groups of the VPC endpoint. |
CfnCanaryProps | Properties for defining a |
CfnGroup | Creates or updates a group which you can use to associate canaries with each other, including cross-Region canaries. |
CfnGroupProps | Properties for defining a |
Cleanup | Different ways to clean up underlying Canary resources when the Canary is deleted. |
Code | The code the canary should execute. |
CodeConfig | Configuration of the code class. |
CronOptions | Options to configure a cron expression. |
CustomTestOptions | Properties for specifying a test. |
InlineCode | Canary code from an inline string. |
Runtime | Runtime options for a canary. |
RuntimeFamily | All known Lambda runtime families. |
S3Code | S3 bucket path to the code zip file. |
Schedule | Schedule for canary runs. |
Test | Specify a test that the canary should run. |
Interfaces
CfnCanary.IArtifactConfigProperty | A structure that contains the configuration for canary artifacts, including the encryption-at-rest settings for artifacts that the canary uploads to Amazon S3 . |
CfnCanary.IBaseScreenshotProperty | A structure representing a screenshot that is used as a baseline during visual monitoring comparisons made by the canary. |
CfnCanary.ICodeProperty | Use this structure to input your script code for the canary. |
CfnCanary.IRunConfigProperty | A structure that contains input information for a canary run. |
CfnCanary.IS3EncryptionProperty | A structure that contains the configuration of the encryption-at-rest settings for artifacts that the canary uploads to Amazon S3 . |
CfnCanary.IScheduleProperty | This structure specifies how often a canary is to make runs and the date and time when it should stop making runs. |
CfnCanary.IVisualReferenceProperty | Defines the screenshots to use as the baseline for comparisons during visual monitoring comparisons during future runs of this canary. |
CfnCanary.IVPCConfigProperty | If this canary is to test an endpoint in a VPC, this structure contains information about the subnet and security groups of the VPC endpoint. |
IArtifactsBucketLocation | Options for specifying the s3 location that stores the data of each canary run. |
ICanaryProps | Properties for a canary. |
ICfnCanaryProps | Properties for defining a |
ICfnGroupProps | Properties for defining a |
ICodeConfig | Configuration of the code class. |
ICronOptions | Options to configure a cron expression. |
ICustomTestOptions | Properties for specifying a test. |