

# Creating a canary
<a name="CloudWatch_Synthetics_Canaries_Create"></a>

**Important**  
Ensure that you use Synthetics canaries to monitor only endpoints and APIs where you have ownership or permissions. Depending on the canary frequency settings, these endpoints might experience increased traffic.

When you use the CloudWatch console to create a canary, you can use a blueprint provided by CloudWatch to create your canary or you can write your own script. For more information, see [Using canary blueprints](CloudWatch_Synthetics_Canaries_Blueprints.md).

You can also create a canary using CloudFormation if you are using your own script for the canary. For more information, see [ AWS::Synthetics::Canary ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html) in the *AWS CloudFormation User Guide*.

If you are writing your own script, you can use several functions that CloudWatch Synthetics has built into a library. For more information, see [Synthetics runtime versions](CloudWatch_Synthetics_Canaries_Library.md).

**Note**  
When you create a canary, one of the layers created is a Synthetics layer prepended with ` Synthetics`. This layer is owned by the Synthetics service account and contains the runtime code.

**To create a canary**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. In the navigation pane, choose **Application Signals**, **Synthetics Canaries**.

   

1. Choose **Create Canary**.

1. Choose one of the following:
   + To base your canary on a blueprint script, choose **Use a blueprint**, and then choose the type of canary you want to create. For more information about what each type of blueprint does, see [Using canary blueprints](CloudWatch_Synthetics_Canaries_Blueprints.md).
   + To upload your own Node.js script to create a custom canary, choose **Upload a script**.

     You can then drag your script into the **Script** area or choose **Browse files** to navigate to the script in your file system.
   + To import your script from an S3 bucket, choose **Import from S3**. Under **Source location**, enter the complete path to your canary or choose **Browse S3**.

     You must have `s3:GetObject` and `s3:GetObjectVersion` permissions for the S3 bucket that you use. The bucket must be in the same AWS Region where you are creating the canary.

1. Under **Name**, enter a name for your canary. The name is used on many pages, so we recommend that you give it a descriptive name that distinguishes it from other canaries.

1. Under **Application or endpoint URL**, enter the URL that you want the canary to test. This URL must include the protocol (such as https://).

   If you want the canary to test an endpoint on a VPC, you must also enter information about your VPC later in this procedure. 

1. If you are using your own script for the canary, under **Lambda handler**, enter the entry point where you want the canary to start. For information on Lambda handler format, see [Synthetics runtime versions ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library.html).

1. Under **Script editor**, **Runtime version**, select a synthetics runtime version to execute the canary. For information on synthetics runtime versions, see [Synthetics runtime versions ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library.html).

   Under **Browser configuration**, you can enable the browser to test the canary. You must select at least one browser.

1. If you are using environment variables in your script, choose **Environment variables** and then specify a value for each environment variable defined in your script. For more information, see [Environment variables](CloudWatch_Synthetics_Canaries_WritingCanary_Nodejs_Pup.md#CloudWatch_Synthetics_Environment_Variables).

1. Under **Schedule**, choose whether to run this canary just once, run it continuously using a rate expression, or schedule it using a cron expression.
   + When you use the CloudWatch console to create a canary that runs continuously, you can choose a rate anywhere between once a minute and once an hour.
   + For more information about writing a cron expression for canary scheduling, see [Scheduling canary runs using cron](CloudWatch_Synthetics_Canaries_cron.md).

1. (Optional) To set a timeout value for the canary, choose **Additional configuration** and then specify the timeout value. Make it no shorter than 15 seconds to allow for Lambda cold starts and the time it takes to boot up the canary instrumentation.

1. Under **Data retention**, specify how long to retain information about both failed and successful canary runs. The range is 1-455 days.

   This setting affects the range of information returned by [GetCanaryRuns](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_GetCanaryRuns.html) operations, as well as the range of information displayed in the Synthetics console.

   It does not affect the data stored in your Amazon S3 buckets, or logs or metrics that are published by the canary.

   Regardless of the canary's data retention period, the range of information displayed in console has certain limits. In the Synthetics console home view, the relative and absolute time range are limited to seven days. In the Synthetics console view for a specific canary, the relative time range is limited to seven days and the absolute time range is limited to 30 days.

1. Under **Data Storage**, select the Amazon S3 bucket to use to store the data from the canary runs. The bucket name can't contain a period (.). If you leave this blank, a default Amazon S3 bucket is used or created.

1. (Optional) By default, canaries store their artifacts on Amazon S3, and the artifacts are encrypted at rest using an AWS-managed AWS KMS key. You can use a different encryption option by choosing **Additional configuration** in the **Data Storage** section. You can then choose the type of key to use for encryption. For more information, see [Encrypting canary artifacts](CloudWatch_Synthetics_artifact_encryption.md). 

1. Under **Access permissions**, choose whether to create an IAM role to run the canary or use an existing one.

   If you have CloudWatch Synthetics create the role, it automatically includes all the necessary permissions. If you want to create the role yourself, see [Required roles and permissions for canaries](CloudWatch_Synthetics_Canaries_CanaryPermissions.md) for information about the necessary permissions.

   If you use the CloudWatch console to create a role for a canary when you create the canary, you can't re-use the role for other canaries, because these roles are specific to just one canary. If you have manually created a role that works for multiple canaries, you can use that existing role.

   To use an existing role, you must have the `iam:PassRole` permission to pass that role to Synthetics and Lambda. You must also have the `iam:GetRole` permission.

1. (Optional) Under **Alarms**, choose whether you want default CloudWatch alarms to be created for this canary. If you choose to create alarms, they are created with the following name convention:`Synthetics-Alarm-canaryName -index `

   `index` is a number representing each different alarm created for this canary. The first alarm has an index of 1, the second alarm has an index of 2, and so on.

1. (Optional) To have this canary test an endpoint that is on a VPC, choose **VPC settings**, and then do the following:

   1. Select the VPC that hosts the endpoint.

   1. Select one or more subnets on your VPC. You must select a private subnet because a Lambda instance can't be configured to run in a public subnet when an IP address can't be assigned to the Lambda instance during execution. For more information, see [Configuring a Lambda Function to Access Resources in a VPC](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html).

   1. Select one or more security groups on your VPC.

   1. To allow outbound IPv6 traffic for this canary, select **Allow IPv6 Traffic for dual-stack subnets**. This enables the canary to monitor IPv6-only and dual stack enabled endpoints over IPv6.

      You can monitor endpoints external to your VPC by giving the canary internet access and configuring the VPC subnets appropriately. For more information, see [Running a canary on a VPC](CloudWatch_Synthetics_Canaries_VPC.md).

   If the endpoint is on a VPC, you must enable your canary to send information to CloudWatch and Amazon S3. For more information, see [Running a canary on a VPC](CloudWatch_Synthetics_Canaries_VPC.md).

1. (Optional) Under **Tags**, add one or more key-value pairs as tags for this canary. Tags can help you identify and organize your AWS resources and track your AWS costs. For more information, see [Tagging your Amazon CloudWatch resources](CloudWatch-Tagging.md).

   If you want the tags that you apply to the canary to also be applied to the Lambda function that the canary uses, choose **Lambda function** under **Tag Replication**. If you choose this option, CloudWatch Synthetics will keep the tags on the canary and the Lambda function synchronized:
   + Synthetics will apply the same tags that you specify here to both your canary and your Lambda function.
   + If you later update the canary's tags and keep this option selected, Synthetics modifies the tags on your Lambda function to remain in sync with the canary. 

1. (Optional) Under **Active tracing**, choose whether to enable active X-Ray tracing for this canary. Active tracing is only available for Puppeteer and Java runtimes. For more information, see [Canaries and X-Ray tracing](CloudWatch_Synthetics_Canaries_tracing.md).

## Resources that are created for canaries
<a name="CloudWatch_Synthetics_Canaries_Resources_Created"></a>

When you create a canary, the following resources are created:
+ An IAM role with the name `CloudWatchSyntheticsRole-canary-name -uuid` (if you use CloudWatch console to create the canary and specify for a new role to be created for the canary)
+ An IAM policy with the name `CloudWatchSyntheticsPolicy- canary-name-uuid`.
+ An S3 bucket with the name `cw-syn-results-accountID -region`.
+ Alarms with the name `Synthetics-Alarm-MyCanaryName`, if you want alarms to be created for the canary.
+ Lambda functions and layers, if you use a blueprint to create the canary. These resources have the prefix `cwsyn-MyCanaryName`.
+ CloudWatch Logs log groups with the name `/aws/lambda/cwsyn-MyCanaryName -randomId`.

# Using canary blueprints
<a name="CloudWatch_Synthetics_Canaries_Blueprints"></a>

This section provides details about each of the canary blueprints and the tasks each blueprint is best suited for. Blueprints are provided for the following canary types: 

**Topics**
+ [Heartbeat monitoring](#CloudWatch_Synthetics_Canaries_Blueprints_Heartbeat)
+ [API canary](#CloudWatch_Synthetics_Canaries_Blueprints_API)
+ [Broken link checker](#CloudWatch_Synthetics_Canaries_Blueprints_Broken_Links)
+ [Visual monitoring blueprint](#CloudWatch_Synthetics_Canaries_Blueprints_VisualTesting)
+ [Canary recorder](#CloudWatch_Synthetics_Canaries_Blueprints_Recorder)
+ [GUI workflow builder](#CloudWatch_Synthetics_Canaries_Blueprints_GUI_Workflow)
+ [Multi checks blueprint](#CloudWatch_Synthetics_Canaries_Blueprints_Multichecks_Blueprint)
+ [Creating multi checks blueprint canary](CloudWatch_Synthetics_Canaries_MultiCheck_Blueprint.md)

When you use a blueprint to create a canary, as you fill out the fields in the CloudWatch console, the **Script editor** area of the page displays the canary you are creating as a Node.js script. You can also edit your canary in this area to customize it further.

## Heartbeat monitoring
<a name="CloudWatch_Synthetics_Canaries_Blueprints_Heartbeat"></a>

Heartbeat scripts load the specified URL and store a screenshot of the page and an HTTP archive file (HAR file). They also store logs of accessed URLs. 

You can use the HAR files to view detailed performance data about the web pages. You can analyze the list of web requests and catch performance issues such as time to load for an item.

If your canary uses the `syn-nodejs-puppeteer-3.1` or later runtime version, you can use the heartbeat monitoring blueprint to monitor multiple URLs and see the status, duration, associated screenshots, and failure reason for each URL in the step summary of the canary run report.

## API canary
<a name="CloudWatch_Synthetics_Canaries_Blueprints_API"></a>

API canaries can test the basic Read and Write functions of a REST API. REST stands for *representational state transfer* and is a set of rules that developers follow when creating an API. One of these rules states that a link to a specific URL should return a piece of data.

Canaries can work with any APIs and test all types of functionality. Each canary can make multiple API calls.

In canaries that use runtime version `syn-nodejs-2.2` or later, the API canary blueprint supports multi-step canaries that monitor your APIs as HTTP steps. You can test multiple APIs in a single canary. Each step is a separate request that can access a different URL, use different headers, and use different rules for whether headers and response bodies are captured. By not capturing headers and response body, you can prevent sensitive data from being recorded. 

Each request in an API canary consists of the following information:
+ The *endpoint*, which is the URL that you request.
+ The *method*, which is the type of request that is sent to the server. REST APIs support GET (read), POST (write), PUT (update), PATCH (update), and DELETE (delete) operations.
+ The *headers*, which provide information to both the client and the server. They are used for authentication and providing information about the body content. For a list of valid headers, see [HTTP Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
+ The *data* (or *body*), which contains information to be sent to the server. This is used only for POST, PUT, PATCH, or DELETE requests.

**Note**  
API canary blueprints are not supported by Playwright runtimes.

The API canary blueprint supports GET and POST methods. When you use this blueprint, you must specify headers. For example, you can specify **Authorization** as a **Key** and specify the necessary authorization data as the ** Value** for that key.

If you are testing a POST request, you also specify the content to post in the ** Data** field.

 **Integration with API Gateway** 

The API blueprint is integrated with Amazon API Gateway. This enables you to select an API Gateway API and stage from the same AWS account and Region as the canary, or to upload a Swagger template from API Gateway for cross-account and cross-Region API monitoring. You can then choose the rest of the details in the console to create the canary, instead of entering them from scratch. For more information about API Gateway, see [What is Amazon API Gateway?](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 

 **Using a private API** 

You can create a canary that uses a private API in Amazon API Gateway. For more information, see [Creating a private API in Amazon API Gateway?](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html)

## Broken link checker
<a name="CloudWatch_Synthetics_Canaries_Blueprints_Broken_Links"></a>

The broken link checker collects all the links inside the URL that you are testing by using `document.getElementsByTagName('a')`. It tests only up to the number of links that you specify, and the URL itself is counted as the first link. For example, if you want to check all the links on a page that contains five links, you must specify for the canary to follow six links.

Broken link checker canaries created using the `syn-nodejs-2.0-beta` runtime or later support the following additional features:
+ Provides a report that includes the links that were checked, status code, failure reason (if any), and source and destination page screenshots.
+ When viewing canary results, you can filter to see only the broken links and then fix the link based on the reason for failure.
+ This version captures annotated source page screenshots for each link and highlights the anchor where the link was found. Hidden components are not annotated.
+ You can configure this version to capture screenshots of both source and destination pages, just source pages, or just destination pages.
+ This version fixes an issue in the earlier version where the canary script stops after the first broken link even when more links are scraped from the first page.

**Note**  
Broken link checker blueprints are not supported by Playwright runtimes.

To update an existing canary using `syn-1.0` to use the new runtime, you must delete and re-create the canary. Updating an existing canary to the new runtime does not make these features available.

A broken link checker canary detects the following types of link errors:
+ 404 Page Not Found
+ Invalid Host Name
+ Bad URL. For example, the URL is missing a bracket, has extra slashes, or uses the wrong protocol.
+ Invalid HTTP response code.
+ The host server returns empty responses with no content and no response code.
+ The HTTP requests constantly time out during the canary's run.
+ The host consistently drops connections because it is misconfigured or is too busy.

## Visual monitoring blueprint
<a name="CloudWatch_Synthetics_Canaries_Blueprints_VisualTesting"></a>

The visual monitoring blueprint includes code to compare screenshots taken during a canary run with screenshots taken during a baseline canary run. If the discrepancy between the two screenshots is beyond a threshold percentage, the canary fails. Visual monitoring is supported in canaries running **syn-puppeteer-node-3.2** and later. It is not currently supported in canaries running Python and Selenium, or using Playwright runtimes.

The visual monitoring blueprint includes the following line of code in the default blueprint canary script, which enables visual monitoring.

```
syntheticsConfiguration.withVisualCompareWithBaseRun(true);
```

The first time that the canary runs successfully after this line is added to the script, it uses the screenshots taken during that run as the baseline for comparison. After that first canary run, you can use the CloudWatch console to edit the canary to do any of the following:
+ Set the next run of the canary as the new baseline.
+ Draw boundaries on the current baseline screenshot to designate areas of the screenshot to ignore during visual comparisons.
+ Remove a screenshot from being used for visual monitoring.

For more information about using the CloudWatch console to edit a canary, see [Edit or delete a canary](synthetics_canaries_deletion.md).

You can also change the canary run that is used as the baseline by using the ` nextrun` or `lastrun` parameters or specifing a canary run ID in the [UpdateCanary](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_UpdateCanary.html) API.

When you use the visual monitoring blueprint, you enter the URL where you want the screenshot to be taken, and specify a difference threshold as a percentage. After the baseline run, future runs of the canary that detect a visual difference greater than that threshold trigger a canary failure. After the baseline run, you can also edit the canary to "draw" boundaries on the baseline screenshot that you want to ignore during the visual monitoring.

The visual monitoring feature is powered by the the ImageMagick open source software toolkit. For more information, see [ ImageMagick ](https://imagemagick.org/index.php).

## Canary recorder
<a name="CloudWatch_Synthetics_Canaries_Blueprints_Recorder"></a>

With the canary recorder blueprint, you can use the CloudWatch Synthetics Recorder to record your click and type actions on a website and automatically generate a Node.js script that can be used to create a canary that follows the same steps. The CloudWatch Synthetics Recorder is a Google Chrome extension provided by Amazon. The canary recorder is not supported for canaries that use the Playwright runtime.

**Credits**: The CloudWatch Synthetics Recorder is based on the [ Headless recorder ](https://github.com/checkly/headless-recorder).

For more information, see [Using the CloudWatch Synthetics Recorder for Google Chrome](CloudWatch_Synthetics_Canaries_Recorder.md).

## GUI workflow builder
<a name="CloudWatch_Synthetics_Canaries_Blueprints_GUI_Workflow"></a>

The GUI Workflow Builder blueprint verifies that actions can be taken on your webpage. For example, if you have a webpage with a login form, the canary can populate the user and password fields and submit the form to verify that the webpage is working correctly.

When you use a blueprint to create this type of canary, you specify the actions that you want the canary to take on the webpage. The actions that you can use are the following:
+ **Click**— Selects the element that you specify and simulates a user clicking or choosing the element.

  To specify the element in a Node.js script, use `[id=]` or ` a[class=]`.

  To specify the element in a Python script, use `xpath //*[@id=]` or ` //*[@class=]`.
+ **Verify selector**— Verifies that the specified element exists on the webpage. This test is useful for verifying that a previous action has causes the correct elements to populate the page.

  To specify the element to verify in a Node.js script, use `[id=]` or ` a[class=]`.

  To specify the element to verify in a Python script, use `xpath //*[@id=]` or `//*[class=]`.
+ **Verify text**— Verifies that the specified string is contained within the target element. This test is useful for verifying that a previous action has caused the correct text to be displayed.

  To specify the element in a Node.js script, use a format such as ` div[@id=]//h1` because this action uses the `waitForXPath` function in Puppeteer.

  To specify the element in a Python script, use xpath format such as ` //*[@id=] `or //\$1[@class=] because this action uses the `implicitly_wait` function in Selenium.
+ **Input text**— Writes the specified text in the target element.

  To specify the element to verify in a Node.js script, use `[id=]` or ` a[class=]`.

  To specify the element to verify in a Python script, use `xpath //*[@id=]` or `//*[@class=]`.
+ **Click with navigation**— Waits for the whole page to load after choosing the specified element. This is most useful when you need to reload the page.

  To specify the element in a Node.js script, use `[id=]` or ` a[class=]`.

  To specify the element in a Python script, use `xpath //*[@id=]` or ` //*[@class=]`.

For example, the following blueprint uses Node.js. It clicks the **firstButton** on the specified URL, verifies that the expected selector with the expected text appears, inputs the name `Test_Customer` into the **Name** field, clicks the **Login** button, and then verifies that the login is successful by checking for the **Welcome** text on the next page.

![\[The create canary page in the console, with fields filled in for the GUI Workflow blueprint.\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/images/canary_create_gui_workflow.PNG)


GUI workflow canaries that use the following runtimes also provide a summary of the steps executed for each canary run. You can use the screenshots and error message associated with each step to find the root cause of failure.
+ `syn-nodejs-2.0` or later
+ `syn-python-selenium-1.0` or later

## Multi checks blueprint
<a name="CloudWatch_Synthetics_Canaries_Blueprints_Multichecks_Blueprint"></a>

The Multi check blueprint simplifies canary creation. It reduces costs by using a simple JSON configuration that provides out-of-the-box functionality for performing HTTP, DNS, SSL, and TCP checks. You can configure up to 10 checks. Configure each check as a numerical step that runs sequentially, allowing for clear understanding of the canary flow.

Multi checks blueprints support:
+ Basic HTTP requests, TCP requests, validate DNS records and monitor SSL certificates
+ HTTP authentication methods such as Basic, API Key, OAuth, and Sigv4 integrated with Secrets Manager
+ Assertions for each check

For more information, see [Creating a canary](CloudWatch_Synthetics_Canaries_Create.md).

# Creating multi checks blueprint canary
<a name="CloudWatch_Synthetics_Canaries_MultiCheck_Blueprint"></a>

Amazon CloudWatch Synthetics multi checks blueprint helps you create a Synthetics canary by providing a simple JSON configuration. You can save costs by bundling up to 10 different types of HTTP/DNS/SSL/TCP checks in a step-based sequential manner. Each check includes assertions that provide basic verification against a check result.

Multi checks canaries are designed for simple use cases that require only basic checks without a headless browser. For more complex use cases, review the other canary types that Amazon CloudWatch Synthetics provides.

**Topics**
+ [Prerequisites](#CloudWatch_Synthetics_MultiCheck_Prerequisites)
+ [Limitations](#CloudWatch_Synthetics_MultiCheck_Limitations)
+ [Packaging structure, JSON schema, and configuration settings](#CloudWatch_Synthetics_MultiCheck_Packaging)
+ [Creating a multi check canary in AWS Management Console](#CloudWatch_Synthetics_MultiCheck_Console)
+ [Creating a multi check canary using AWS Synthetics APIs](#CloudWatch_Synthetics_MultiCheck_API)
+ [Creating a multi check canary in CloudFormation](#CloudWatch_Synthetics_MultiCheck_CloudFormation)
+ [Authentication configuration](#CloudWatch_Synthetics_MultiCheck_Authentication)
+ [Troubleshooting](#CloudWatch_Synthetics_MultiCheck_Troubleshooting)

## Prerequisites
<a name="CloudWatch_Synthetics_MultiCheck_Prerequisites"></a>
+ Must be using syn-nodejs-3.0\$1 in order to create a multi check canary
+ When using Authentication and Secrets Manager configuration, you must ensure the canary [ ExecutionRoleArn](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_CreateCanary.html) allows for the permissions to access these secrets
+ When using Authentication for Sigv4, you must ensure the canary [ ExecutionRoleArn](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_CreateCanary.html) allows for the permissions to access the related role

## Limitations
<a name="CloudWatch_Synthetics_MultiCheck_Limitations"></a>
+ HTTP Response sizes cannot be greater than 1 MB
+ Maximum of 10 defined variables.
+ When using the JSON RFC, the Checks JSON may have duplicate fields provided however only the last sequential field will be used
+ In the AWS Management Console, a multi check canary will default to showing multi check step metrics to readily identify the availability of each check. When checks are removed, this graph may still show the checks in the availability graph until the metric stops being active for at least 3 hours

## Packaging structure, JSON schema, and configuration settings
<a name="CloudWatch_Synthetics_MultiCheck_Packaging"></a>

The JSON Checks configuration that will be used for the canary must be named ` blueprint-config.json`. The configuration must follow the [ schema](https://github.com/aws-samples/synthetics-canary-local-debugging-sample/tree/main) and follow the instructions under [Writing a JSON configuration for Node.js multi Checks blueprint](CloudWatch_Synthetics_WritingCanary_Multichecks.md).

Compress the `blueprint-config.json` into a ZIP file and provide it in one of the following creation workflows. When there is a `synthetics.json` configuration, then it is also compressed in the same ZIP file. The following is a zip file example called `multi-checks.zip`.

```
multi-checks.zip
├── blueprint-config.json
└── synthetics.json
```

## Creating a multi check canary in AWS Management Console
<a name="CloudWatch_Synthetics_MultiCheck_Console"></a>

1. Open the Amazon CloudWatch synthetics console.

1. Choose **Create Canary**.

1. Under **Use a blueprint**, choose **multi checks** .

   Under **Configure Checks**, you will see two tabs, ** Checks** and **Canary configuration**.

1. Select the runtime version **syn-nodejs-3.0** or later.

1. Follow the procedure under [Writing a JSON configuration for Node.js multi Checks blueprint](CloudWatch_Synthetics_WritingCanary_Multichecks.md) to describe the check you want to perform. Alternatively, the console provides you a default JSON configuration that you can build on.

1. Choose **Create Canary**.

## Creating a multi check canary using AWS Synthetics APIs
<a name="CloudWatch_Synthetics_MultiCheck_API"></a>

Use the `CreateCanary` API and within the `Code` parameter, provide the field/value `BlueprintTypes="multi-checks"` instead of ` Handler`. When both `BlueprintTypes` and `Handler` are specified, a `ValidationException` is displayed. The runtime version provided must be `syn-nodejs-3.0` or later.

```
aws synthetics create-canary \
    --name my-multi-check-canary \
    --code ZipFile="ZIP_BLOB",BlueprintTypes="multi-checks" \
    --runtime-version syn-nodejs-3.0 \
    ...

// Or if you wanted to use S3 to provide your code.

aws synthetics create-canary \
    --name my-multi-check-canary \
    --code S3Bucket="my-code-bucket",S3Key="my-zip-code-key",BlueprintTypes="multi-checks" \
    ...
```

## Creating a multi check canary in CloudFormation
<a name="CloudWatch_Synthetics_MultiCheck_CloudFormation"></a>

In your CloudFormation template for a multi check canary, within the `Code` parameter, provide the field/value `BlueprintTypes="multi-checks"` instead of ` Handler`. When both `BlueprintTypes` and `Handler` are specified, a `ValidationException` is displayed. The runtime version provided must be `syn-nodejs-3.0 or later`. 

An example template:

```
SyntheticsCanary:
    Type: 'AWS::Synthetics::Canary'
    Properties:
      Name: MyCanary
      RuntimeVersion: syn-nodejs-3.0
      Schedule: {Expression: 'rate(5 minutes)', DurationInSeconds: 3600}
      ...
      Code:
        S3Bucket: "my-code-bucket"
        S3Key: "my-zip-code-key"
        BlueprintTypes: ["multi-checks"]
      ...
```

## Authentication configuration
<a name="CloudWatch_Synthetics_MultiCheck_Authentication"></a>

When your canary makes HTTP requests to an authenticated endpoint, you can configure the steps of your blueprint canary to use one of four authentication types: Basic, API Key, OAuth Client Credentials, and SigV4. Rather than setting up request headers yourself, you can specify an authentication type in your blueprint definition, and Synthetics follows the specified authentication type to populate the components of your HTTP request with the authentication information provided.

You specify an authentication type in your blueprint step with the Authentication section. You specify the authentication scheme you want to use, the properties required for your chosen authentication scheme, and Synthetics uses the information provided to construct an authentication header for your HTTP request.

Since storing secrets (such as passwords or API keys) in plain text is a security concern, Synthetics supports integration with AWS Secrets Manager. When you want to authenticate an HTTP request in a Synthetics blueprint canary, you can refer to the secret storing your authentication information and Synthetics handles retrieving the secret and caching it in your canary. This approach provides secrets to Synthetics while keeping your secrets securely stored, without specifying them in plain text in your blueprint configuration.

For more information about AWS Secrets Manager, see [What is AWS Secrets Manager?](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html)

### Basic authentication
<a name="CloudWatch_Synthetics_MultiCheck_BasicAuth"></a>

Synthetics implements the Basic HTTP authentication scheme defined in RFC 7617. The process works as follows:
+ A username and password pair is provided from the blueprint configuration.
+ The user-pass is created by concatenating the username, a single colon (":") character, and the password.
+ The user-pass is UTF-8 encoded, then converted into a base64-encoded string.
+ This base64-encoded user-pass is provided in the "Authorization" header with the following format: Authorization: Basic \$1base64-encoded-user-pass\$1

For example, if the user agent wants to send the user-id "Aladdin" and password "open sesame", it uses the following header field: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Example configuration:

```
"Authentication": {
    "type": "BASIC",
    "username": MY_USERNAME, // Required
    "password": MY_PASSWORD // Required
}
```

### API key authentication
<a name="CloudWatch_Synthetics_MultiCheck_APIKeyAuth"></a>

You can provide an API key for authenticating your HTTP requests. When you use API key authentication, your provided API key is put into the "X-API-Key" HTTP header. If you have a custom resource that looks for API key headers in a header besides this one, you can optionally specify a different header name to have Synthetics put the API key into.

Example configuration:

```
"Authentication": {
    "type": "API_KEY",
    "apiKey": S0A1M2P3L4E5, // Required
    "header": X-Specific-Header // Optional, defaults to "X-API-Key"
}
```

### SigV4 authentication
<a name="CloudWatch_Synthetics_MultiCheck_SigV4Auth"></a>

AWS SigV4 (Signature Version 4) is the AWS signing protocol for adding authentication information to AWS API requests. To make a SigV4-authenticated request, you need to specify the region and service you are making requests to, as well as an ARN (AWS Resource Name) identifying an IAM role you want the canary to assume when making this SigV4 request. Synthetics assumes the IAM role provided in the roleArn, and uses it to authenticate your AWS API request.

Example configuration:

```
"Authentication": {
    "type": "SIGV4",
    "region": us-west-2, // Required
    "service": s3, // Required
    "roleArn": arn:AWS:iam:12345678912:role/SampleRole // Required
}
```

#### SigV4 considerations
<a name="CloudWatch_Synthetics_MultiCheck_SigV4Considerations"></a>

For Synthetics to assume the role that you provided in the SigV4 authentication section, the trust policy attached to that role must be configured to allow the canary to assume the provided roleArn. The AWS principal you need to trust is the role that your canary assumed through AWS STS. It takes the format ` aws:sts::{account_running_the_canary}:assumed-role/<canary_name>/<assumed_role_name>` arn:.

For example, if you have a canary running in account 0123456789012, named test-canary, and the role it assumed was named canary-assume-role, then the trust policy needs to include this statement for the canary to assume the roleArn for SigV4 authentication correctly:

```
{
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:AWS:sts::123456789012:assumed-role/test-canary/"
    },
    "Action": "sts:AssumeRole"
}
```

### OAuth client credentials
<a name="CloudWatch_Synthetics_MultiCheck_OAuthAuth"></a>

Synthetics implements the OAuth Client Credentials grant type as defined in RFC 6479 Section 4.4. If you want to make an HTTP request to an endpoint authenticated with a Bearer Token issued by an OAuth token endpoint, Synthetics can request and manage a bearer token on your behalf. When you use the OAuth scheme, Synthetics performs the following steps:
+ Uses the Basic authentication scheme with the clientId and clientSecret to authenticate a request to the tokenUrl, the endpoint that issues bearer tokens
+ If you provide the optional scope, audience, and resource parameters, they are included in the token request
+ Uses the access token returned by the tokenUrl to authenticate your HTTP request
+ Securely stores the refresh token returned from the tokenUrl for future token requests

Example configuration:

```
"Authentication": {
    "type": "OAUTH_CLIENT_CREDENTIALS",
    "tokenUrl": ..., // Required
    "clientId": ..., // Required
    "clientSecret": ..., // Required
    "scope": ..., // Optional
    "audience": ..., // Optional
    "resource": ..., // Optional
}
```

#### OAuth considerations
<a name="CloudWatch_Synthetics_MultiCheck_OAuthConsiderations"></a>

Synthetics refreshes OAuth tokens when a 401 or 407 response is returned.

### AWS Secrets Manager integration
<a name="CloudWatch_Synthetics_MultiCheck_SecretsManager"></a>

To avoid storing secret values (such as passwords or API keys) in plain text, Synthetics provides an integration with AWS Secrets Manager. You can reference an entire secret value in your blueprint configuration with the format ` ${aws_SECRET:<secret_name>}`, or to reference a particular key ` ${aws_SECRET:<secret_name>:<secret_key>}`.

For example, if you have a secret named login/basic-auth-credentials, storing a username and password with the following JSON structure:

```
{
    "username": "Aladdin",
    "password": "open sesame"
}
```

You can reference the username and password in your blueprint configuration as follows, and Synthetics handles retrieving the secret value and using its keys to authenticate your request:

```
"Authentication": {
    "type": "BASIC",
    "username": ${AWS_SECRET:login/basic-auth-credentials:username},
    "password": ${AWS_SECRET:login/basic-auth-credentials:password}
}
```

To allow Synthetics to retrieve the specified secret, the role ARN assumed by the canary needs to have secretsManager:GetSecretValue permissions. If the secret is encrypted using a customer-managed key instead of the AWS managed key AWS/secretsmanager, then you also need kms:Decrypt permissions for that key.

Example permissions:

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "arn:AWS:secretsmanager:us-east-1:123456789012:secret:secretName-AbCdEf"
        },
        {
            "Effect": "Allow",
            "Action": "kms:Decrypt",
            "Resource": "arn:AWS:kms:us-east-1:123456789012:key/key-id"
        }
    ]
}
```

## Troubleshooting
<a name="CloudWatch_Synthetics_MultiCheck_Troubleshooting"></a>

### Common troubleshooting failures
<a name="CloudWatch_Synthetics_MultiCheck_Common_Failures"></a>

The underlying code for multi check blueprint is written in Typescript. See the canary troubleshooting page for common failures: [Troubleshooting a failed canary](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Troubleshoot.html).

### JSON check configuration syntax errors
<a name="CloudWatch_Synthetics_MultiCheck_JSON_Errors"></a>

When there are any syntactic errors related to the canary's JSON check configuration, the AWS Management Console will provide you a failure reason when you attempt to create the canary. If you are creating a canary using an API or CloudFormation, you will see the failure when the canary is executed for the first time. It is recommended to use the safe canary updates workflow for multi check canary. For more information, see [Performing safe canary updates ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/performing-safe-canary-upgrades.html).

### Networking or timeout failures
<a name="CloudWatch_Synthetics_MultiCheck_Network_Failures"></a>

For any intermittent or consistent failures related to timeouts, network connection failures (for example, ENOTFOUND, ECONNRESET) consider turning on ` DEBUG` logs such that the following run will provide more additional details on why the Checks are failing. To do so, provide the Environment Variable CW\$1SYNTHETICS\$1LOG\$1LEVEL: "DEBUG".

If there are still failures that you are unable to debug, consider reaching out to AWS Support or checking if any of the other provided Canary types from CloudWatch Synthetics more closely matches your use-case.

# Using the CloudWatch Synthetics Recorder for Google Chrome
<a name="CloudWatch_Synthetics_Canaries_Recorder"></a>

Amazon provides a CloudWatch Synthetics Recorder to help you create canaries more easily. The recorder is a Google Chrome extension.

The recorder records your click and type actions on a website and automatically generates a Node.js script that can be used to create a canary that follows the same steps.

After you start recording, the CloudWatch Synthetics Recorder detects your actions in the browser and converts them to a script. You can pause and resume the recording as needed. When you stop recording, the recorder produces a Node.js script of your actions, which you can easily copy with the **Copy to Clipboard** button. You can then use this script to create a canary in CloudWatch Synthetics. 

**Credits**: The CloudWatch Synthetics Recorder is based on the [ Headless recorder ](https://github.com/checkly/headless-recorder).

## Installing the CloudWatch Synthetics Recorder extension for Google Chrome
<a name="CloudWatch_Synthetics_Canaries_Recorder-install"></a>

To use the CloudWatch Synthetics Recorder, you can start creating a canary and choose the **Canary Recorder** blueprint. If you do this when you haven't already downloaded the recorder, the CloudWatch Synthetics console provides a link to download it.

Alternatively, you can follow these steps to download and install the recorder directly.

**To install the CloudWatch Synthetics Recorder**

1. Using Google Chrome, go to this website: [ https://chrome.google.com/webstore/detail/cloudwatch-synthetics-rec/bhdnlmmgiplmbcdmkkdfplenecpegfno ](https://chrome.google.com/webstore/detail/cloudwatch-synthetics-rec/bhdnlmmgiplmbcdmkkdfplenecpegfno)

1. Choose **Add to Chrome**, then choose **Add extension** .

## Using the CloudWatch Synthetics Recorder for Google Chrome
<a name="CloudWatch_Synthetics_Canaries_Recorder-using"></a>

To use the CloudWatch Synthetics Recorder to help you create a canary, you can choose **Create canary** in the CloudWatch console, and then choose **Use a blueprint**, **Canary Recorder**. For more information, see [Creating a canary](CloudWatch_Synthetics_Canaries_Create.md). 

Alternatively, you can use the recorder to record steps without immediately using them to create a canary.

**To use the CloudWatch Synthetics Recorder to record your actions on a website**

1. Navigate to the page that you want to monitor.

1. Choose the Chrome extensions icon, and then choose **CloudWatch Synthetics Recorder**.

1. Choose **Start Recording**.

1. Perform the steps that you want to record. To pause recording, choose ** Pause**.

1. When you are finished recording the workflow, choose **Stop recording** .

1. Choose **Copy to clipboard** to copy the generated script to your clipboard. Or, if you want to start over, choose **New recording**.

1. To create a canary with the copied script, you can paste your copied script into the recorder blueprint inline editor, or save it to an Amazon S3 bucket and import it from there.

1. If you're not immediately creating a canary, you can save your recorded script to a file.

## Known limitations of the CloudWatch Synthetics Recorder
<a name="CloudWatch_Synthetics_Canaries_Recorder-limitations"></a>

The CloudWatch Synthetics Recorder for Google Chrome currently has the following limitations.
+ HTML elements that don’t have IDs will use CSS selectors. This can break canaries if the webpage structure changes later. We plan to provide some configuration options (such as using data-id) around this in a future version of the recorder. 
+ The recorder doesn't support actions such as double-click or copy/paste, and doesn't support key combinations such as CMD\$10. 
+ To verify the presence of an element or text on the page, users must add assertions after the script is generated. The recorder doesn't support verifying an element without performing any action on that element. This is similar to the “Verify text” or “Verify element” options in the canary workflow builder. We plan to add some assertions support in a future version of the recorder. 
+ The recorder records all actions in the tab where the recording is initiated. It doesn't record pop-ups (for instance, to allow location tracking) or navigation to different pages from pop-ups. 

# Synthetics runtime versions
<a name="CloudWatch_Synthetics_Canaries_Library"></a>

When you create or update a canary, you choose a Synthetics runtime version for the canary. A Synthetics runtime is a combination of the Synthetics code that calls your script handler, and the Lambda layers of bundled dependencies.

CloudWatch Synthetics currently supports runtimes that use Node.js, Python, or Java languages. The frameworks supported are Puppeteer, Playwright, and Selenium.

We recommend that you always use the most recent runtime version for your canaries, to be able to use the latest features and updates made to the Synthetics library.

**Please note**: whenever you run a canary to use the new version of the Synthetics runtime, all Synthetics library functions that your canary uses are also automatically moved to the same version of NodeJS that the Synthetics runtime supports.

**Topics**
+ [Runtime versions using Java](CloudWatch_Synthetics_Library_Java.md)
+ [Runtime versions using Node.js and Playwright](CloudWatch_Synthetics_Library_nodejs_playwright.md)
+ [Runtime versions using Node.js and Puppeteer](CloudWatch_Synthetics_Library_nodejs_puppeteer.md)
+ [Runtime versions using Python and Selenium Webdriver](CloudWatch_Synthetics_Library_python_selenium.md)
+ [Runtime versions using Node.js](CloudWatch_Synthetics_Library_Nodejs.md)
+ [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md)
+ [Runtime versions update](CloudWatch_Synthetics_Runtime_Version_Update.md)

# Runtime versions using Java
<a name="CloudWatch_Synthetics_Library_Java"></a>

The following section contains information about the CloudWatch Synthetics runtime versions for Java. This runtime does not have any browser or framework included.

The naming convention for these runtime versions is `syn-language -majorversion.minorversion`. 

## syn-java-1.0
<a name="Synthetics_runtimeversion-syn-java-1.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Java 21

 **Features** 
+ *CloudWatch Logs integration* – You can query and filter for logs through the CloudWatch Synthetics console. Each log message contains unique ` canaryRunId`, making it easy to search for logs for a particular canary run.
+ *Metrics* – You can monitor canary run success percentage and duration through CloudWatch metrics. You can also configure alarms to alert you when canaries detect issues.
+ *Canary artifacts* - Each canary run uploads a detailed report corresponding to the run and the steps in the run which can be accessed through Amazon S3.
+ *Support for traces* - You can emit traces for all the requests made by the canary through X-Ray. Each canary run is associated with one trace Id.

# Runtime versions using Node.js and Playwright
<a name="CloudWatch_Synthetics_Library_nodejs_playwright"></a>

The following sections contain information about the CloudWatch Synthetics runtime versions for Node.js and Playwright. Playwright is an open-source automation library for browser testing. For more information about Playwright, see [ https://playwright.dev/](https://playwright.dev) 

The naming convention for these runtime versions is `syn-language -framework-majorversion. minorversion`. 

## syn-nodejs-playwright-6.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-6.0"></a>

**Important**  
Starting Synthetics `syn-nodejs-playwright-5.1` and later, Synthetics runtime uses the new namespace. Please migrate the canary script to use the new namespace. Legacy namespace will be deprecated in a future release.  
@amzn/synthetics-playwright → @aws/synthetics-playwright

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x
+ Playwright version 1.58.2
+ Playwright/test version 1.58.2
+ Chromium version 145.0.7632.77
+ Firefox version 146.0.1

 **Changes in syn-nodejs-playwright-6.0** 
+ Applied security patches and updated Playwright and browser versions. 

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

## Previous runtime versions for Node.js and Playwright
<a name="Previousversions-nodejs-playwright"></a>

The following earlier runtime versions for Node.js and Playwright are still supported. 

### syn-nodejs-playwright-5.1
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-5.1"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x
+ Playwright version 1.57.0
+ Playwright/test version 1.57.0
+ Chromium version 143.0.7499.169
+ Firefox version 142.0.1

 **Changes in syn-nodejs-playwright-5.1** 
+ Synthetics runtime namespace migration. 
+ Type definition is available in [npm Registry](https://www.npmjs.com/package/@aws/synthetics-playwright). Please ensure the type definition package version matches your canary's runtime version.

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

### syn-nodejs-playwright-5.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-5.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x
+ Playwright version 1.57.0
+ Playwright/test version 1.57.0
+ Chromium version 143.0.7499.4
+ Firefox version 142.0.1

 **Changes in syn-nodejs-playwright-5.0** 
+ Applied security patches and updated Playwright and browser versions. 

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

### syn-nodejs-playwright-4.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-4.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x
+ Playwright version 1.55.0
+ Playwright/test version 1.55.0
+ Chromium version 140.0.7339.16
+ Firefox version 141.0

 **Changes in syn-nodejs-playwright-4.0** 
+ Applied security patches and updated Playwright and browser versions. 

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

### syn-nodejs-playwright-3.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-3.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 20.x
+ Playwright version 1.53.0
+ Playwright/test version 1.53.0
+ Chromium version 138.0.7204.168

 **Changes in syn-nodejs-playwright-3.0** 
+ Multi-browser support – You can now run your nodejs puppeteer canaries in either Firefox or Chrome
+ Support for visual monitoring

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

### syn-nodejs-playwright-2.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-2.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 20.x
+ Playwright version 1.49.1
+ Playwright/test version 1.49.1
+ Chromium version 131.0.6778.264

 **Changes in syn-nodejs-playwright-2.0** 
+ The mismatch between total duration and sum of timings for a given request in HAR file is fixed.
+ Supports dry runs for the canary which allows for adhoc executions or performing a safe canary update.

For more information, see the following:
+  [Playwright change log ](https://playwright.dev/docs/release-notes) 
+  [Playwright API reference](https://playwright.dev/docs/api/class-playwright) 

### syn-nodejs-playwright-1.0
<a name="Synthetics_runtimeversion-syn-nodejs-playwright-1.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 20.x
+ Playwright version 1.44.1
+ Playwright/test version 1.44.1
+ Chromium version 126.0.6478.126

**Features**:
+ **PlayWright support** – You can write canary scripts by using the Playwright automation framework. You can bring your existing Playwright scripts to run as canaries, and enhance them with AWS monitoring capabilities. 
+ **CloudWatch Logs integration** – You can query and filter for logs through the CloudWatch Synthetics console. Each log message contains unique `canaryRunId`, making it easy to search for logs for a particular canary run. 
+ **Metrics and canary artifacts** – You can monitor canary run pass rate through CloudWatch metrics, and configure alarms to alert you when canaries detect issues. 
+ **Screenshots and steps association** – You can capture screenshots using native Playwright functionality to visualize the stages of a canary script on each run. Screenshots are automatically associated with canary steps, and are uploaded to Amazon S3 buckets. 
+ **Multiple tabs**– You can create canaries that open multiple browser tabs, and access screenshots from each tab. You can create multi-tab and multi-step user workflows in Synthetics. 

# Runtime versions using Node.js and Puppeteer
<a name="CloudWatch_Synthetics_Library_nodejs_puppeteer"></a>

The first runtime version for Node.js and Puppeteer was named `syn-1.0`. Later runtime versions have the naming convention `syn-language -majorversion.minorversion`. Starting with `syn-nodejs-puppeteer-3.0`, the naming convention is `syn- language-framework-majorversion .minorversion` 

An additional `-beta` suffix shows that the runtime version is currently in a beta preview release.

Runtime versions with the same major version number are backward compatible. 

The Lambda code in a canary is configured to have a maximum memory of 1 GB. Each run of a canary times out after a configured timeout value. If no timeout value is specified for a canary, CloudWatch chooses a timeout value based on the canary's frequency. If you configure a timeout value, make it no shorter than 15 seconds to allow for Lambda cold starts and the time it takes to boot up the canary instrumentation.

## syn-nodejs-puppeteer-15.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-15.0"></a>

`syn-nodejs-puppeteer-15.0` is the most recent Synthetics runtime for Node.js and Puppeteer. 

**Important**  
Starting Synthetics `syn-nodejs-puppeteer-13.1` and later, Synthetics runtime uses the new namespace. Please migrate the canary script to use new namespaces. Legacy namespaces will be deprecated in a future release.  
Synthetics → @aws/synthetics-puppeteer
SyntheticsLink → @aws/synthetics-link
SyntheticsLogger → @aws/synthetics-logger
SyntheticsLogHelper → @aws/synthetics-log-helper
BrokenLinkCheckerReport → @aws/synthetics-broken-link-checker-report

**Important**  
Synthetics runtime `syn-nodejs-puppeteer-11.0` and later versions support only the following step-level configuration overrides:  
 `screenshotOnStepStart` 
 `screenshotOnStepSuccess` 
 `screenshotOnStepFailure` 
 `stepSuccessMetric` 
 `stepDurationMetric` 
 `continueOnStepFailure/continueOnHttpStepFailure` 
 `stepsReport` 

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG#24375-2026-02-19) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.37.5/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 22.x
+ Puppeteer-core version 24.37.5
+ Chromium version 145.0.7632.77
+ Firefox version 147.0.4

 **Changes in syn-nodejs-puppeteer-15.0** 
+ Applied security patches and updated Puppeteer and browser versions.
+ Fixed bug where continueOnHttpStepFailure was not being honored, causing canary runs to be incorrectly marked as successful despite HTTP step failures occurring.

## Previous runtime versions for Node.js and Puppeteer
<a name="Previousversions-nodejs-puppeteer"></a>

The following earlier runtime versions for Node.js and Puppeteer are still supported. 

### syn-nodejs-puppeteer-14.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-14.0"></a>

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG#24340-2025-12-19) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.34.0/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 22.x
+ Puppeteer-core version 24.34.0
+ Chromium version 143.0.7499.169
+ Firefox version 146.x

 **Changes in syn-nodejs-puppeteer-14.0** 
+ Applied security patches and updated Puppeteer and browser versions.

### syn-nodejs-puppeteer-13.1
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-13.1"></a>

`syn-nodejs-puppeteer-13.1` is the most recent Synthetics runtime for Node.js and Puppeteer. 

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG#24250-2025-10-15) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.2.0/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 22.x
+ Puppeteer-core version 24.25.0
+ Chromium version 142.0.7444.175
+ Firefox version 145.x

 **Changes in syn-nodejs-puppeteer-13.1** 
+ Synthetics runtime namespace migration.
+ Type definitions are available in npm Registry. Please ensure the type definition package version matches your canary's runtime version.
  +  [ @aws/synthetics-puppeteer](https://www.npmjs.com/package/@aws/synthetics-puppeteer) 
  +  [ @aws/synthetics-link](https://www.npmjs.com/package/@aws/synthetics-link) 
  +  [ @aws/synthetics-broken-link-checker-report](https://www.npmjs.com/package/@aws/synthetics-broken-link-checker-report) 
  +  [ @aws/synthetics-log-helper](https://www.npmjs.com/package/@aws/synthetics-log-helper) 
  +  [ @aws/synthetics-logger](https://www.npmjs.com/package/@aws/synthetics-logger) 

### syn-nodejs-puppeteer-13.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-13.0"></a>

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG#24250-2025-10-15) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.2.0/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 22.x
+ Puppeteer-core version 24.25.0
+ Chromium version 142.0.7444.175
+ Firefox version 145.x

 **Changes in syn-nodejs-puppeteer-13.0** 
+ Applied security patches and updated Puppeteer and browser versions.
+ Bug fix – Fixed intermittent runtime extension crash issue caused by concurrent map access

### syn-nodejs-puppeteer-12.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-12.0"></a>

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG#24221-2025-09-23) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.22.1/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 22.x
+ Puppeteer-core version 24.22.1
+ Chromium version 140.0.7339.185
+ Firefox version 143.0.1

 **Changes in syn-nodejs-puppeteer-12.0** 
+ Applied security patches and updated Puppeteer and browser versions.
+ Bug fix for Restricted header redaction – Fixed an issue where in some situations restricted headers were not being redacted in executeHttpStep(). Behavior is now consistent with Puppeteer 10.0.
+ Bug fix for includeResponseBody configuration – Fixed an issue where HAR file generation can misapply the includeResponseBody configuration setting in certain situations. HAR now ensures response bodies are excluded when setting is configured.
+ Request capture lifecycle fixed – Fixed an issue where in some situations the HTTP request capturer may cause continuous aggregation of requests. Recording now terminates correctly after each step execution.

### syn-nodejs-puppeteer-11.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-11.0"></a>

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.2.0/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 20.x
+ Puppeteer-core version 24.15.0
+ Chromium version 138.0.7204.168

 **Changes in syn-nodejs-puppeteer-11.0** 
+ Multi-browser support – You can now run Node.js Puppeteer canaries in either Firefox or Chrome
+ Simplified packaging – Package scripts directly under root without using the Node.js/node\$1modules directory structure
+ Screenshot integration – Capture screenshots using native Puppeteer functions to visualize canary script stages. Synthetics automatically associates screenshots with canary steps and uploads them to Amazon S3
+ Enhanced log querying – Query and filter logs through the CloudWatch Insights console. Each log message includes a unique `canaryRunId` for easier searching
+ Configuration file support – Define and update Synthetics settings using a synthetics.json file. This separation of configuration from script logic improves maintenance and reusability
+ Multiple tabs support – Create canaries that open multiple browser tabs and access screenshots from each tab. Build multi-tab and multi-step user workflows in Synthetics
+ Security fixes
+ Visual monitoring bug fixes
+ Added support for structured JSON logging with configurable log levels – Logs are now emitted in JSON format to enable easier parsing and querying in CloudWatch. Log level is configurable (for example, DEBUG, INFO, TRACE) through environment variables allowing users to control verbosity based on their needs
+ Support for ES syntax

### syn-nodejs-puppeteer-10.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-10.0"></a>

For more information, see the following:
+  [Puppeteer Change log](https://pptr.dev/CHANGELOG) 
+  [Puppeteer API reference](https://github.com/puppeteer/puppeteer/blob/puppeteer-v24.2.0/docs/api/index.md) 

**Major dependencies**:
+ Lambda runtime Node.js 20.x
+ Puppeteer-core version 24.2.0
+ Chromium version 131.0.6778.264

 **Changes in syn-nodejs-puppeteer-10.0** 
+ The bug related to closing the browser that took excessively long is fixed.
+ Supports dry runs for the canary which allows for adhoc executions or performing a safe canary update.

### syn-nodejs-puppeteer-9.1
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-9.1"></a>

**Major dependencies**:
+ Lambda runtime Node.js 20.x
+ Puppeteer-core version 22.12.1
+ Chromium version 126.0.6478.126

**Changes in syn-nodejs-puppeteer-9.1** – Bug fixes related to date ranges and pending requests in HAR files are fixed.

### syn-nodejs-puppeteer-9.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-9.0"></a>

**Major dependencies**:
+ Lambda runtime Node.js 20.x
+ Puppeteer-core version 22.12.1
+ Chromium version 126.0.6478.126

**Changes in syn-nodejs-puppeteer-9.0** – The bug fix to enable visual monitoring capabilities is fixed.

### syn-nodejs-puppeteer-8.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-8.0"></a>

**Warning**  
Because of a bug, the `syn-nodejs-puppeteer-8.0` runtime doesn't support visual monitoring in canaries. Upgrade to [syn-nodejs-puppeteer-9.0](#CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-9.0) for the bug fix for visual monitoring.

**Important**  
Lambda Node.js 18 and later runtimes use AWS SDK for JavaScript V3. If you need to migrate a canary from an earlier runtime, follow the [aws-sdk-js-v3 Migration Workshop](https://github.com/aws-samples/aws-sdk-js-v3-workshop) on GitHub. For more information about AWS SDK for JavaScript version 3, see [this blog post](https://aws.amazon.com/blogs/developer/modular-aws-sdk-for-javascript-is-now-generally-available/).

**Major dependencies**:
+ Lambda runtime Node.js 20.x
+ Puppeteer-core version 22.10.0
+ Chromium version 125.0.6422.112

**Updates in syn-nodejs-puppeteer-8.0**:
+  **Support for two-factor authentication** 
+ **Bug fixes** related to some service clients losing data in Node.js SDK V3 responses is fixed.

## Deprecated runtime versions for Node.js and Puppeteer
<a name="CloudWatch_Synthetics_nodejs-puppeteer-Deprecated"></a>

The following runtimes for Node.js and Puppeteer have been deprecated. For information about runtime deprecation dates, see [CloudWatch Synthetics runtime deprecation dates](CloudWatch_Synthetics_Runtime_Support_Policy.md#runtime_deprecation_dates).

### syn-nodejs-puppeteer-7.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-7.0"></a>

**Major dependencies**:
+ Lambda runtime Node.js 18.x
+ Puppeteer-core version 21.9.0
+ Chromium version 121.0.6167.139

**Code size**:

The size of code and dependencies that you can package into this runtime is 80 MB.

**Updates in syn-nodejs-puppeteer-7.0**:
+ **Updated versions of the bundled libraries in Puppeteer and Chromium**— The Puppeteer and Chromium dependencies are updated to new versions.
**Important**  
Moving from Puppeteer 19.7.0 to Puppeteer 21.9.0 introduces breaking changes regarding testing and filters. For more information, see the **BREAKING CHANGES** sections in [puppeteer: v20.0.0](https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-v20.0.0) and [puppeteer-core: v21.0.0](https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v21.0.0).

 **Recommended upgrade to AWS SDK v3** 

The Lambda nodejs18.x runtime doesn't support AWS SDK v2. We strongly recommend that you migrate to AWS SDK v3.

### syn-nodejs-puppeteer-6.2
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-6.2"></a>

**Major dependencies**:
+ Lambda runtime Node.js 18.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Changes in syn-nodejs-puppeteer-6.2**:
+  **Updated versions of the bundled libraries in Chromium** 
+ **Ephemeral storage monitoring**— This runtime adds ephemeral storage monitoring in customer accounts.
+  **Bug fixes** 

### syn-nodejs-puppeteer-6.1
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-6.1"></a>

**Major dependencies**:
+ Lambda runtime Node.js 18.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Updates in syn-nodejs-puppeteer-6.1**:
+ **Stability improvements**— Added auto-retry logic for handling intermittent Puppeteer launch errors.
+ **Dependency upgrades**— Upgrades for some third-party dependency packages.
+ **Canaries without Amazon S3 permissions**— Bug fixes, such that canaries that don't have any Amazon S3 permissions can still run. These canaries with no Amazon S3 permissions won't be able to upload screenshots or other artifacts to Amazon S3. For more information about permissions for canaries, see [Required roles and permissions for canaries](CloudWatch_Synthetics_Canaries_CanaryPermissions.md).

**Important**  
IMPORTANT: The included AWS SDK for JavaScript v2 dependency will be removed and updated to use AWS SDK for JavaScript v3 in a future runtime release. When that happens, you can update your canary code references. Alternatively, you can continue referencing and using the included AWS SDK for JavaScript v2 dependency by adding it as a dependency to your source code zip file.

### syn-nodejs-puppeteer-6.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-6.0"></a>

**Major dependencies**:
+ Lambda runtime Node.js 18.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Updates in syn-nodejs-puppeteer-6.0**:
+ **Dependency upgrade**— The Node.js dependency is upgraded to 18.x.
+ **Intercept mode support**— Puppeteer cooperative intercept mode support was added to the Synthetics canary runtime library.
+ **Tracing behavior change**— Changed default tracing behavior to trace only fetch and xhr requests, and not trace resource requests. You can enable the tracing of resource requests by configuring the `traceResourceRequests` option.
+ **Duration metric refined**— The ` Duration` metric now excludes the operation time the canary uses to upload artifacts, take screenshots, and generate CloudWatch metrics. `Duration` metric values are reported to CloudWatch, and you can also see them in the Synthetics console.
+ **Bug fix**— Clean up core dump generated when Chromium crashes during a canary run.

**Important**  
IMPORTANT: The included AWS SDK for JavaScript v2 dependency will be removed and updated to use AWS SDK for JavaScript v3 in a future runtime release. When that happens, you can update your canary code references. Alternatively, you can continue referencing and using the included AWS SDK for JavaScript v2 dependency by adding it as a dependency to your source code zip file.

### syn-nodejs-puppeteer-5.2
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-5.2"></a>

**Major dependencies**:
+ Lambda runtime Node.js 16.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Updates in syn-nodejs-puppeteer-5.2**:
+  **Updated versions of the bundled libraries in Chromium** 
+  **Bug fixes** 

### syn-nodejs-puppeteer-5.1
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-5.1"></a>

**Major dependencies**:
+ Lambda runtime Node.js 16.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Bug fixes in syn-nodejs-puppeteer-5.1**:
+ **Bug fix**— This runtime fixes a bug in ` syn-nodejs-puppeteer-5.0` where the HAR files created by the canaries were missing request headers.

### syn-nodejs-puppeteer-5.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-5.0"></a>

**Major dependencies**:
+ Lambda runtime Node.js 16.x
+ Puppeteer-core version 19.7.0
+ Chromium version 111.0.5563.146

**Updates in syn-nodejs-puppeteer-5.0**:
+ **Dependency upgrade**— The Puppeteer-core version is updated to 19.7.0. The Chromium version is upgraded to 111.0.5563.146.

**Important**  
The new Puppeteer-core version is not completely backward-compatible with previous versions of Puppeteer. Some of the changes in this version can cause existing canaries that use deprecated Puppeteer functions to fail. For more information, see the breaking changes in the change logs for Puppeteer-core versions 19.7.0 through 6.0, in [Puppeteer change logs](https://github.com/puppeteer/puppeteer/releases?q=breaking&expanded=true).

### syn-nodejs-puppeteer-4.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-4.0"></a>

**Major dependencies**:
+ Lambda runtime Node.js 16.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-4.0**:
+ **Dependency upgrade**— The Node.js dependency is updated to 16.x.

### syn-nodejs-puppeteer-3.9
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.9"></a>

**Important**  
This runtime version was deprecated on January 8, 2024. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 14.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-3.9**:
+ **Dependency upgrades**— Upgrades some third-party dependency packages.

### syn-nodejs-puppeteer-3.8
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.8"></a>

**Important**  
This runtime version was deprecated on January 8, 2024. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 14.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-3.8**:
+ **Profile cleanup**— Chromium profiles are now cleaned up after each canary run.

**Bug fixes in syn-nodejs-puppeteer-3.8**:
+ **Bug fixes**— Previously, visual monitoring canaries would sometimes stop working properly after a run with no screenshots. This is now fixed.

### syn-nodejs-puppeteer-3.7
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.7"></a>

**Important**  
This runtime version was deprecated on January 8, 2024. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 14.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-3.7**:
+ **Logging enhancement**— The canary will upload logs to Amazon S3 even if it times out or crashes.
+ **Lambda layer size reduced**— The size of the Lambda layer used for canaries is reduced by 34%.

**Bug fixes in syn-nodejs-puppeteer-3.7**:
+ **Bug fixes**— Japanese, Simplified Chinese, and Traditional Chinese fonts will render properly.

### syn-nodejs-puppeteer-3.6
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.6"></a>

**Important**  
This runtime version was deprecated on January 8, 2024. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 14.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-3.6**:
+ **More precise timestamps**— The start time and stop time of canary runs are now precise to the millisecond.

### syn-nodejs-puppeteer-3.5
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.5"></a>

**Important**  
This runtime version was deprecated on January 8, 2024. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 14.x
+ Puppeteer-core version 5.5.0
+ Chromium version 92.0.4512

**Updates in syn-nodejs-puppeteer-3.5**:
+ **Updated dependencies**— The only new features in this runtime are the updated dependencies.

### syn-nodejs-puppeteer-3.4
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.4"></a>

**Important**  
This runtime version was deprecated on November 13, 2022. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 12.x
+ Puppeteer-core version 5.5.0
+ Chromium version 88.0.4298.0

**Updates in syn-nodejs-puppeteer-3.4**:
+ **Custom handler function**— You can now use a custom handler function for your canary scripts. Previous runtimes required the script entry point to include `.handler`. 

  You can also put canary scripts in any folder and pass the folder name as part of the handler. For example, `MyFolder/MyScriptFile.functionname` can be used as an entry point.
+ **Expanded HAR file information**— You can now see bad, pending, and incomplete requests in the HAR files produced by canaries.

### syn-nodejs-puppeteer-3.3
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.3"></a>

**Important**  
This runtime version was deprecated on November 13, 2022. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 12.x
+ Puppeteer-core version 5.5.0
+ Chromium version 88.0.4298.0

**Updates in syn-nodejs-puppeteer-3.3**:
+ **More options for artifact encryption**— For canaries using this runtime or later, instead of using an AWS managed key to encrypt artifacts that the canary stores in Amazon S3, you can choose to use an AWS KMS customer managed key or an Amazon S3-managed key. For more information, see [Encrypting canary artifacts](CloudWatch_Synthetics_artifact_encryption.md). 

### syn-nodejs-puppeteer-3.2
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.2"></a>

**Important**  
This runtime version was deprecated on November 13, 2022. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 12.x
+ Puppeteer-core version 5.5.0
+ Chromium version 88.0.4298.0

**Updates in syn-nodejs-puppeteer-3.2**:
+ **visual monitoring with screenshots**— Canaries using this runtime or later can compare a screenshot taken during a run with a baseline version of the same screenshot. If the screenshots are more different than a specified percentage threshold, the canary fails. For more information, see [Visual monitoring](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_SyntheticsLogger_VisualTesting) or [Visual monitoring blueprint](CloudWatch_Synthetics_Canaries_Blueprints.md#CloudWatch_Synthetics_Canaries_Blueprints_VisualTesting). 
+ **New functions regarding sensitive data** You can prevent sensitive data from appearing in canary logs and reports. For more information, see [SyntheticsLogHelper class](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_SyntheticsLogHelper).
+ **Deprecated function** The ` RequestResponseLogHelper` class is deprecated in favor of other new configuration options. For more information, see [RequestResponseLogHelper class](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_RequestResponseLogHelper).

### syn-nodejs-puppeteer-3.1
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.1"></a>

**Important**  
This runtime version was deprecated on November 13, 2022. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 12.x
+ Puppeteer-core version 5.5.0
+ Chromium version 88.0.4298.0

**Updates in syn-nodejs-puppeteer-3.1**:
+ **Ability to configure CloudWatch metrics**— With this runtime, you can disable the metrics that you do not require. Otherwise, canaries publish various CloudWatch metrics for each canary run.
+ **Screenshot linking**— You can link a screenshot to a canary step after the step has completed. To do this, you take the screenshot by using the **takeScreenshot** method, using the name of the step that you want to associate the screenshot with. For example, you might want to perform a step, add a wait time, and then take the screenshot.
+ **Heartbeat monitor blueprint can monitor multiple URLs**— You can use the heartbeat monitoring blueprint in the CloudWatch console to monitor multiple URLs and see the status, duration, associated screenshots, and failure reason for each URL in the step summary of the canary run report.

### syn-nodejs-puppeteer-3.0
<a name="CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.0"></a>

**Important**  
This runtime version was deprecated on November 13, 2022. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 12.x
+ Puppeteer-core version 5.5.0
+ Chromium version 88.0.4298.0

**Updates in syn-nodejs-puppeteer-3.0**:
+ **Upgraded dependencies**— This version uses Puppeteer version 5.5.0, Node.js 12.x, and Chromium 88.0.4298.0.
+ **Cross-Region bucket access**— You can now specify an S3 bucket in another Region as the bucket where your canary stores its log files, screenshots, and HAR files.
+ **New functions available**— This version adds library functions to retrieve the canary name and the Synthetics runtime version.

  For more information, see [Synthetics class](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_Synthetics_Class_all).

### syn-nodejs-2.2
<a name="CloudWatch_Synthetics_runtimeversion-2.2"></a>

This section contains information about the `syn-nodejs-2.2` runtime version.

**Important**  
This runtime version was deprecated on May 28, 2021. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 10.x
+ Puppeteer-core version 3.3.0
+ Chromium version 83.0.4103.0

**Changes in syn-nodejs-2.2**:
+ **Monitor your canaries as HTTP steps**— You can now test multiple APIs in a single canary. Each API is tested as a separate HTTP step, and CloudWatch Synthetics monitors the status of each step using step metrics and the CloudWatch Synthetics step report. CloudWatch Synthetics creates ` SuccessPercent` and `Duration` metrics for each HTTP step.

  This functionality is implemented by the **executeHttpStep(stepName, requestOptions, callback, stepConfig)** function. For more information, see [executeHttpStep(stepName, requestOptions, [callback], [stepConfig])](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_executeHttpStep).

  The API canary blueprint is updated to use this new feature.
+ **HTTP request reporting**— You can now view detailed HTTP requests reports which capture details such as request/response headers, response body, status code, error and performance timings, TCP connection time, TLS handshake time, first byte time, and content transfer time. All HTTP requests which use the HTTP/HTTPS module under the hood are captured here. Headers and response body are not captured by default but can be enabled by setting configuration options.
+ **Global and step-level configuration**— You can set CloudWatch Synthetics configurations at the global level, which are applied to all steps of canaries. You can also override these configurations at the step level by passing configuration key/value pairs to enable or disable certain options.

  For more information, see [SyntheticsConfiguration class](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_SyntheticsConfiguration).
+ **Continue on step failure configuration**— You can choose to continue canary execution when a step fails. For the ` executeHttpStep` function, this is turned on by default. You can set this option once at global level or set it differently per-step. 

### syn-nodejs-2.1
<a name="CloudWatch_Synthetics_runtimeversion-2.1"></a>

**Important**  
This runtime version was deprecated on May 28, 2021. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 10.x
+ Puppeteer-core version 3.3.0
+ Chromium version 83.0.4103.0

**Updates in syn-nodejs-2.1**:
+ **Configurable screenshot behavior**— Provides the ability to turn off the capturing of screenshots by UI canaries. In canaries that use previous versions of the runtimes, UI canaries always capture screenshots before and after each step. With `syn-nodejs-2.1`, this is configurable. Turning off screenshots can reduce your Amazon S3 storage costs, and can help you comply with HIPAA regulations. For more information, see [SyntheticsConfiguration class](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_SyntheticsConfiguration).
+ **Customize the Google Chrome launch parameters** You can now configure the arguments used when a canary launches a Google Chrome browser window. For more information, see [launch(options)](CloudWatch_Synthetics_Canaries_Library_Nodejs.md#CloudWatch_Synthetics_Library_LaunchOptions).

There can be a small increase in canary duration when using syn-nodejs-2.0 or later, compared to earlier versions of the canary runtimes.

### syn-nodejs-2.0
<a name="CloudWatch_Synthetics_runtimeversion-2.0"></a>

**Important**  
This runtime version was deprecated on May 28, 2021. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 10.x
+ Puppeteer-core version 3.3.0
+ Chromium version 83.0.4103.0

**Updates in syn-nodejs-2.0**:
+ **Upgraded dependencies**— This runtime version uses Puppeteer-core version 3.3.0 and Chromium version 83.0.4103.0
+ **Support for X-Ray active tracing.** When a canary has tracing enabled, X-Ray traces are sent for all calls made by the canary that use the browser, the AWS SDK, or HTTP or HTTPS modules. Canaries with tracing enabled appear on the X-Ray Trace Map, even when they don't send requests to other services or applications that have tracing enabled. For more information, see [Canaries and X-Ray tracing](CloudWatch_Synthetics_Canaries_tracing.md).
+ **Synthetics reporting**— For each canary run, CloudWatch Synthetics creates a report named ` SyntheticsReport-PASSED.json` or ` SyntheticsReport-FAILED.json` which records data such as start time, end time, status, and failures. It also records the PASSED/FAILED status of each step of the canary script, and failures and screenshots captured for each step.
+ **Broken link checker report**— The new version of the broken link checker included in this runtime creates a report that includes the links that were checked, status code, failure reason (if any), and source and destination page screenshots.
+ **New CloudWatch metrics**— Synthetics publishes metrics named `2xx`, `4xx`, `5xx`, and `RequestFailed` in the `CloudWatchSynthetics` namespace. These metrics show the number of 200s, 400s, 500s, and request failures in the canary runs. With this runtime version, these metrics are reported only for UI canaries, and are not reported for API canaries. They are also reported for API canaries starting with runtime version ` syn-nodejs-puppeteeer-2.2`.
+ **Sortable HAR files**— You can now sort your HAR files by status code, request size, and duration.
+ **Metrics timestamp**— CloudWatch metrics are now reported based on the Lambda invocation time instead of the canary run end time.

**Bug fixes in syn-nodejs-2.0**:
+ Fixed the issue of canary artifact upload errors not being reported. Such errors are now surfaced as execution errors.
+ Fixed the issue of redirected requests (3xx) being incorrectly logged as errors.
+ Fixed the issue of screenshots being numbered starting from 0. They should now start with 1.
+ Fixed the issue of screenshots being garbled for Chinese and Japanese fonts.

There can be a small increase in canary duration when using syn-nodejs-2.0 or later, compared to earlier versions of the canary runtimes.

### syn-nodejs-2.0-beta
<a name="CloudWatch_Synthetics_runtimeversion-2.0-beta"></a>

**Important**  
This runtime version was deprecated on February 8, 2021. For more information, see [Runtime versions support policy](CloudWatch_Synthetics_Runtime_Support_Policy.md).

**Major dependencies**:
+ Lambda runtime Node.js 10.x
+ Puppeteer-core version 3.3.0
+ Chromium version 83.0.4103.0

**Changes in syn-nodejs-2.0-beta**:
+ **Upgraded dependencies**— This runtime version uses Puppeteer-core version 3.3.0 and Chromium version 83.0.4103.0
+ **Synthetics reporting**— For each canary run, CloudWatch Synthetics creates a report named ` SyntheticsReport-PASSED.json` or ` SyntheticsReport-FAILED.json` which records data such as start time, end time, status, and failures. It also records the PASSED/FAILED status of each step of the canary script, and failures and screenshots captured for each step.
+ **Broken link checker report**— The new version of the broken link checker included in this runtime creates a report that includes the links that were checked, status code, failure reason (if any), and source and destination page screenshots.
+ **New CloudWatch metrics**— Synthetics publishes metrics named `2xx`, `4xx`, `5xx`, and `RequestFailed` in the `CloudWatchSynthetics` namespace. These metrics show the number of 200s, 400s, 500s, and request failures in the canary runs. These metrics are reported only for UI canaries, and are not reported for API canaries.
+ **Sortable HAR files**— You can now sort your HAR files by status code, request size, and duration.
+ **Metrics timestamp**— CloudWatch metrics are now reported based on the Lambda invocation time instead of the canary run end time.

**Bug fixes in syn-nodejs-2.0-beta**:
+ Fixed the issue of canary artifact upload errors not being reported. Such errors are now surfaced as execution errors.
+ Fixed the issue of redirected requests (3xx) being incorrectly logged as errors.
+ Fixed the issue of screenshots being numbered starting from 0. They should now start with 1.
+ Fixed the issue of screenshots being garbled for Chinese and Japanese fonts.

### syn-1.0
<a name="CloudWatch_Synthetics_runtimeversion-1.0"></a>

The first Synthetics runtime version is `syn-1.0`.

**Major dependencies**:
+ Lambda runtime Node.js 10.x
+ Puppeteer-core version 1.14.0
+ The Chromium version that matches Puppeteer-core 1.14.0

# Runtime versions using Python and Selenium Webdriver
<a name="CloudWatch_Synthetics_Library_python_selenium"></a>

The following sections contain information about the CloudWatch Synthetics runtime versions for Python and Selenium Webdriver. Selenium is an open-source browser automation tool. For more information about Selenium, see [ www.selenium.dev/](https://www.selenium.dev)

For features and methods supported by Synthetics runtime on Selenium framework, see [Python and Selenium library classes and functions that apply to UI canaries only ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library_Python.html#CloudWatch_Synthetics_Library_Python_UIcanaries) and [Selenium API reference](https://www.selenium.dev/selenium/docs/api/py/api.html).

The naming convention for these runtime versions is `syn-language -framework-majorversion. minorversion`.

## syn-python-selenium-10.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-10.0"></a>

Version 10.0 is the newest CloudWatch Synthetics runtime for Python and Selenium.

**Major dependencies**:
+ Python 3.11
+ Selenium 4.32.0
+ Chromium version 145.0.7632.77

**Changes in syn-python-selenium-10.0 ** 
+ Applied security patches and updated browser versions.

For more information, see the following:
+  [Selenium Change log](https://www.selenium.dev/blog/2025/selenium-4-32-released) 
+  [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/api.html) 

## Previous runtime versions for Python and Selenium
<a name="Previousversions-python-selenium"></a>

The following earlier runtime versions for Python and Selenium are still supported. 

### syn-python-selenium-9.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-9.0"></a>

**Major dependencies**:
+ Python 3.11
+ Selenium 4.32.0
+ Chromium version 143.0.7499.169

**Changes in syn-python-selenium-9.0 ** 
+ Applied security patches and updated browser versions.

For more information, see the following:
+  [Selenium Change log](https://www.selenium.dev/blog/2025/selenium-4-32-released) 
+  [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/api.html) 

### syn-python-selenium-8.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-8.0"></a>

Version 8.0 is the newest CloudWatch Synthetics runtime for Python and Selenium.

**Major dependencies**:
+ Python 3.11
+ Selenium 4.32.0
+ Chromium version 142.0.7444.175

**Changes in syn-python-selenium-8.0 ** 
+ Applied security patches and updated Selenium and browser versions.
+ Modified failed HAR network request log level from ERROR to INFO.

For more information, see the following:
+  [Selenium Change log](https://www.selenium.dev/blog/2025/selenium-4-32-released) 
+  [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/api.html) 

### syn-python-selenium-7.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-7.0"></a>

**Major dependencies**:
+ Python 3.11
+ Selenium 4.32.0
+ Chromium version 138.0.7204.168

 **Changes in syn-python-selenium-7.0 ** 
+ Applied security patches and updated Selenium and browser versions.

For more information, see the following:
+  [Selenium Change log](https://www.selenium.dev/blog/2025/selenium-4-32-released) 
+  [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/api.html) 

### syn-python-selenium-6.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-6.0"></a>

**Major dependencies**:
+ Python 3.11
+ Selenium 4.21.0
+ Chromium version 131.0.6778.264

 **Changes in syn-python-selenium-6.0** 
+ Upgrade from Python 3.9 to Python 3.11.

For more information, see the following:
+  [Selenium Change log](https://www.selenium.dev/blog/2024/selenium-4-21-released/) 
+  [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/api.html) 

### syn-python-selenium-5.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-5.1"></a>

**Major dependencies**:
+ Python 3.9
+ Selenium 4.21.0
+ Chromium version 131.0.6778.264

 **Changes in syn-python-selenium-5.1** 
+ Minor updates on metric emission.
+ Supports dry runs for the canary which allows for adhoc executions or performing a safe canary update.

### syn-python-selenium-5.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-5.0"></a>

**Major dependencies**:
+ Python 3.9
+ Selenium 4.21.0
+ Chromium version 131.0.6778.264

**Changes in syn-python-selenium-5.0**:
+ Automatic retry if the browser fails to launch.

### syn-python-selenium-4.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-4.1"></a>

**Major dependencies**:
+ Python 3.9
+ Selenium 4.15.1
+ Chromium version 126.0.6478.126

**Changes in syn-python-selenium-4.1**:
+ **Addresses security vulnerability**– This runtime has an update to address the [CVE-2024-39689](https://nvd.nist.gov/vuln/detail/CVE-2024-39689) vulnerability.

### syn-python-selenium-4.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-4.0"></a>

**Major dependencies**:
+ Python 3.9
+ Selenium 4.15.1
+ Chromium version 126.0.6478.126

**Changes in syn-python-selenium-4.0**:
+ **Bug fixes** for errors in HAR parser logging.

## Deprecated runtime versions for Python and Selenium
<a name="Deprecated-python-selenium"></a>

The following earlier runtime versions for Python and Selenium have been deprecated. For information about runtime deprecation dates, see [CloudWatch Synthetics runtime deprecation dates](CloudWatch_Synthetics_Runtime_Support_Policy.md#runtime_deprecation_dates).

### syn-python-selenium-3.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-3.0"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 4.15.1
+ Chromium version 121.0.6167.139

**Changes in syn-python-selenium-3.0**:
+ **Updated versions of the bundled libraries in Chromium**— The Chromium dependency is updated to a new version.

### syn-python-selenium-2.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-2.1"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 4.15.1
+ Chromium version 111.0.5563.146

**Changes in syn-python-selenium-2.1**:
+ **Updated versions of the bundled libraries in Chromium**— The Chromium and Selenium dependencies are updated to new versions.

### syn-python-selenium-2.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-2.0"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 4.10.0
+ Chromium version 111.0.5563.146

**Changes in syn-python-selenium-2.0**:
+ **Updated dependencies**— The Chromium and Selenium dependencies are updated to new versions.

**Bug fixes in syn-python-selenium-2.0**:
+ **Timestamp added**— A timestamp has been added to canary logs.
+ **Session re-use**— A bug was fixed so that canaries are now prevented from reusing the session from their previous canary run.

### syn-python-selenium-1.3
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-1.3"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 3.141.0
+ Chromium version 92.0.4512.0

**Changes in syn-python-selenium-1.3**:
+ **More precise timestamps**— The start time and stop time of canary runs are now precise to the millisecond.

### syn-python-selenium-1.2
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-1.2"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 3.141.0
+ Chromium version 92.0.4512.0
+ **Updated dependencies**— The only new features in this runtime are the updated dependencies.

### syn-python-selenium-1.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-1.1"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 3.141.0
+ Chromium version 83.0.4103.0

**Features**:
+ **Custom handler function**— You can now use a custom handler function for your canary scripts. Previous runtimes required the script entry point to include `.handler`. 

  You can also put canary scripts in any folder and pass the folder name as part of the handler. For example, `MyFolder/MyScriptFile.functionname` can be used as an entry point.
+ **Configuration options for adding metrics and step failure configurations**— These options were already available in runtimes for Node.js canaries. For more information, see [SyntheticsConfiguration class](CloudWatch_Synthetics_Canaries_Library_Python.md#CloudWatch_Synthetics_Library_SyntheticsConfiguration_Python) .
+ **Custom arguments in Chrome **— You can now open a browser in incognito mode or pass in proxy server configuration. For more information, see [Chrome()](CloudWatch_Synthetics_Canaries_Library_Python.md#CloudWatch_Synthetics_Library_Python_Chrome).
+ **Cross-Region artifact buckets**— A canary can store its artifacts in an Amazon S3 bucket in a different Region.
+ **Bug fixes, including a fix for the `index.py` issue**— With previous runtimes, a canary file named ` index.py` caused exceptions because it conflicted with the name of the library file. This issue is now fixed.

### syn-python-selenium-1.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-python-selenium-1.0"></a>

**Major dependencies**:
+ Python 3.8
+ Selenium 3.141.0
+ Chromium version 83.0.4103.0

**Features**:
+ **Selenium support**— You can write canary scripts using the Selenium test framework. You can bring your Selenium scripts from elsewhere into CloudWatch Synthetics with minimal changes, and they will work with AWS services.

# Runtime versions using Node.js
<a name="CloudWatch_Synthetics_Library_Nodejs"></a>

The following section contains information about the CloudWatch Synthetics runtime versions for Node.js. This runtime does not have any browser or framework included.

The naming convention for these runtime versions is `syn-language -majorversion.minorversion`.

## syn-nodejs-4.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-nodejs-4.1"></a>

**Important**  
Starting Synthetics `syn-nodejs-3.1` and later, Synthetics runtime uses the new namespace. Please migrate the canary script to use the new namespace. Legacy namespace will be deprecated in a future release.  
@amzn/synthetics-core → @aws/synthetics-core

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x

 **Changes in syn-nodejs-4.1** 
+ Upgrade `fast-xml-parser` to 5.5.7 to address the following CVEs:
  + CVE-2026-25128
  + CVE-2026-25896
  + CVE-2026-26278
  + CVE-2026-27942
  + CVE-2026-33036

## Previous runtime versions for Node.js
<a name="Previousversions-nodejs"></a>

The following earlier runtime versions for Node.js are still supported. 

### syn-nodejs-4.0
<a name="CloudWatch_Synthetics_runtimeversion-syn-nodejs-4.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 22.x

 **Changes in syn-nodejs-4.0** 
+ Applied security patches. 

### syn-nodejs-3.1
<a name="CloudWatch_Synthetics_runtimeversion-syn-nodejs-3.1"></a>

**Important**  
Starting Synthetics `syn-nodejs-3.1` and later, Synthetics runtime uses the new namespace. Please migrate the canary script to use the new namespace. Legacy namespace will be deprecated in a future release.  
@amzn/synthetics-core → @aws/synthetics-core

**Major dependencies**:
+ AWS Lambda runtime Node.js 20.x

 **Changes in syn-nodejs-3.1** 
+ Synthetics runtime namespace migration. 
+ Type definition is available in [npm Registry](https://www.npmjs.com/package/@aws/synthetics-core). Please ensure the type definition package version matches your canary's runtime version.

### syn-nodejs-3.0
<a name="Synthetics_runtimeversion-syn-nodejs-3.0"></a>

**Major dependencies**:
+ AWS Lambda runtime Node.js 20.x

 **Changes in syn-nodejs-3.0** 
+ Support for multi checks blueprint. 

# Runtime versions support policy
<a name="CloudWatch_Synthetics_Runtime_Support_Policy"></a>

Synthetics runtime versions are subject to maintenance and security updates. When any component of a runtime version is no longer supported, that Synthetics runtime version is deprecated.

You can't create canaries using deprecated runtime versions. Canaries that use deprecated runtimes continue to run. You can stop, start, and delete these canaries. You can update an existing canary that uses a deprecated runtime version by updating the canary to use a supported runtime version.

CloudWatch Synthetics notifies you by email if you have canaries that use runtimes that are scheduled to be deprecated in the next 60 days. We recommend that you migrate your canaries to a supported runtime version to benefit from the new functionality, security, and performance enhancements that are included in more recent releases. 

## CloudWatch Synthetics runtime deprecation dates
<a name="runtime_deprecation_dates"></a>

The following table lists the date of deprecation of each deprecated CloudWatch Synthetics runtime.


| Runtime Version | Deprecation date | 
| --- | --- | 
|   `syn-python-selenium-5.1`   |  February 3, 2026  | 
|   `syn-python-selenium-5.0`   |  February 3, 2026  | 
|   `syn-python-selenium-4.1`   |  February 3, 2026  | 
|   `syn-python-selenium-4.0`   |  February 3, 2026  | 
|   `syn-nodejs-puppeteer-7.0`   |  January 22, 2026  | 
|   `syn-nodejs-puppeteer-6.2`   |  January 22, 2026  | 
|   `syn-nodejs-puppeteer-5.2`   |  January 22, 2026  | 
|   `syn-python-selenium-3.0`   |  January 22, 2026  | 
|   `syn-python-selenium-2.1`   |  January 22, 2026  | 
|   `syn-nodejs-puppeteer-6.1`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-6.0`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-5.1`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-5.0`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-4.0`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-3.9`   |  January 8, 2024  | 
|   `syn-nodejs-puppeteer-3.8`   |  January 8, 2024  | 
|   `syn-python-selenium-2.0`   |  March 8, 2024  | 
|   `syn-python-selenium-1.3`   |  March 8, 2024  | 
|   `syn-python-selenium-1.2`   |  March 8, 2024  | 
|   `syn-python-selenium-1.1`   |  March 8, 2024  | 
|   `syn-python-selenium-1.0`   |  March 8, 2024  | 
|   `syn-nodejs-puppeteer-3.7`   |  January 8, 2024  | 
|   `syn-nodejs-puppeteer-3.6`   |  January 8, 2024  | 
|   `syn-nodejs-puppeteer-3.5`   |  January 8, 2024  | 
|   `syn-nodejs-puppeteer-3.4`   |  November 13, 2022  | 
|   `syn-nodejs-puppeteer-3.3`   |  November 13, 2022  | 
|   `syn-nodejs-puppeteer-3.2`   |  November 13, 2022  | 
|   `syn-nodejs-puppeteer-3.1`   |  November 13, 2022  | 
|   `syn-nodejs-puppeteer-3.0`   |  November 13, 2022  | 
|   `syn-nodejs-2.2`   |  May 28, 2021  | 
|   `syn-nodejs-2.1`   |  May 28, 2021  | 
|   `syn-nodejs-2.0`   |  May 28, 2021  | 
|   `syn-nodejs-2.0-beta`   |  February 8, 2021  | 
|   `syn-1.0`   |  May 28, 2021  | 

# Runtime versions update
<a name="CloudWatch_Synthetics_Runtime_Version_Update"></a>

You can update a canary’s runtime version by using the CloudWatch console, AWS CloudFormation, the AWS CLI or the AWS SDK. When you use the CloudWatch console, you can update up to five canaries at once by selecting them in the canary list page and then choosing **Actions** , **Update Runtime**.

You can verify the update by testing it first before committing the runtime update. When updating the runtime versions, choose the **Start Dry Run** or **Validate and save later** options in the CloudWatch console to create a dry run of the original canary along with any changes you made to the configuration. The dry run will update and execute the canary to validate whether the runtime update is safe for the canary. Once you have verified your canary with the new runtime version, you can update the runtime version of your canary. For more information, see [Performing safe canary updates](performing-safe-canary-upgrades.md).

Alternatively, you can verify the update by first cloning the canary using the CloudWatch console and updating the runtime version. This creates another canary which is a clone of your original canary. Once you have verified your canary with the new runtime version, you can update the runtime version of your original canary and delete the clone canary.

 You can also update multiple canaries using an upgrade script. For more information, see [Canary runtime upgrade script](#CloudWatch_Synthetics_Canaries_upgrade_script).

If you upgrade a canary and it fails, see [Troubleshooting a failed canary](CloudWatch_Synthetics_Canaries_Troubleshoot.md).

## Canary runtime upgrade script
<a name="CloudWatch_Synthetics_Canaries_upgrade_script"></a>

To upgrade a canary script to a supported runtime version, use the following script.

```
const AWS = require('aws-sdk');

// You need to configure your AWS credentials and Region.
//   https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html
//   https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html

const synthetics = new AWS.Synthetics();

const DEFAULT_OPTIONS = {
  /**
   * The number of canaries to upgrade during a single run of this script.
   */
  count: 10,
  /**
   * No canaries are upgraded unless force is specified.
   */
  force: false
};

/**
 * The number of milliseconds to sleep between GetCanary calls when
 * verifying that an update succeeded.
 */
const SLEEP_TIME = 5000;

(async () => {
  try {
    const options = getOptions();

    const versions = await getRuntimeVersions();
    const canaries = await getAllCanaries();
    const upgrades = canaries
      .filter(canary => !versions.isLatestVersion(canary.RuntimeVersion))
      .map(canary => {
        return {
          Name: canary.Name,
          FromVersion: canary.RuntimeVersion,
          ToVersion: versions.getLatestVersion(canary.RuntimeVersion)
        };
      });

    if (options.force) {
      const promises = [];

      for (const upgrade of upgrades.slice(0, options.count)) {
        const promise = upgradeCanary(upgrade);
        promises.push(promise);
        // Sleep for 100 milliseconds to avoid throttling.
        await usleep(100);
      }

      const succeeded = [];
      const failed = [];
      for (let i = 0; i < upgrades.slice(0, options.count).length; i++) {
        const upgrade = upgrades[i];
        const promise = promises[i];
        try {
          await promise;
          console.log(`The update of ${upgrade.Name} succeeded.`);
          succeeded.push(upgrade.Name);
        } catch (e) {
          console.log(`The update of ${upgrade.Name} failed with error: ${e}`);
          failed.push({
            Name: upgrade.Name,
            Reason: e
          });
        }
      }

      if (succeeded.length) {
        console.group('The following canaries were upgraded successfully.');
        for (const name of succeeded) {
          console.log(name);
        }
        console.groupEnd()
      } else {
        console.log('No canaries were upgraded successfully.');
      }

      if (failed.length) {
        console.group('The following canaries were not upgraded successfully.');
        for (const failure of failed) {
          console.log('\x1b[31m', `${failure.Name}: ${failure.Reason}`, '\x1b[0m');
        }
        console.groupEnd();
      }
    } else {
      console.log('Run with --force [--count <count>] to perform the first <count> upgrades shown. The default value of <count> is 10.')
      console.table(upgrades);
    }
  } catch (e) {
    console.error(e);
  }
})();

function getOptions() {
  const force = getFlag('--force', DEFAULT_OPTIONS.force);
  const count = getOption('--count', DEFAULT_OPTIONS.count);
  return { force, count };

  function getFlag(key, defaultValue) {
    return process.argv.includes(key) || defaultValue;
  }
  function getOption(key, defaultValue) {
    const index = process.argv.indexOf(key);
    if (index < 0) {
      return defaultValue;
    }
    const value = process.argv[index + 1];
    if (typeof value === 'undefined' || value.startsWith('-')) {
      throw `The ${key} option requires a value.`;
    }
    return value;
  }
}

function getAllCanaries() {
  return new Promise((resolve, reject) => {
    const canaries = [];

    synthetics.describeCanaries().eachPage((err, data) => {
      if (err) {
        reject(err);
      } else {
        if (data === null) {
          resolve(canaries);
        } else {
          canaries.push(...data.Canaries);
        }
      }
    });
  });
}

function getRuntimeVersions() {
  return new Promise((resolve, reject) => {
    const jsVersions = [];
    const pythonVersions = [];
    synthetics.describeRuntimeVersions().eachPage((err, data) => {
      if (err) {
        reject(err);
      } else {
        if (data === null) {
          jsVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate);
          pythonVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate);
          resolve({
            isLatestVersion(version) {
              const latest = this.getLatestVersion(version);
              return latest === version;
            },
            getLatestVersion(version) {
              if (jsVersions.some(v => v.VersionName === version)) {
                return jsVersions[jsVersions.length - 1].VersionName;
              } else if (pythonVersions.some(v => v.VersionName === version)) {
                return pythonVersions[pythonVersions.length - 1].VersionName;
              } else {
                throw Error(`Unknown version ${version}`);
              }
            }
          });
        } else {
          for (const version of data.RuntimeVersions) {
            if (version.VersionName === 'syn-1.0') {
              jsVersions.push(version);
            } else if (version.VersionName.startsWith('syn-nodejs-2.')) {
              jsVersions.push(version);
            } else if (version.VersionName.startsWith('syn-nodejs-puppeteer-')) {
              jsVersions.push(version);
            } else if (version.VersionName.startsWith('syn-python-selenium-')) {
              pythonVersions.push(version);
            } else {
              throw Error(`Unknown version ${version.VersionName}`);
            }
          }
        }
      }
    });
  });
}

async function upgradeCanary(upgrade) {
  console.log(`Upgrading canary ${upgrade.Name} from ${upgrade.FromVersion} to ${upgrade.ToVersion}`);
  await synthetics.updateCanary({ Name: upgrade.Name, RuntimeVersion: upgrade.ToVersion }).promise();
  while (true) {
    await usleep(SLEEP_TIME);
    console.log(`Getting the state of canary ${upgrade.Name}`);
    const response = await synthetics.getCanary({ Name: upgrade.Name }).promise();
    const state = response.Canary.Status.State;
    console.log(`The state of canary ${upgrade.Name} is ${state}`);
    if (state === 'ERROR' || response.Canary.Status.StateReason) {
      throw response.Canary.Status.StateReason;
    }
    if (state !== 'UPDATING') {
      return;
    }
  }
}

function usleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
```

# Writing a canary script
<a name="CloudWatch_Synthetics_Canaries_WritingCanary"></a>

The following sections explain how to write a canary script and how to integrate a canary with other AWS services and with external dependencies and libraries.

**Topics**
+ [Writing a canary script using the Java runtime](Synthetics_WritingCanary_Java.md)
+ [Writing a Node.js canary script using the Playwright runtime](Synthetics_WritingCanary_Nodejs_Playwright.md)
+ [Writing a Node.js canary script using the Puppeteer runtime](CloudWatch_Synthetics_Canaries_WritingCanary_Nodejs_Pup.md)
+ [Writing a Python canary script](CloudWatch_Synthetics_Canaries_WritingCanary_Python.md)
+ [Writing a JSON configuration for Node.js multi Checks blueprint](CloudWatch_Synthetics_WritingCanary_Multichecks.md)

# Writing a canary script using the Java runtime
<a name="Synthetics_WritingCanary_Java"></a>

**Topics**
+ [Java project structure for a canary](#Synthetics_canary_Java_package)
+ [Packaging the project for a canary](#Synthetics_canary_Java_package_canary)
+ [Handler name](#Synthetics_canary_Java_handler)
+ [CloudWatch Synthetics configurations](#Synthetics_canary_Java_config)
+ [CloudWatch Synthetics environment variables](#Synthetics_canary_Java_variables)

## Java project structure for a canary
<a name="Synthetics_canary_Java_package"></a>

To create a canary in Java, you need to write your code, compile it, and deploy the compiled artifacts to Synthetics. You can initialize a Java Lambda project in various ways. For instance, you can use a standard Java project setup in your preferred IDE, such as IntelliJ IDEA or Visual Studio Code. Alternatively, you can create the required file structure manually.

A Synthetics Java project contains the following general structure:

```
/project-root
    └ src
        └ main
            └ java
                └ canarypackage // name of package
                |    └ ExampleCanary.java // Canary code file
                |    └ other_supporting_classes
                - resources
                     └ synthetics.json // Synthetics configuration file    
     └ build.gradle OR pom.xml
```

You can use either Maven or Gradle to build your project and manage dependencies.

In the above structure, the `ExampleCanary` class is the entry point or handler for the canary.

 **Java canary class example** 

This example is for a canary to make a get request to a URL stored in the * TESTING\$1URL* Lambda environment variable. The canary does not use any of the methods provided by Synthetics runtime.

```
package canarypackage;

import java.net.HttpURLConnection;
import java.net.URL;

// Handler value: canary.ExampleCanary::canaryCode
public class ExampleCanary { 
  public void canaryCode() throws Exception{ 
      URL url = new URL(System.getenv("TESTING_URL"));
      HttpURLConnection con=(HttpURLConnection)url.openConnection();
      con.setRequestMethod("GET");
      con.setConnectTimeout(5000);
      con.setReadTimeout(5000);
      int status=con.getResponseCode();
      if(status!=200){
        throw new Exception("Failed to load " + url + ", status code: " + status);
      }
  }
}
```

It is highly recommended to modularize your canaries using the Synthetics provided library function `executeStep`. The canary makes `get` calls to two separate URLs procured from URL1 and URL2 environment variables.

**Note**  
To use the `executeStep` functionality, the handler method for the canary should take in a parameter of type Synthetics as shown below. 

```
package canarypackage;

import com.amazonaws.synthetics.Synthetics;
import java.net.HttpURLConnection;
import java.net.URL;

// Handler value: canary.ExampleCanary::canaryCode
public class ExampleCanary {
  public void canaryCode(Synthetics synthetics) throws Exception {
    createStep("Step1", synthetics, System.getenv("URL1"));
    createStep("Step2", synthetics, System.getenv("URL2"));
    return;
  }
  
  private void createStep(String stepName, Synthetics synthetics, String url) throws Exception{
    synthetics.executeStep(stepName,()->{
      URL obj=new URL(url);
      HttpURLConnection con=(HttpURLConnection)obj.openConnection();
      con.setRequestMethod("GET");
      con.setConnectTimeout(5000);
      con.setReadTimeout(5000);
      int status=con.getResponseCode();
      if(status!=200){
        throw new Exception("Failed to load" + url + "status code:" + status);
      }
      return null;
    }).get();
  }
}
```

## Packaging the project for a canary
<a name="Synthetics_canary_Java_package_canary"></a>

Synthetics accepts code for a java canary in the *zip* format. The zip consists of the class files for the canary code, the jars for any third party dependencies and the Synthetics configuration file.

A Synthetics Java zip contains the following general structure.

```
example-canary
    └ lib
    |  └ //third party dependency jars
       └ java-canary.jar
    └ synthetics.json
```

To build this zip from the above project structure, you can use gradle (build.gradle) or maven (pom.xml). Here is an example.

For information on compile time dependencies or interfaces for the Synthetics library, see the README under [ aws-cloudwatch-synthetics-sdk-java ](https://github.com/aws/aws-cloudwatch-synthetics-sdk-java/tree/main).

```
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    // Third party dependencies 
    // example: implementation 'software.amazon.awssdk:s3:2.31.9'
    
    // Declares dependency on Synthetics interfaces for compiling only
    // Refer https://github.com/aws/aws-cloudwatch-synthetics-sdk-java for building from source.
    compileOnly 'software.amazon.synthetics:aws-cloudwatch-synthetics-sdk-java:1.0.0'}

test {
    useJUnitPlatform()
}

// Build the zip to be used as Canary code.
task buildZip(type: Zip) {

    archiveFileName.set("example-canary.zip")
    destinationDirectory.set(file("$buildDir"))
    
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
        from(tasks.named("jar"))
    }
    from "src/main/java/resources/synthetics.json"
    
    doLast {
        println "Artifact written to: ${archiveFile.get().asFile.absolutePath}"
    }
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

tasks.named("build") {
    dependsOn "buildZip"
}
```

## Handler name
<a name="Synthetics_canary_Java_handler"></a>

The handler name is the entry point for the canary. For Java runtime, the handler is in the following format.

```
<<full qualified name for canary class>>::<<name of the method to start the execution from>>
// for above code: canarypackage.ExampleCanary::canaryCode
```

## CloudWatch Synthetics configurations
<a name="Synthetics_canary_Java_config"></a>

You can configure the behavior of the Synthetics Java runtime by providing an optional JSON configuration file named `synthetics.json`. This file should be packaged in the root directory of the package zip. Though a configuration file is optional, if you don't provide a configuration file, or a configuration key is missing, CloudWatch uses the defaults.

The following are supported configuration values, and their defaults.

```
{
    "step": {
        "stepSuccessMetric": true,
        "stepDurationMetric": true,
        "continueOnStepFailure": false,
        "stepsReport": true
    },
    "logging": {
        "logRequest": false,
        "logResponse": false
    },
    "httpMetrics": {
        "metric_2xx": true,
        "metric_4xx": true,
        "metric_5xx": true,
        "aggregated2xxMetric": true,
        "aggregated4xxMetric": true,
        "aggregated5xxMetric": true
    },
    "canaryMetrics": {
        "failedCanaryMetric": true,
        "aggregatedFailedCanaryMetric": true
    }
}
```

 **Step configurations** 
+ *continueOnStepFailure* – Determines if a script should continue even after a step has failed. The default is false.
+ *stepSuccessMetric* – Determines if a step's ` SuccessPercent` metric is emitted. The `SuccessPercent` metric for a step is *100* for the canary run if the step succeeds, and * 0 * if the step fails. The default is *true*.
+ *stepDurationMetric* – Determines if a step's * Duration* metric is emitted. The *Duration* metric is emitted as a duration, in milliseconds, of the step's run. The default is * true*.

 **Logging configurations** 

Applies to logs generated by CloudWatch Synthetics. Controls the verbosity of request and response logs.
+ *logRequest* – Specifies whether to log every request in canary logs. The default is false.
+ *logResponse* – Specifies whether to log every response in canary logs. The default is false.

 **HTTP metric configurations** 

Configurations for metrics related to the count of network requests with different HTTP status codes, emitted by CloudWatch Synthetics for this canary.
+ *metric\$12xx* – Specifies whether to emit the * 2xx* metric (with the CanaryName dimension) for this canary. The default is *true*.
+ *metric\$14xx* – Specifies whether to emit the * 4xx* metric (with the CanaryName dimension) for this canary. The default is *true*.
+ *metric\$15xx* – Specifies whether to emit the * 5xx* metric (with the CanaryName dimension) for this canary. The default is *true*.
+ *aggregated2xxMetric* – Specifies whether to emit the * 2xx* metric (without the CanaryName dimension) for this canary. The default is *true*.
+ *aggregated4xxMetric* – Specifies whether to emit the * 4xx* metric (without the CanaryName dimension) for this canary. The default is *true*.
+ *aggregated5xxMetric* – Specifies whether to emit the * 5xx* metric (without the CanaryName dimension) for this canary. The default is *true*.

 **Canary metric configurations** 

Configurations for other metrics emitted by CloudWatch Synthetics.
+ *failedCanaryMetric* Network Access Analyzer Specifies whether to emit the * Failed* metric (with the CanaryName dimension) for this canary. The default is *true*.
+ *aggregatedFailedCanaryMetric* – Specifies whether to emit the *Failed* metric (without the CanaryName dimension) for this canary. The default is *true*.

## CloudWatch Synthetics environment variables
<a name="Synthetics_canary_Java_variables"></a>

You can configure the logging level and format by using environment variables.

 **Log format** 

The CloudWatch Synthetics Java runtime creates CloudWatch logs for every canary run. Logs are written in JSON format for convenient querying. Optionally, you can change the log format to *TEXT*.
+ *Environment variable name* – CW\$1SYNTHETICS\$1LOG\$1FORMAT
+ *Supported values* – JSON, TEXT
+ *Default* –JSON

 **Log levels** 
+ *Environment variable name* – CW\$1SYNTHETICS\$1LOG\$1LEVEL
+ *Supported values* – TRACE, DEBUG, INFO, WARN, ERROR, FATAL
+ *Default* – INFO

Apart from the above environment variables, there is a default environment variable added for Java runtime, `AWS_LAMBDA-EXEC_WRAPPER` environment variable to your function, and set its value to `/opt/synthetics-otel-instrument`. This environment variable modifies your function's startup behavior for telemetry. If this environment variable already exists, make sure that it's set to the required value.

# Writing a Node.js canary script using the Playwright runtime
<a name="Synthetics_WritingCanary_Nodejs_Playwright"></a>

**Topics**
+ [Packaging your Node.js canary files for the Playwright runtime](#Synthetics_canary_Nodejs_Playwright_package)
+ [Changing an existing Playwright script to use as a CloudWatch Synthetics canary](#CloudWatch_Synthetics_canary_edit_Playwright_script)
+ [CloudWatch Synthetics configurations](#Synthetics_canary_configure_Playwright_script)

## Packaging your Node.js canary files for the Playwright runtime
<a name="Synthetics_canary_Nodejs_Playwright_package"></a>

 Your canary script comprises of a `.js` (CommonJS syntax) or `.mjs` (ES syntax) file containing your Synthetics handler code, together with any additional packages and modules your code depends on. Scripts created in ES (ECMAScript) format should either use .mjs as the extension or include a package.json file with the "type": "module" field set. Unlike other runtimes like Node.js Puppeteer, you are not required to save your scripts in a specific folder structure. You can package your scripts directly. Use your preferred `zip` utility to create a `.zip` file with your handler file at the root. If your canary script depends on additional packages or modules that aren't included in the Synthetics runtime, you can add these dependencies to your `.zip` file. To do so, you can install your function's required libraries in the `node_modules` directory by running the `npm install` command. The following example CLI commands create a `.zip` file named `my_deployment_package.zip` containing the `index.js` or `index.mjs` file (Synthetics handler) and its dependencies. In the example, you install dependencies using the `npm` package manager.

```
~/my_function
├── index.mjs
├── synthetics.json
├── myhelper-util.mjs    
└── node_modules
    ├── mydependency
```

Create a `.zip` file that contains the contents of your project folder at the root. Use the `r` (recursive) option, as shown in the following example, to ensure that `zip` compresses the subfolders.

```
zip -r my_deployment_package.zip .
```

Add a Synthetics configuration file to configure the behavior of CloudWatch Synthetics. You can create a `synthetics.json` file and save it at the same path as your entry point or handler file.

Optionally, you can also store your entry point file in a folder structure of your choice. However, be sure that the folder path is specified in your handler name.

 **Handler name** 

Be sure to set your canary’s script entry point (handler) as ` myCanaryFilename.functionName` to match the file name of your script’s entry point. You can optionally store the canary in a separate folder such as ` myFolder/my_canary_filename.mjs`. If you store it in a separate folder, specify that path in your script entry point, such as ` myFolder/my_canary_filename.functionName`.

## Changing an existing Playwright script to use as a CloudWatch Synthetics canary
<a name="CloudWatch_Synthetics_canary_edit_Playwright_script"></a>

You can edit an existing script for Node.js and Playwright to be used as a canary. For more information about Playwright, see the [Playwright library](https://playwright.dev/docs/api/class-playwright) documentation. 

You can use the following Playwright script that is saved in file ` exampleCanary.mjs`.

```
import { chromium } from 'playwright';
import { expect } from '@playwright/test';

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com', {timeout: 30000});
await page.screenshot({path: 'example-home.png'});

const title = await page.title();
expect(title).toEqual("Example Domain");
 
await browser.close();
```

Convert the script by performing the following steps:

1. Create and export a `handler` function. The handler is the entry point function for the script. You can choose any name for the handler function, but the function that is used in your script should be the same as in your canary handler. If your script name is `exampleCanary.mjs`, and the handler function name is `myhandler`, your canary handler is named `exampleCanary.myhandler`. In the following example, the handler function name is `handler`.

   ```
   exports.handler = async () => {
     // Your script here
     };
   ```

1. Import the `Synthetics Playwright module` as a dependency.

   ```
   import { synthetics } from '@aws/synthetics-playwright';
   ```

1. Launch a browser using the Synthetics `Launch` function.

   ```
   const browser = await synthetics.launch();
   ```

1. Create a new Playwright page by using the Synthetics `newPage` function.

   ```
   const page = await synthetics.newPage();
   ```

Your script is now ready to be run as a Synthetics canary. The following is the the updated script:

 **Updated script in ES6 format** 

The script file saved with a `.mjs` extension.

```
import { synthetics } from '@aws/synthetics-playwright';
import { expect } from '@playwright/test';

export const handler = async (event, context) => {
  try {
        // Launch a browser
        const browser = await synthetics.launch();
        
        // Create a new page
        const page = await synthetics.newPage(browser);
        
        // Navigate to a website
        await page.goto('https://www.example.com', {timeout: 30000});
        
        // Take screenshot
        await page.screenshot({ path: '/tmp/example.png' });
        
        // Verify the page title
        const title = await page.title();
        expect(title).toEqual("Example Domain");
    } finally {
        // Ensure browser is closed
        await synthetics.close();
    }
};
```

 **Updated script in CommonJS format** 

The script file saved with a `.js` extension.

```
const { synthetics } = require('@aws/synthetics-playwright');
const { expect } = require('@playwright/test');

exports.handler = async (event) => {
  try {
    const browser = await synthetics.launch();
    const page = await synthetics.newPage(browser);
    await page.goto('https://www.example.com', {timeout: 30000});
    await page.screenshot({ path: '/tmp/example.png' });
    const title = await page.title();
    expect(title).toEqual("Example Domain");
  } finally {
    await synthetics.close();
  }
};
```

## CloudWatch Synthetics configurations
<a name="Synthetics_canary_configure_Playwright_script"></a>

You can configure the behavior of the Synthetics Playwright runtime by providing an optional JSON configuration file named `synthetics.json`. This file should be packaged in the same location as the handler file. Though a configuration file is optional, f you don't provide a configuration file, or a configuration key is missing, CloudWatch assumes defaults.

 **Packaging your configuration file** 

The following are supported configuration values, and their defaults.

```
{
    "step": {
        "screenshotOnStepStart": false,
        "screenshotOnStepSuccess": false,
        "screenshotOnStepFailure": false,
        "stepSuccessMetric": true,
        "stepDurationMetric": true,
        "continueOnStepFailure": true,
        "stepsReport": true
    },
    "report": {
        "includeRequestHeaders": true,
        "includeResponseHeaders": true,
        "includeUrlPassword": false,
        "includeRequestBody": true,
        "includeResponseBody": true,
        "restrictedHeaders": ['x-amz-security-token', 'Authorization'], // Value of these headers is redacted from logs and reports
        "restrictedUrlParameters": ['Session', 'SigninToken'] // Values of these url parameters are redacted from logs and reports
    },
    "logging": {
        "logRequest": false,
        "logResponse": false,
        "logResponseBody": false,
        "logRequestBody": false,
        "logRequestHeaders": false,
        "logResponseHeaders": false
    },
    "httpMetrics": {
        "metric_2xx": true,
        "metric_4xx": true,
        "metric_5xx": true,
        "failedRequestsMetric": true,
        "aggregatedFailedRequestsMetric": true,
        "aggregated2xxMetric": true,
        "aggregated4xxMetric": true,
        "aggregated5xxMetric": true
    },
    "canaryMetrics": {
        "failedCanaryMetric": true,
        "aggregatedFailedCanaryMetric": true
    },
    "userAgent": "",
    "har": true
}
```

 **Step configurations** 
+ `screenshotOnStepStart` – Determines if Synthetics should capture a screenshot before the step starts. The default is `true`. 
+ `screenshotOnStepSuccess` – Determines if Synthetics should capture a screenshot after a step has succeeded. The default is `true`. 
+ `screenshotOnStepFailure` – Determines if Synthetics should capture a screenshot after a step has failed. The default is `true`. 
+ `continueOnStepFailure` – Determines if a script should continue even after a step has failed. The default is `false`. 
+ `stepSuccessMetric` – Determines if a step’s ` SuccessPercent` metric is emitted. The `SuccessPercent` metric for a step is `100` for the canary run if the step succeeds, and `0` if the step fails. The default is `true`. 
+ `stepDurationMetric` – Determines if a step's `Duration` metric is emitted. The `Duration` metric is emitted as a duration, in milliseconds, of the step's run. The default is `true`.

 **Report configurations** 

Includes all reports generated by CloudWatch Synthetics, such as a HAR file and a Synthetics steps report. Sensitive data redaction fields `restrictedHeaders` and `restrictedUrlParameters` also apply to logs generated by Synthetics. 
+ `includeRequestHeaders` – Whether to include request headers in the report. The default is `false`. 
+ `includeResponseHeaders` – Whether to include response headers in the report. The default is `false`.
+ `includeUrlPassword` – Whether to include a password that appears in the URL. By default, passwords that appear in URLs are redacted from logs and reports, to prevent the disclosure of sensitive data. The default is `false` . 
+ `includeRequestBody` – Whether to include the request body in the report. The default is `false`. 
+ `includeResponseBody` – Whether to include the response body in the report. The default is `false`. 
+ `restrictedHeaders` – A list of header values to ignore, if headers are included. This applies to both request and response headers. For example, you can hide your credentials by passing `includeRequestHeaders` as true and `restrictedHeaders` as `['Authorization']`. 
+ `restrictedUrlParameters` – A list of URL path or query parameters to redact. This applies to URLs that appear in logs, reports, and errors. The parameter is case-insensitive. You can pass an asterisk (`*`) as a value to redact all URL path and query parameter values. The default is an empty array. 
+ `har` – Determines if an HTTP archive (HAR) should be generated. The default is `true`.

The following is an example of a report configurations file.

```
"includeRequestHeaders": true,
"includeResponseHeaders": true,
"includeUrlPassword": false,
"includeRequestBody": true,
"includeResponseBody": true,
"restrictedHeaders": ['x-amz-security-token', 'Authorization'], // Value of these headers is redacted from logs and reports
"restrictedUrlParameters": ['Session', 'SigninToken'] // Values of these URL parameters are redacted from logs and reports
```

 **Logging configurations** 

Applies to logs generated by CloudWatch Synthetics. Controls the verbosity of request and response logs.
+ `logRequest` – Whether to log every request in canary logs. For UI canaries, this logs each request sent by the browser. The default is ` false`. 
+ `logResponse` – Whether to log every response in canary logs. For UI canaries, this logs every response received by the browser. The default is ` false`. 
+ `logRequestBody` – Whether to log request bodies along with the requests in canary logs. This configuration applies only if `logRequest` is true. The default is `false`. 
+ `logResponseBody` – Whether to log response bodies along with the requests in canary logs. This configuration applies only if `logResponse` is true. The default is `false`. 
+ `logRequestHeaders` – Whether to log request headers along with the requests in canary logs. This configuration applies only if ` logRequest` is true. The default is `false`. 
+ `logResponseHeaders` – Whether to log response headers along with the responses in canary logs. This configuration applies only if ` logResponse` is true. The default is `false`. 

 **HTTP metric configurations** 

Configurations for metrics related to the count of network requests with different HTTP status codes, emitted by CloudWatch Synthetics for this canary.
+ `metric_2xx` – Whether to emit the `2xx` metric (with the `CanaryName` dimension) for this canary. The default is ` true`. 
+ `metric_4xx` – Whether to emit the `4xx` metric (with the `CanaryName` dimension) for this canary. The default is ` true`. 
+ `metric_5xx` – Whether to emit the `5xx` metric (with the `CanaryName` dimension) for this canary. The default is ` true`. 
+ `failedRequestsMetric` – Whether to emit the ` failedRequests` metric (with the `CanaryName` dimension) for this canary. The default is `true`. 
+ `aggregatedFailedRequestsMetric` – Whether to emit the ` failedRequests` metric (without the `CanaryName` dimension) for this canary. The default is `true`. 
+ `aggregated2xxMetric` – Whether to emit the `2xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`. 
+ `aggregated4xxMetric` – Whether to emit the `4xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`. 
+ `aggregated5xxMetric` – Whether to emit the `5xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`. 

 **Canary metric configurations** 

Configurations for other metrics emitted by CloudWatch Synthetics.
+ `failedCanaryMetric` – Whether to emit the `Failed` metric (with the `CanaryName` dimension) for this canary. The default is ` true`. 
+ `aggregatedFailedCanaryMetric` – Whether to emit the ` Failed` metric (without the `CanaryName` dimension) for this canary. The default is `true`. 

 **Other configurations** 
+ `userAgent` – A string to append to the user agent. The user agent is a string that is included in request header, and identifies your browser to websites you visit when you use the headless browser. CloudWatch Synthetics automatically adds `CloudWatchSynthetics/canary-arn to the user agent`. The specified configuration is appended to the generated user agent. The default user agent value to append is an empty string (`""`).

### CloudWatch Synthetics environment variables
<a name="Synthetics_canary_Nodejs_Playwright_script"></a>

Configure the logging level and format by using environment variables.

 **Log format** 

The CloudWatch Synthetics Playwright runtime creates CloudWatch logs for every canary run. Logs are written in JSON format for convenient querying. Optionally, you can change the log format to `TEXT`.
+ `Environment variable name` – CW\$1SYNTHETICS\$1LOG\$1FORMAT 
+ `Supported values` – JSON, TEXT 
+ `Default` – JSON 

 **Log levels** 

Though enabling `Debug` mode increases verbosity, it can be useful for troubleshooting.
+ `Environment variable name` – CW\$1SYNTHETICS\$1LOG\$1LEVEL
+ `Supported values` – TRACE, DEBUG, INFO, WARN, ERROR, FATAL 
+ `Default` – INFO

# Writing a Node.js canary script using the Puppeteer runtime
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Nodejs_Pup"></a>

**Topics**
+ [Creating a CloudWatch Synthetics canary from scratch](#CloudWatch_Synthetics_Canaries_write_from_scratch)
+ [Packaging your Node.js canary files](#CloudWatch_Synthetics_Canaries_package)
+ [Changing an existing Puppeteer script to use as a Synthetics canary](#CloudWatch_Synthetics_Canaries_modify_puppeteer_script)
+ [Environment variables](#CloudWatch_Synthetics_Environment_Variables)
+ [Integrating your canary with other AWS services](#CloudWatch_Synthetics_Canaries_AWS_integrate)
+ [Forcing your canary to use a static IP address](#CloudWatch_Synthetics_Canaries_staticIP)

## Creating a CloudWatch Synthetics canary from scratch
<a name="CloudWatch_Synthetics_Canaries_write_from_scratch"></a>

Here is an example minimal Synthetics Canary script. This script passes as a successful run, and returns a string. To see what a failing canary looks like, change `let fail = false;` to `let fail = true;`. 

You must define an entry point function for the canary script. To see how files are uploaded to the Amazon S3 location specified as the canary's `ArtifactS3Location`, create these files in the `/tmp` folder. All canary artifacts should be stored in `/tmp`, because it's the only writable directory. Be sure that the screenshot path is set to `/tmp` for any screenshots or other files created by the script. Synthetics automatically uploads files in ` /tmp` to an S3 bucket.

```
/tmp/<name>
```

After the script runs, the pass/fail status and the duration metrics are published to CloudWatch and the files under`/tmp` are uploaded to an S3 bucket.

```
const basicCustomEntryPoint = async function () {

    // Insert your code here

    // Perform multi-step pass/fail check

    // Log decisions made and results to /tmp

    // Be sure to wait for all your code paths to complete 
    // before returning control back to Synthetics.
    // In that way, your canary will not finish and report success
    // before your code has finished executing

    // Throw to fail, return to succeed
    let fail = false;
    if (fail) {
        throw "Failed basicCanary check.";
    }

    return "Successfully completed basicCanary checks.";
};

exports.handler = async () => {
    return await basicCustomEntryPoint();
};
```

Next, we'll expand the script to use Synthetics logging and make a call using the AWS SDK. For demonstration purposes, this script will create an Amazon DynamoDB client and make a call to the DynamoDB listTables API. It logs the response to the request and logs either pass or fail depending on whether the request was successful.

```
const log = require('@aws/synthetics-logger');
const AWS = require('aws-sdk');
// Require any dependencies that your script needs
// Bundle additional files and dependencies into a .zip file with folder structure
// nodejs/node_modules/additional files and folders

const basicCustomEntryPoint = async function () {

    log.info("Starting DynamoDB:listTables canary.");
    
    let dynamodb = new AWS.DynamoDB();
    var params = {};
    let request = await dynamodb.listTables(params);
    try {
        let response = await request.promise();
        log.info("listTables response: " + JSON.stringify(response));
    } catch (err) {
        log.error("listTables error: " + JSON.stringify(err), err.stack);
        throw err;
    }

    return "Successfully completed DynamoDB:listTables canary.";
};

exports.handler = async () => {
    return await basicCustomEntryPoint();
};
```

## Packaging your Node.js canary files
<a name="CloudWatch_Synthetics_Canaries_package"></a>

 **For syn-nodejs-puppeteer-11.0 and above** 

 The older packaging structure (for syn-nodejs-puppeteer-10.0 and below) is still supported in newer versions.

Create a script using one of the following options:
+ .js file (CommonJS syntax)
+ .mjs file (ES modules syntax)

For ES modules, use one of the following options:
+ .js file (CommonJS syntax)
+ .mjs file (ES modules syntax)

The package structure is defined below:
+ Root-level handler file (index.js/index.mjs)
+ Optional configuration file (synthetics.json)
+ Additional dependencies in node\$1modules (if needed)

Packaging structure example:

```
  my_function/
├── index.mjs
├── synthetics.json
├── helper-utils.mjs
└── node_modules/
    └── dependencies
```

To package, follow the steps below:

1. Install dependencies (if any).

   ```
   npm install
   ```

1. Create a .zip package.

   ```
   zip -r my_deployment_package.zip
   ```

 **For syn-nodejs-puppeteer-11.0 and below** 

The following structure is required when using Amazon S3:

```
  nodejs/
└── node_modules/
    └── myCanaryFilename.js
```

 **To add an optional sub-folder support in syn-nodejs-puppeteer-3.4\$1:** 

```
nodejs/
└── node_modules/
    └── myFolder/
        └── myCanaryFilename.js
```

**Note**  
Handler path in configuration must match your file location.

 **Handler name** 

Be sure to set your canary’s script entry point (handler) as ` myCanaryFilename.functionName` to match the file name of your script’s entry point. If you are using a runtime earlier than `syn-nodejs-puppeteer-3.4`, then `functionName` must be `handler`. If you are using ` syn-nodejs-puppeteer-3.4` or later, you can choose any function name as the handler. If you are using `syn-nodejs-puppeteer-3.4` or later, you can also optionally store the canary in a separate folder such as ` nodejs/node_modules/myFolder/my_canary_filename`. If you store it in a separate folder, specify that path in your script entry point, such as ` myFolder/my_canary_filename.functionName`.

## Changing an existing Puppeteer script to use as a Synthetics canary
<a name="CloudWatch_Synthetics_Canaries_modify_puppeteer_script"></a>

This section explains how to take Puppeteer scripts and modify them to run as Synthetics canary scripts. For more information about Puppeteer, see [Puppeteer API v1.14.0](https://github.com/puppeteer/puppeteer/blob/v1.14.0/docs/api.md). 

We'll start with this example Puppeteer script:

```
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();
```

The conversion steps are as follows:
+ Create and export a `handler` function. The handler is the entry point function for the script. If you are using a runtime earlier than ` syn-nodejs-puppeteer-3.4`, the handler function must be named `handler`. If you are using `syn-nodejs-puppeteer-3.4` or later, the function can have any name, but it must be the same name that is used in the script. Also, if you are using `syn-nodejs-puppeteer-3.4` or later, you can store your scripts under any folder and specify that folder as part of the handler name.

  ```
  const basicPuppeteerExample = async function () {};
  
  exports.handler = async () => {
      return await basicPuppeteerExample();
  };
  ```
+ Use the `Synthetics` dependency.

  ```
  var synthetics = require('@aws/synthetics-puppeteer');
  ```
+ Use the `Synthetics.getPage` function to get a Puppeteer `Page` object.

  ```
  const page = await synthetics.getPage();
  ```

  The page object returned by the Synthetics.getPage function has the ** page.on** `request`, `response` and ` requestfailed` events instrumented for logging. Synthetics also sets up HAR file generation for requests and responses on the page, and adds the canary ARN to the user-agent headers of outgoing requests on the page.

The script is now ready to be run as a Synthetics canary. Here is the updated script:

```
var synthetics = require('@aws/synthetics-puppeteer');  // Synthetics dependency

const basicPuppeteerExample = async function () {
    const page = await synthetics.getPage(); // Get instrumented page from Synthetics
    await page.goto('https://example.com');
    await page.screenshot({path: '/tmp/example.png'}); // Write screenshot to /tmp folder
};

exports.handler = async () => {  // Exported handler function 
    return await basicPuppeteerExample();
};
```

## Environment variables
<a name="CloudWatch_Synthetics_Environment_Variables"></a>

You can use environment variables when creating canaries. This allows you to write a single canary script and then use that script with different values to quickly create multiple canaries that have a similar task.

For example, suppose your organization has endpoints such as `prod`, ` dev`, and `pre-release` for the different stages of your software development, and you need to create canaries to test each of these endpoints. You can write a single canary script that tests your software and then specify different values for the endpoint environment variable when you create each of the three canaries. Then, when you create a canary, you specify the script and the values to use for the environment variables.

The names of environment variables can contain letters, numbers, and the underscore character. They must start with a letter and be at least two characters. The total size of your environment variables can't exceed 4 KB. You can't specify any Lambda reserved environment variables as the names of your environment variables. For more information about reserved environment variables, see [ Runtime environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime).

**Important**  
Environment variable keys and values are encrypted at rest using AWS owned AWS KMS keys. However, the environment variables are not encrypted on the client side. Do not store sensitive information in them.

The following example script uses two environment variables. This script is for a canary that checks whether a webpage is available. It uses environment variables to parameterize both the URL that it checks and the CloudWatch Synthetics log level that it uses. 

The following function sets `LogLevel` to the value of the ` LOG_LEVEL` environment variable.

```
 synthetics.setLogLevel(process.env.LOG_LEVEL);
```

This function sets `URL` to the value of the `URL` environment variable.

```
const URL = process.env.URL;
```

This is the complete script. When you create a canary using this script, you specify values for the `LOG_LEVEL` and `URL` environment variables.

```
var synthetics = require('@aws/synthetics-puppeteer');
const log = require('@aws/synthetics-logger');

const pageLoadEnvironmentVariable = async function () {

    // Setting the log level (0-3)
    synthetics.setLogLevel(process.env.LOG_LEVEL);
    // INSERT URL here
    const URL = process.env.URL;

    let page = await synthetics.getPage();
    //You can customize the wait condition here. For instance,
    //using 'networkidle2' may be less restrictive.
    const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000});
    if (!response) {
        throw "Failed to load page!";
    }
    //Wait for page to render.
    //Increase or decrease wait time based on endpoint being monitored.
    await page.waitFor(15000);
    await synthetics.takeScreenshot('loaded', 'loaded');
    let pageTitle = await page.title();
    log.info('Page title: ' + pageTitle);
    log.debug('Environment variable:' + process.env.URL);

    //If the response status code is not a 2xx success code
    if (response.status() < 200 || response.status() > 299) {
        throw "Failed to load page!";
    }
};

exports.handler = async () => {
    return await pageLoadEnvironmentVariable();
};
```

### Passing environment variables to your script
<a name="CloudWatch_Synthetics_Canaries_pass_variables"></a>

To pass environment variables to your script when you create a canary in the console, specify the keys and values of the environment variables in the **Environment variables** section on the console. For more information, see [Creating a canary](CloudWatch_Synthetics_Canaries_Create.md).

To pass environment variables through the API or AWS CLI, use the ` EnvironmentVariables` parameter in the `RunConfig` section. The following is an example AWS CLI command that creates a canary that uses two environment variables with keys of `Environment` and `Region`.

```
aws synthetics create-canary --cli-input-json '{
   "Name":"nameofCanary",
   "ExecutionRoleArn":"roleArn",
   "ArtifactS3Location":"s3://amzn-s3-demo-bucket-123456789012-us-west-2",
   "Schedule":{
      "Expression":"rate(0 minute)",
      "DurationInSeconds":604800
   },
   "Code":{
      "S3Bucket": "canarycreation",
      "S3Key": "cwsyn-mycanaryheartbeat-12345678-d1bd-1234-abcd-123456789012-12345678-6a1f-47c3-b291-123456789012.zip",
      "Handler":"pageLoadBlueprint.handler"
   },
   "RunConfig": {
      "TimeoutInSeconds":60,
      "EnvironmentVariables": {
         "Environment":"Production",
         "Region": "us-west-1"
      }
   },
   "SuccessRetentionPeriodInDays":13,
   "FailureRetentionPeriodInDays":13,
   "RuntimeVersion":"syn-nodejs-2.0"
}'
```

## Integrating your canary with other AWS services
<a name="CloudWatch_Synthetics_Canaries_AWS_integrate"></a>

All canaries can use the AWS SDK library. You can use this library when you write your canary to integrate the canary with other AWS services.

To do so, you need to add the following code to your canary. For these examples, AWS Secrets Manager is used as the service that the canary is integrating with.
+ Import the AWS SDK.

  ```
  const AWS = require('aws-sdk');
  ```
+ Create a client for the AWS service that you are integrating with.

  ```
  const secretsManager = new AWS.SecretsManager();
  ```
+ Use the client to make API calls to that service.

  ```
  var params = {
    SecretId: secretName
  };
  return await secretsManager.getSecretValue(params).promise();
  ```

The following canary script code snippet demonstrates an example of integration with Secrets Manager in more detail.

```
var synthetics = require('@aws/synthetics-puppeteer');
const log = require('@aws/synthetics-logger');
 
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
 
const getSecrets = async (secretName) => {
    var params = {
        SecretId: secretName
    };
    return await secretsManager.getSecretValue(params).promise();
}
 
const secretsExample = async function () {
    let URL = "<URL>";
    let page = await synthetics.getPage();
    
    log.info(`Navigating to URL: ${URL}`);
    const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000});
    
    // Fetch secrets
    let secrets = await getSecrets("secretname")
   
    /**
    * Use secrets to login. 
    *
    * Assuming secrets are stored in a JSON format like:
    * {
    *   "username": "<USERNAME>",
    *   "password": "<PASSWORD>"
    * }
    **/
    let secretsObj = JSON.parse(secrets.SecretString);
    await synthetics.executeStep('login', async function () {
        await page.type(">USERNAME-INPUT-SELECTOR<", secretsObj.username);
        await page.type(">PASSWORD-INPUT-SELECTOR<", secretsObj.password);
        
        await Promise.all([
          page.waitForNavigation({ timeout: 30000 }),
          await page.click(">SUBMIT-BUTTON-SELECTOR<")
        ]);
    });
   
    // Verify login was successful
    await synthetics.executeStep('verify', async function () {
        await page.waitForXPath(">SELECTOR<", { timeout: 30000 });
    });
};

exports.handler = async () => {
    return await secretsExample();
};
```

## Forcing your canary to use a static IP address
<a name="CloudWatch_Synthetics_Canaries_staticIP"></a>

You can set up a canary so that it uses a static IP address.

**To force a canary to use a static IP address**

1. Create a new VPC. For more information, see [Using DNS with Your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html).

1. Create a new internet gateway. For more information, see [Adding an internet gateway to your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#working-with-igw).

1. Create a public subnet inside your new VPC.

1. Add a new route table to the VPC.

1. Add a route in the new route table, that goes from `0.0.0.0/0` to the internet gateway.

1. Associate the new route table with the public subnet.

1. Create an elastic IP address. For more information, see [Elastic IP addresses ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html).

1. Create a new NAT gateway and assign it to the public subnet and the elastic IP address.

1. Create a private subnet inside the VPC.

1. Add a route to the VPC default route table, that goes from `0.0.0.0/0` to the NAT gateway

1. Create your canary. 

# Writing a Python canary script
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python"></a>

This script passes as a successful run, and returns a string. To see what a failing canary looks like, change fail = False to fail = True

```
def basic_custom_script():
    # Insert your code here
    # Perform multi-step pass/fail check
    # Log decisions made and results to /tmp
    # Be sure to wait for all your code paths to complete 
    # before returning control back to Synthetics.
    # In that way, your canary will not finish and report success
    # before your code has finished executing
    fail = False
    if fail:
        raise Exception("Failed basicCanary check.")
    return "Successfully completed basicCanary checks."
def handler(event, context):
    return basic_custom_script()
```

## Packaging your Python canary files
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python_package"></a>

If you have more than one .py file or your script has a dependency, you can bundle them all into a single ZIP file. If you use the `syn-python-selenium-1.1` runtime, the ZIP file must contain your main canary .py file within a `python` folder, such as `python/my_canary_filename.py`. If you use ` syn-python-selenium-1.1` or later, you can optionally use a different folder , such as `python/myFolder/my_canary_filename.py`.

This ZIP file should contain all necessary folders and files, but the other files do not need to be in the `python` folder.

Be sure to set your canary’s script entry point as ` my_canary_filename.functionName` to match the file name and function name of your script’s entry point. If you are using the `syn-python-selenium-1.0` runtime, then `functionName` must be `handler`. If you are using ` syn-python-selenium-1.1` or later, this handler name restriction doesn't apply, and you can also optionally store the canary in a separate folder such as ` python/myFolder/my_canary_filename.py`. If you store it in a separate folder, specify that path in your script entry point, such as ` myFolder/my_canary_filename.functionName`. 

## Changing an existing Selenium script to use a Synthetics canary
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python_Selenium"></a>

You can quickly modify an existing script for Python and Selenium to be used as a canary. For more information about Selenium, see [ www.selenium.dev/](https://www.selenium.dev/).

For this example, we'll start with the following Selenium script:

```
from selenium import webdriver

def basic_selenium_script():
    browser = webdriver.Chrome()
    browser.get('https://example.com')
    browser.save_screenshot('loaded.png')

basic_selenium_script()
```

The conversion steps are as follows.

**To convert a Selenium script to be used as a canary**

1. Change the `import` statement to use Selenium from the ` aws_synthetics` module:

   ```
   from aws_synthetics.selenium import synthetics_webdriver as webdriver
   ```

   The Selenium module from `aws_synthetics` ensures that the canary can emit metrics and logs, generate a HAR file, and work with other CloudWatch Synthetics features.

1. Create a handler function and call your Selenium method. The handler is the entry point function for the script.

   If you are using `syn-python-selenium-1.0`, the handler function must be named `handler`. If you are using `syn-python-selenium-1.1` or later, the function can have any name, but it must be the same name that is used in the script. Also, if you are using `syn-python-selenium-1.1` or later, you can store your scripts under any folder and specify that folder as part of the handler name.

   ```
   def handler(event, context):
       basic_selenium_script()
   ```

The script is now updated to be a CloudWatch Synthetics canary. Here is the updated script:

The `webdriver` is an instance of the class [ SyntheticsWebDriver](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library_Python.html#CloudWatch_Synthetics_Library_Python_SyntheticsWebDriver) and the browser returned by `webdriver.Chrome()` is an instance of [ SyntheticsBrowser](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library_Python.html#CloudWatch_Synthetics_Library_Python_SyntheticsBrowser).

```
from aws_synthetics.selenium import synthetics_webdriver as webdriver

def basic_selenium_script():
    browser = webdriver.Chrome()
    browser.get('https://example.com')
    browser.save_screenshot('loaded.png')

def handler(event, context):
    basic_selenium_script()
```

## Changing an existing Puppeteer Synthetics script to authenticate non-standard certificates
<a name="Canaries_Non-Standard_Certificates"></a>

One important use case for Synthetics canaries is for you to monitor your own endpoints. If you want to monitor an endpoint that isn't ready for external traffic, this monitoring can sometimes mean that you don't have a proper certificate signed by a trusted third-party certificate authority.

Two possible solutions to this scenario are as follows:
+ To authenticate a client certificate, see [ How to validate authentication using Amazon CloudWatch Synthetics – Part 2](https://aws.amazon.com/blogs/mt/how-to-validate-authentication-using-amazon-cloudwatch-synthetics-part-2/).
+ To authenticate a self-signed certificate, see [ How to validate authentication with self-signed certificates in Amazon CloudWatch Synthetics](https://aws.amazon.com/blogs/mt/how-to-validate-authentication-with-self-signed-certificates-in-amazon-cloudwatch-synthetics/)

You are not limited to these two options when you use CloudWatch Synthetics canaries. You can extend these features and add your business logic by extending the canary code.

**Note**  
Synthetics canaries running on Python runtimes innately have the ` --ignore-certificate-errors` flag enabled, so those canaries shouldn't have any issues reaching sites with non-standard certificate configurations.

# Writing a JSON configuration for Node.js multi Checks blueprint
<a name="CloudWatch_Synthetics_WritingCanary_Multichecks"></a>

The Node.js multi checks blueprint allows you to create canaries that perform multiple validation checks within a single canary run. This blueprint is useful when you want to test multiple endpoints, validate different aspects of your application, or perform a series of related checks in sequence. 

**Topics**
+ [Root configuration structure](#root-configuration-structure)
+ [Global settings](#global-settings)
+ [Variables and data management](#variables-data-management)
+ [Step definitions](#step-definitions)
+ [Check types](#check-types)
+ [Authentication methods](#authentication-methods)
+ [Assertions and validation](#assertions-validation)
+ [Data extraction](#data-extraction)

## Root configuration structure
<a name="root-configuration-structure"></a>

The root configuration defines the overall structure of your advanced API blueprint canary.


**Schema properties**  

| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  globalSettings  | Object | No | Default configurations applied to all steps | 
|  variables  | Object | No | Reusable values across steps (max 10) | 
|  steps  | Object |  Yes  | Collection of monitoring steps (1-10 steps) | 

 **Example** 

```
{
  "globalSettings": {
    "stepTimeout": 30000,
    "userAgent": "CloudWatch-Synthetics-Advanced/1.0"
  },
  "variables": {
    "baseUrl": "https://api.example.com",
    "apiVersion": "v1"
  },
  "steps": {
    "1": {
      "stepName": "healthCheck",
      "checkerType": "HTTP",
      "url": "${baseUrl}/health",
      "httpMethod": "GET"
    }
  }
}
```

 **Validation rules** 
+ Must contain at least one step
+ Maximum 10 steps allowed
+ No additional properties allowed beyond `globalSettings`, ` variables`, and `steps`

## Global settings
<a name="global-settings"></a>

Global settings provide default configurations that apply to all steps unless overridden at the step level.

 **Properties** 


**Global setting properties**  

| Property | Type | Default | Range | Description | 
| --- | --- | --- | --- | --- | 
|  stepTimeout  | integer | 30000 | 5000-300000 | Default timeout for all steps (milliseconds) | 

 **Example** 

```
{
  "globalSettings": {
    "stepTimeout": 60000,
            
  }
}
```

## Variables and data management
<a name="variables-data-management"></a>

Variables allow you to define reusable values that can be referenced throughout your configuration using `${variableName}` syntax.

 **Variable properties** 


| Property | Type | Description | 
| --- | --- | --- | 
| Variable names | string | Must match pattern ^[a-zA-Z][a-zA-Z0-9\$1]\$1\$1 | 
| Variable values | string | Any string value | 

 **Limitations** 
+ Maximum 10 variables per configuration
+ Variable names must start with a letter
+ Variable names can contain letters, numbers, and underscores only
+ Maximum length not specified in schema

 **Example** 

```
{
  "variables": {
    "baseUrl": "https://api.example.com",
    "apiKey": "${AWS_SECRET:my-api-key}",
    "timeout": "30000",
    "userEmail": "test@example.com"
  }
}
```

 **Configuration usage** 

```
{
  "steps": {
    "1": {
      "url": "${baseUrl}/users",
      "timeout": "${timeout}",
      "headers": {
        "Authorization": "Bearer ${apiKey}"
      }
    }
  }
}
```

## Step definitions
<a name="step-definitions"></a>

Steps define individual monitoring operations. Each step is numbered from 1 to 10 and contains a specific type of check.

 *Common step properties* 


| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  stepName  | string |  Yes  | Unique identifier for the step | 
|  checkerType  | string |  Yes  | Type of check: HTTP, DNS, SSL,  TCP | 
|  extractors  | array | No | Data extraction configuration | 

 *Step name validation* 
+ Pattern - ^[a-zA-Z][a-zA-Z0-9\$1-]\$1\$1
+ Maximum length - 64 characters
+ Must start with a letter

 *Step numbering* 
+ Steps are numbered as string keys: "1", "2", ..., "10"
+ Pattern: ^([1-9]\$110)\$1
+ Minimum 1 step required
+ Maximum 10 steps allowed

 *Example* 

```
{
  "steps": {
    "1": {
      "stepName": "loginAPI",
      "checkerType": "HTTP",
      "url": "https://api.example.com/login",
      "httpMethod": "POST"
    },
    "2": {
      "stepName": "dnsCheck",
      "checkerType": "DNS",
      "domain": "example.com"
    }
  }
}
```

## Check types
<a name="check-types"></a>

### HTTP checks
<a name="http-types"></a>

Monitor web endpoints and APIs with comprehensive request and response validation.

 **Required properties** 


| Property | Type | Description | 
| --- | --- | --- | 
|  url  | string | Target URL (must be valid URI format) | 
|  httpMethod  | string | HTTP method: GET, POST, PUT,  PATCH, DELETE, HEAD, OPTIONS | 

 **Optional properties** 


| Property | Type | Default | Range | Description | 
| --- | --- | --- | --- | --- | 
|  timeout  | integer | 30000 | 5000-300000 | Request timeout (milliseconds) | 
|  waitTime  | integer | 0 | 0-60 | Delay before request (seconds) | 
|  headers  | object | - | - | Custom HTTP headers | 
|  body  | string | - | - | Request body for POST/PUT operations | 
|  authentication  | object | - | - | Authentication configuration | 
|  assertions  | array | - | - | Response validation rules | 

 **Example** 

```
{
  "stepName": "createUser",
  "checkerType": "HTTP",
  "url": "https://api.example.com/users",
  "httpMethod": "POST",
  "timeout": 15000,
  "headers": {
    "Content-Type": "application/json",
    "X-API-Version": "v1"
  },
  "body": "{\"name\":\"John Doe\",\"email\":\"john@example.com\"}",
  "authentication": {
    "type": "API_KEY",
    "apiKey": "${AWS_SECRET:api-credentials}",
    "headerName": "X-API-Key"
  },
  "assertions": [
    {
      "type": "STATUS_CODE",
      "operator": "EQUALS",
      "value": 201
    }
  ]
}
```

### DNS checks
<a name="dns-types"></a>

Validate DNS resolution and record information.

 **Required properties** 


| Property | Type | Description | 
| --- | --- | --- | 
|  domain  | string | Domain name to query (hostname format) | 

 **Optional properties** 


| Property | Type | Default | Description | 
| --- | --- | --- | --- | 
|  recordType  | string | "A" | DNS record type: A, CNAME, MX,  TXT, NS | 
|  nameserver  | string | - | Specific DNS server to query | 
|  timeout  | integer | 30000 | Query timeout (5000-300000ms) | 
|  port  | integer | 53 | DNS server port (1-65535) | 
|  protocol  | string | "UDP" | Protocol: UDP or TCP | 
|  assertions  | array | - | DNS response validation rules | 

 **Example** 

```
{
  "stepName": "dnsResolution",
  "checkerType": "DNS",
  "domain": "example.com",
  "recordType": "A",
  "nameserver": "8.8.8.8",
  "timeout": 10000,
  "assertions": [
    {
      "type": "RECORD_VALUE",
      "operator": "CONTAINS",
      "value": "192.168"
    }
  ]
}
```

### SSL checks
<a name="ssl-types"></a>

Monitor SSL certificate health and configuration.

 **Required properties** 


| Property | Type | Description | 
| --- | --- | --- | 
|  hostname  | string | Target hostname (hostname format) | 

 **Optional properties** 


| Property | Type | Default | Description | 
| --- | --- | --- | --- | 
|  port  | integer | 443 | SSL port (1-65535) | 
|  timeout  | integer | 30000 | Connection timeout (5000-300000ms) | 
|  sni  | boolean | TRUE | Server Name Indication | 
|  verifyHostname  | boolean | TRUE | Hostname verification | 
|  allowSelfSigned  | boolean | FALSE | Accept self-signed certificates | 
|  assertions  | array | - | Certificate validation rules | 

 **Example** 

```
{
  "stepName": "sslCertCheck",
  "checkerType": "SSL",
  "hostname": "secure.example.com",
  "port": 443,
  "sni": true,
  "verifyHostname": true,
  "assertions": [
    {
      "type": "CERTIFICATE_EXPIRY",
      "operator": "GREATER_THAN",
      "value": 30,
      "unit": "DAYS"
    }
  ]
}
```

### TCP checks
<a name="tcp-types"></a>

Test TCP port connectivity and response validation.

 **Required properties** 


| Property | Type | Description | 
| --- | --- | --- | 
|  hostname  | string | Target hostname (hostname format) | 
|  port  | integer | Target port (1-65535) | 

 **Optional properties** 


| Property | Type | Default | Description | 
| --- | --- | --- | --- | 
|  timeout  | integer | 30000 | Overall timeout (5000-300000ms) | 
|  connectionTimeout  | integer | 3000 | Connection timeout (5000-300000ms) | 
|  readTimeout  | integer | 2000 | Data read timeout (5000-300000ms) | 
|  sendData  | string | - | Data to send after connection | 
|  expectedResponse  | string | - | Expected response data | 
|  encoding  | string | "UTF-8" | Data encoding: UTF-8, ASCII, HEX | 
|  assertions  | array | - | Connection and response validation | 

 **Example** 

```
{
  "stepName": "databaseConnection",
  "checkerType": "TCP",
  "hostname": "db.example.com",
  "port": 3306,
  "connectionTimeout": 5000,
  "sendData": "SELECT 1",
  "expectedResponse": "1",
  "assertions": [
    {
      "type": "CONNECTION_SUCCESSFUL",
      "value": true
    }
  ]
}
```

## Authentication methods
<a name="authentication-methods"></a>

 **No authentication** 

```
{
  "type": "NONE"
}
```

 **Basic authentication** 


| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  type  | string |  Yes  | Must be "BASIC" | 
|  username  | string |  Yes  | Username for authentication | 
|  password  | string |  Yes  | Password for authentication | 

 **Example** 

```
{
  "type": "BASIC",
  "username": "admin",
  "password": "${AWS_SECRET:basic-auth:password}"
}
```

 **API key authentication** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "API\$1KEY" | 
|  apiKey  | string |  Yes  | - | API key value | 
|  headerName  | string | No | "X-API-Key" | Header name for API key | 

 **Example** 

```
{
  "type": "API_KEY",
  "apiKey": "${AWS_SECRET:api-credentials}",
  "headerName": "Authorization"
}
```

 **OAuth client credentials** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "OAUTH\$1CLIENT\$1CREDENTIALS" | 
|  tokenUrl  | string |  Yes  | - | OAuth token endpoint URL | 
|  clientId  | string |  Yes  | - | OAuth client ID | 
|  clientSecret  | string |  Yes  | - | OAuth client secret | 
|  scope  | string | No | - | OAuth scope | 
|  audience  | string | No | - | OAuth audience | 
|  resource  | string | No | - | OAuth resource | 
|  tokenApiAuth  | array | No | - | Token API auth methods: BASIC\$1AUTH\$1HEADER, REQUEST\$1BODY | 
|  tokenCacheTtl  | integer | No | 3600 | Token cache TTL (minimum 60 seconds) | 

 **Example** 

```
{
  "type": "OAUTH_CLIENT_CREDENTIALS",
  "tokenUrl": "https://auth.example.com/oauth/token",
  "clientId": "${AWS_SECRET:oauth-creds:client_id}",
  "clientSecret": "${AWS_SECRET:oauth-creds:client_secret}",
  "scope": "read write",
  "tokenCacheTtl": 7200
}
```

 **AWS Signature (Version 4)** 


| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  type  | string |  Yes  | Must be "SIGV4" | 
|  service  | string |  Yes  | Name of the AWS service (for example, "execute-api") | 
|  region  | string |  Yes  | AWS region | 
|  roleArn  | string |  Yes  | IAM role ARN for signing | 

 **Example** 

```
{
  "type": "SIGV4",
  "service": "execute-api",
  "region": "us-east-1",
  "roleArn": "arn:aws:iam::123456789012:role/SyntheticsRole"
}
```

## Assertions and validation
<a name="assertions-validation"></a>

### HTTP assertions
<a name="http-assertions"></a>

 **Status code assertions** 


| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  type  | string |  Yes  | Must be "STATUS\$1CODE" | 
|  operator  | string |  Yes  | EQUALS, NOT\$1EQUALS, GREATER\$1THAN,  LESS\$1THAN, IN\$1RANGE | 
|  value  | integer | Conditional | HTTP status code (100-599) | 
|  rangeMin  | integer | Conditional | Minimum range value (for IN\$1RANGE) | 
|  rangeMax  | integer | Conditional | Maximum range value (for IN\$1RANGE) | 

```
{
  "type": "STATUS_CODE",
  "operator": "EQUALS",
  "value": 200
}
```

 **Response time assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "RESPONSE\$1TIME" | 
|  operator  | string |  Yes  | - | LESS\$1THAN, GREATER\$1THAN, EQUALS | 
|  value  | number |  Yes  | - | Time value (minimum 0) | 
|  unit  | string | No | "MILLISECONDS" | Must be "MILLISECONDS" | 

```
{
  "type": "RESPONSE_TIME",
  "operator": "LESS_THAN",
  "value": 500,
  "unit": "MILLISECONDS"
}
```

 **Head assertions** 


| Property | Type | Required | Description | 
| --- | --- | --- | --- | 
|  type  | string |  Yes  | Must be "HEADER" | 
|  headerName  | string |  Yes  | Name of header to validate | 
|  operator  | string |  Yes  | EQUALS, NOT\$1EQUALS, CONTAINS,  NOT\$1CONTAINS, REGEX\$1MATCH, EXIST | 
|  value  | string/boolean | Conditional | Expected value (boolean for EXIST operator) | 

```
{
  "type": "HEADER",
  "headerName": "Content-Type",
  "operator": "CONTAINS",
  "value": "application/json"
}
```

 **Body assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "BODY" | 
|  target  | string | No | "JSON" | JSON or TEXT | 
|  path  | string | Conditional | - | JSONPath (required for JSON target) | 
|  operator  | string |  Yes  | - | CONTAINS, NOT\$1CONTAINS, EQUALS,  NOT\$1EQUALS, EXISTS | 
|  value  | string/boolean |  Yes  | - | Expected value (boolean for EXISTS operator) | 

```
{
  "type": "BODY",
  "target": "JSON",
  "path": "$.users[0].name",
  "operator": "EQUALS",
  "value": "John Doe"
}
```

### DNS assertions
<a name="dns-assertions"></a>

 **Record value assertions** 


| Property | Type | Required | Range | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "RECORD\$1VALUE" | 
|  operator  | string |  Yes  | - | EQUALS, NOT\$1EQUALS, CONTAINS,  NOT\$1CONTAINS, REGEX\$1MATCH | 
|  value  | string |  Yes  | - | Expected record value | 

 **Record count assertions** 


| Property | Type | Required | Range | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "RECORD\$1COUNT" | 
|  operator  | string |  Yes  | - | EQUALS, GREATER\$1THAN, LESS\$1THAN | 
|  value  | integer |  Yes  | ≥ 0 | Expected count (minimum 0) | 

 **Authoritative assertions** 


| Property | Type | Required | Range | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "AUTHORITATIVE" | 
|  value  | boolean |  Yes  | - | Expected authoritative status | 

 **TTL assertions** 


| Property | Type | Required | Range | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "TTL" | 
|  operator  | string |  Yes  | - | EQUALS, GREATER\$1THAN, LESS\$1THAN | 
|  value  | integer |  Yes  | ≥ 0 | Expected TTL (minimum 0) | 

### SSL assertions
<a name="ssl-assertions"></a>

 **Certificate expiry assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "CERTIFICATE\$1EXPIRY" | 
|  operator  | string |  Yes  | - | GREATER\$1THAN, LESS\$1THAN | 
|  value  | integer |  Yes  | - | Time value (minimum 0) | 
|  unit  | string | No | "DAYS" | DAYS, HOURS | 

 **Certificate subject assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "CERTIFICATE\$1SUBJECT" | 
|  field  | string |  Yes  | - | Subject field: CN, O, OU, C , ST, L | 
|  operator  | string |  Yes  | - | CONTAINS, EQUALS, REGEX\$1MATCH | 
|  value  | string |  Yes  | - | Expected field value | 

 **Certificate issuer assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "CERTIFICATE\$1ISSUER" | 
|  field  | string |  Yes  | - | Issuer field: CN, O | 
|  operator  | string |  Yes  | - | CONTAINS, EQUALS | 
|  value  | string |  Yes  | - | Expected field value | 

### TCP assertions
<a name="tcp-assertions"></a>

 **Connection success assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "CONNECTION\$1SUCCESSFUL" | 
|  value  | boolean |  Yes  | - | Expected connection status | 

 **Response data assertions** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Yes  | - | Must be "RESPONSE\$1DATA" | 
|  operator  | string |  Yes  | - | CONTAINS, EQUALS, NOT\$1CONTAINS,  REGEX\$1MATCH, STARTS\$1WITH, ENDS\$1WITH | 
|  value  | string |  Yes  | - | Expected response data | 
|  encoding  | string | No | "UTF-8" | UTF-8, ASCII, HEX | 

## Data extraction
<a name="data-extraction"></a>

Extractors allows you to capture data from responses for use in subsequent steps or for reporting purposes.

 **Extraction properties** 


| Property | Type | Required | Default | Description | 
| --- | --- | --- | --- | --- | 
|  name  | string |  Yes  | - | Variable name for extracted data | 
|  type  | string |  Yes  | - | Extraction type: BODY | 
|  path  | string | No | - | JSONPath for body extraction | 
|  regex  | string | No | - | Regular expression pattern | 
|  regexGroup  | integer | No | 0 | Regex capture group (minimum 0) | 

 **Extraction name validation** 
+ Pattern: `^[a-zA-Z][a-zA-Z0-9_]*$`
+ Must start with a letter
+ Can contain letters, numbers, and underscores

**Limitation** – Substitution does not apply for fields in the schema that have specific ENUM values

 **Extraction types** 

```
{
  "name": "userId",
  "type": "BODY",
  "path": "$.user.id"
}
```

```
{
  "stepName": "loginAndExtract",
  "checkerType": "HTTP",
  "url": "https://api.example.com/login",
  "httpMethod": "POST",
  "body": "{\"username\":\"test\",\"password\":\"pass\"}",
  "extractors": [
    {
      "name": "textVariable",
      "type": "BODY",
      "path": "$.myvalue"
    }
  ]
},
{
  "stepName": "substituteVariable",
  "checkerType": "HTTP",
  "url": "https://api.example.com/get/${textVariable}",
  "httpMethod": "GET",
  "assertions": [
    {
    "type": "BODY",
    "target": "JSON",
    "path": "$.users[0].name",
    "operator": "EQUALS",
    "value": "${textVariable}"
    }
  ]
}
```

# Library functions available for canary scripts
<a name="CloudWatch_Synthetics_Canaries_Function_Library"></a>

CloudWatch Synthetics includes several built-in classes and functions that you can call when writing Node.js scripts to use as canaries.

Some apply to both UI and API canaries. Others apply to UI canaries only. A UI canary is a canary that uses the `getPage()` function and uses Puppeteer as a web driver to navigate and interact with webpages.

**Note**  
Whenever you upgrade a canary to use a new version of the the Synthetics runtime, all Synthetics library functions that your canary uses are also automatically upgraded to the same version of NodeJS that the Synthetics runtime supports.

**Topics**
+ [Library functions available for Node.js canary](Library_function_Nodejs.md)
+ [Library functions available for Java canary](CloudWatch_Synthetics_Canaries_Java.md)
+ [Library functions available for Node.js canary scripts using Playwright](CloudWatch_Synthetics_Canaries_Nodejs_Playwright.md)
+ [Library functions available for Node.js canary scripts using Puppeteer](CloudWatch_Synthetics_Canaries_Library_Nodejs.md)
+ [Library functions available for Python canary scripts using Selenium](CloudWatch_Synthetics_Canaries_Library_Python.md)

# Library functions available for Node.js canary
<a name="Library_function_Nodejs"></a>

This section describes the library functions that are available for canary scripts using the Node.js runtime.

**Topics**
+ [addExecutionError(errorMessage, ex);](#Library_function_Nodejs_addExecutionError_Nodecanary)
+ [getCanaryName();](#Library_function_Nodejs_getCanaryName)
+ [getCanaryArn();](#Library_function_Nodejs_Nodecanary)
+ [getCanaryUserAgentString();](#Library_function_Nodejs_getCanaryUserAgentString_Nodecanary)
+ [getRuntimeVersion();](#Library_function_Nodejs_getRuntimeVersion_Nodecanary)
+ [getLogLevel();](#Library_function_Nodejs_getLogLevel_Nodecanary)
+ [setLogLevel();](#Library_function_Nodejs_setLogLevel_Nodecanary)
+ [executeStep(stepName, functionToExecute, [stepConfig])](#Library_function_Nodejs_executestep_Nodecanary)
+ [executeHttpStep(stepName, requestOptions, [callback], [stepConfig])](#Library_function_Nodejs_executeHttpStep)

## addExecutionError(errorMessage, ex);
<a name="Library_function_Nodejs_addExecutionError_Nodecanary"></a>

`errorMessage` describes the error and `ex` is the exception that is encountered

You can use `addExecutionError` to set execution errors for your canary. It fails the canary without interrupting the script execution. It also doesn't impact your `successPercent` metrics.

You should track errors as execution errors only if they are not important to indicate the success or failure of your canary script.

An example of the use of `addExecutionError` is the following. You are monitoring the availability of your endpoint and taking screenshots after the page has loaded. Because the failure of taking a screenshot doesn't determine availability of the endpoint, you can catch any errors encountered while taking screenshots and add them as execution errors. Your availability metrics will still indicate that the endpoint is up and running, but your canary status will be marked as failed. The following sample code block catches such an error and adds it as an execution error.

```
try {await synthetics.executeStep(stepName, callbackFunc);} catch(ex) {synthetics.addExecutionError('Unable to take screenshot ', ex);}
```

## getCanaryName();
<a name="Library_function_Nodejs_getCanaryName"></a>

Returns the name of the canary.

## getCanaryArn();
<a name="Library_function_Nodejs_Nodecanary"></a>

Returns the ARN of the canary.

## getCanaryUserAgentString();
<a name="Library_function_Nodejs_getCanaryUserAgentString_Nodecanary"></a>

Returns the custom user agent of the canary.

## getRuntimeVersion();
<a name="Library_function_Nodejs_getRuntimeVersion_Nodecanary"></a>

This function is available on runtime version `syn-nodejs-3.0` and later. It returns the Synthetics runtime version of the canary. For example, the return value could be `syn-nodejs-3.0`.

## getLogLevel();
<a name="Library_function_Nodejs_getLogLevel_Nodecanary"></a>

Retrieves the current log level for the Synthetics library. Possible values are the following:
+ `0` – Debug
+ `1` – Info
+ `2` – Warn
+ `3` – Error

Example:

```
let logLevel = synthetics.getLogLevel();
```

## setLogLevel();
<a name="Library_function_Nodejs_setLogLevel_Nodecanary"></a>

Sets the log level for the Synthetics library. Possible values are the following:
+ `0` – Debug
+ `1` – Info
+ `2` – Warn
+ `3` – Error

Example:

```
synthetics.setLogLevel(0);
```

## executeStep(stepName, functionToExecute, [stepConfig])
<a name="Library_function_Nodejs_executestep_Nodecanary"></a>

Executes the provided step, wrapping it with start/pass/fail logging and pass/fail and duration metrics.

The `executeStep` function also does the following:
+ Logs that the step started
+ Starts a timer
+ Executes the provided function
+ When the function returns normally, it counts as passing. If the function throws, it counts as failing
+ Ends the timer
+ Logs whether the step passed or failed
+ Emits the `stepName SuccessPercent` metric, 100 for pass or 0 for failure
+ Emits the `stepName Duration metric`, with a value based on the step start and end times
+ Returns what the functionToExecute returned or re-throws what ` functionToExecute` threw
+ Adds a step execution summary to the canary's report

 **Example** 

```
await synthetics.executeStep(stepName, async function () {
    return new Promise((resolve, reject) => {
        const req = https.request(url, (res) => {
            console.log(`Status: ${res.statusCode}`);
            if (res.statusCode >= 400) {
                reject(new Error(`Request failed with status ${res.statusCode} for ${url}`));
            } else {
                resolve();
            }
        });

        req.on('error', (err) => {
            reject(new Error(`Request failed for ${url}: ${err.message}`));
        });

        req.end();
    });
});
```

## executeHttpStep(stepName, requestOptions, [callback], [stepConfig])
<a name="Library_function_Nodejs_executeHttpStep"></a>

Executes the provided HTTP request as a step, and publishes `SuccessPercent` (pass/fail) and `Duration` metrics.

**executeHttpStep** uses either HTTP or HTTPS native functions under the hood, depending upon the protocol specified in the request.

This function also adds a step execution summary to the canary's report. The summary includes details about each HTTP request, such as the following:
+ Start time
+ End time
+ Status (PASSED/FAILED)
+ Failure reason, if it failed
+ HTTP call details such as request/response headers, body, status code, status message, and performance timings. 

**Topics**
+ [Parameters](#Library_function_Nodejs_executeHttpStep_parameters_Nodecanary)
+ [Examples of using executeHttpStep](#Library_function_Nodejs_executeHttpStep_examples_Nodecanary)

### Parameters
<a name="Library_function_Nodejs_executeHttpStep_parameters_Nodecanary"></a>

 **stepName(*String*)** 

Specifies the name of the step. This name is also used for publishing CloudWatch metrics for this step.

 **requestOptions(*Object or String*)** 

The value of this parameter can be a URL, a URL string, or an object. If it is an object, then it must be a set of configurable options to make an HTTP request. It supports all options in [ http.request(options[, callback])](https://nodejs.org/api/http.html#http_http_request_options_callback) in the Node.js documentation.

In addition to these Node.js options, **requestOptions** supports the additional parameter `body`. You can use the `body` parameter to pass data as a request body.

 **callback(*response*)** 

(Optional) This is a user function which is invoked with the HTTP response. The response is of the type [ Class: http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage).

 **stepConfig(*object*)** 

(Optional) Use this parameter to override global synthetics configurations with a different configuration for this step.

### Examples of using executeHttpStep
<a name="Library_function_Nodejs_executeHttpStep_examples_Nodecanary"></a>

The following series of examples build on each other to illustrate the various uses of this option.

This first example configures request parameters. You can pass a URL as ** requestOptions**:

```
let requestOptions = 'https://www.amazon.com';
```

Or you can pass a set of options:

```
let requestOptions = {
        'hostname': 'myproductsEndpoint.com',
        'method': 'GET',
        'path': '/test/product/validProductName',
        'port': 443,
        'protocol': 'https:'
    };
```

The next example creates a callback function which accepts a response. By default, if you do not specify **callback**, CloudWatch Synthetics validates that the status is between 200 and 299 inclusive.

```
// Handle validation for positive scenario
    const callback = async function(res) {
        return new Promise((resolve, reject) => {
            if (res.statusCode < 200 || res.statusCode > 299) {
                throw res.statusCode + ' ' + res.statusMessage;
            }
     
            let responseBody = '';
            res.on('data', (d) => {
                responseBody += d;
            });
     
            res.on('end', () => {
                // Add validation on 'responseBody' here if required. For ex, your status code is 200 but data might be empty
                resolve();
            });
        });
    };
```

The next example creates a configuration for this step that overrides the global CloudWatch Synthetics configuration. The step configuration in this example allows request headers, response headers, request body (post data), and response body in your report and restrict 'X-Amz-Security-Token' and 'Authorization' header values. By default, these values are not included in the report for security reasons. If you choose to include them, the data is only stored in your S3 bucket.

```
// By default headers, post data, and response body are not included in the report for security reasons. 
// Change the configuration at global level or add as step configuration for individual steps
let stepConfig = {
    includeRequestHeaders: true, 
    includeResponseHeaders: true,
    restrictedHeaders: ['X-Amz-Security-Token', 'Authorization'], // Restricted header values do not appear in report generated.
    includeRequestBody: true,
    includeResponseBody: true
};
```

This final example passes your request to **executeHttpStep** and names the step.

```
await synthetics.executeHttpStep('Verify GET products API', requestOptions, callback, stepConfig);
```

With this set of examples, CloudWatch Synthetics adds the details from each step in your report and produces metrics for each step using **stepName**.

 You will see `successPercent` and `duration` metrics for the `Verify GET products API` step. You can monitor your API performance by monitoring the metrics for your API call steps. 

For a sample complete script that uses these functions, see [Multi-step API canary](CloudWatch_Synthetics_Canaries_Samples.md#CloudWatch_Synthetics_Canaries_Samples_APIsteps).

# Library functions available for Java canary
<a name="CloudWatch_Synthetics_Canaries_Java"></a>

The `executeStep` function is used to modularize the canary code and execute it in steps. In CloudWatch Synthetics, a Synthetics step is a way to break down your canary script into a series of clearly defined actions, allowing you to monitor different parts of your application journey separately. For each step, CloudWatch Synthetics does the following:
+ A report, including a summary of step execution details like the duration of a step, *pass* or *fail* status, and so on, is created for each canary run. When you choose a run in the CloudWatch Synthetics console, you can view execution details of each step on the **Step** tab.
+ *SuccessPercent* and *Duration* CloudWatch metrics are emitted for each step, enabling users to monitor availability and latency of each step.

   **Usage** 

  ```
  synthetics.executeStep(stepName,()->{
      try {
          //step code to be executed
          return null;
      } catch (Exception e) {
          throw e;
      }
  }).get();
  ```

   **Parameters** 
  + *stepName*, String (required) – A descriptive name of the Synthetics step
  + *function to execute*, Callable<T> (required) – Represents the tasks to be executed
  + *stepOptions*, `com.amazonaws.synthetics.StepOptions (optional)` – StepOptions object that can be used to configure the step execution. 

    *stepConfiguration*, ` com.amazonaws.synthetics.StepConfiguration`(required as part of the stepOptions)

 **Returns** 

The value returned is *CompletableFuture<T>*.

**Note**  
Synthetics only supports sequential steps. Make sure to call the `.get()` method as shown in the example to ensure that the step completes before proceeding to the subsequent step.

# Library functions available for Node.js canary scripts using Playwright
<a name="CloudWatch_Synthetics_Canaries_Nodejs_Playwright"></a>

This section describes the library functions that are available for canary scripts using the Node.js Playwright runtime.

**Topics**
+ [launch](#Synthetics_Library_Nodejs_Playwright_functions)
+ [newPage](#Synthetics_Library_Nodejs_Playwright_function_newPage)
+ [close](#Synthetics_Library_Nodejs_Playwright_function_close)
+ [getDefaultLaunchOptions](#Synthetics_Library_Nodejs_Playwright_function_getDefaultLaunchOptions)
+ [executeStep](#Synthetics_Library_Nodejs_Playwright_function_executeStep)

## launch
<a name="Synthetics_Library_Nodejs_Playwright_functions"></a>

This function launches a Chromium browser using a Playwright launch function, and returns the browser object. It decompresses browser binaries and launches the chromium browser by using default options suitable for a headless browser. For more information about the `launch` function, see [https://playwright.dev/docs/api/class-browsertype#browser-type-launch](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) in the Playwright documentation.

 **Usage** 

```
const browser = await synthetics.launch();
```

 **Arguments** 

`options` [options](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) (optional) is a configurable set of options for the browser.

 **Returns** 

Promise `<Browser>` where [Browser](https://playwright.dev/docs/api/class-browser) is a Playwright browser instance.

If this function is called again, a previously-opened browser is closed before initiating a new browser. You can override launch parameters used by CloudWatch Synthetics, and pass additional parameters when launching the browser. For example, the following code snippet launches a browser with default arguments and a default executable path, but with a viewport of 800 x 600 pixels. For more information, see [Playwright launch options](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) in the Playwright documentation.

```
const browser = await synthetics.launch({
  defaultViewport: { 
      "deviceScaleFactor": 1, 
      "width": 800,
      "height": 600 
}});
```

 You can also add or override Chromium flags passed on by default to the browser. For example, you can disable web security by adding a `--disable-web-security` flag to arguments in the CloudWatch Synthetics launch parameters: 

```
// This function adds the --disable-web-security flag to the launch parameters
const defaultOptions = await synthetics.getDefaultLaunchOptions();
const launchArgs = [...defaultOptions.args, '--disable-web-security'];
const browser = await synthetics.launch({
    args: launchArgs
  });
```

## newPage
<a name="Synthetics_Library_Nodejs_Playwright_function_newPage"></a>

The `newPage()` function creates and returns a new Playwright page. Synthetics automatically sets up a Chrome DevTools Protocol (CDP) connection to enable network captures for HTTP archive (HAR) generation.

 **Usage** 

Use `newPage()` in either of the following ways:

 **1. Creating a new page in a new browser context:** 

```
const page = await synthetics.newPage(browser);
```

 **2. Creating a new page in a specified browser context:** 

```
// Create a new browser context
const browserContext = await browser.newContext();

// Create a new page in the specified browser context
const page = await synthetics.newPage(browserContext)
```

 **Arguments** 

Accepts either Playwright [Browser](https://playwright.dev/docs/api/class-browser) instance or Playwright [ BrowserContext](https://playwright.dev/docs/api/class-browsercontext) instance. 

 **Returns** 

Promise <Page> where Page is a Playwright [Page](https://playwright.dev/docs/api/class-page) instance.

## close
<a name="Synthetics_Library_Nodejs_Playwright_function_close"></a>

Closes the currently-opened browser.

 **Usage** 

```
await synthetics.close();
```

It is recommended to close the browser in a `finally` block of your script.

 **Arguments** 

None 

 **Returns** 

Returns Promise<void> used by the Synthetics launch function for launching the browser.

## getDefaultLaunchOptions
<a name="Synthetics_Library_Nodejs_Playwright_function_getDefaultLaunchOptions"></a>

The `getDefaultLaunchOptions()` function returns the browser launch options that are used by CloudWatch Synthetics.

 **Usage** 

```
const defaultOptions = await synthetics.getDefaultLaunchOptions();
```

 **Arguments** 

None 

 **Returns** 

Returns Playwright [ launch options](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) used by the Synthetics `launch` function for launching the browser.

## executeStep
<a name="Synthetics_Library_Nodejs_Playwright_function_executeStep"></a>

The `executeStep` function is used to execute a step in a Synthetics script. In CloudWatch Synthetics, a Synthetics step is a way to break down your canary script into a series of clearly defined actions, allowing you to monitor different parts of your application journey separately. For each step, CloudWatch Synthetics does the following:
+ Automatically captures a screenshot before step starts and after a step is complete. You can also capture screenshots inside a step. Screenshots are captured by default, but can be turned off by using Synthetics configurations.
+ A report, including a summary, of step execution details like the duration of a step, `pass` or `fail` status, source and destination page URLs, associated screenshots, etc. is created for each canary run. When you choose a run in the CloudWatch Synthetics console, you can view execution details of each step on the **Step** tab.
+ `SuccessPercent` and `Duration` CloudWatch metrics are emitted for each step, enabling users to monitor availability and latency of each step.

 **Usage** 

```
await synthetics.executeStep("mystepname", async function () {
  await page.goto(url, { waitUntil: 'load', timeout: 30000 });
}
```

**Note**  
Steps should run sequentially. Be sure to use `await` on promises.

 **Arguments** 
+ `stepName` string (required) (boolean)— Name of the Synthetics step. 
+ `functionToExecute` async function (required)— The function that you want Synthetics to run. This function should contain the logic for the step.
+ `stepConfig` object (optional)— Step configuration overrides the global Synthetics configuration for this step.
  + `continueOnStepFailure` boolean (optional) — Whether to continue running the canary script after this step fails. 
  + `screenshotOnStepStart` boolean (optional) — Whether to take a screenshot at the start of this step. 
  + `screenshotOnStepSuccess` boolean (optional) — Whether to take a screenshot if this step succeeds. 
  + `screenshotOnStepFailure` boolean (optional) — Whether to take a screenshot if this step fails. 
+ `page` — Playwright page object (optional)

  A Playwright page object. Synthetics uses this page object to capture screenshots and URLs. By default, Synthetics uses the Playwright page created when the `synthetics.newPage()` function is called for capturing page details like screenshots and URLs.

 **Returns** 

Returns a Promise that resolves with the value returned by the ` functionToExecute` function. For an example script, see [Sample code for canary scripts](CloudWatch_Synthetics_Canaries_Samples.md) in this guide.

# Library functions available for Node.js canary scripts using Puppeteer
<a name="CloudWatch_Synthetics_Canaries_Library_Nodejs"></a>

This section describes the library functions available for Node.js canary scripts.

**Topics**
+ [Node.js library classes and functions that apply to all canaries](#CloudWatch_Synthetics_Library_allcanaries)
+ [Node.js library classes and functions that apply to UI canaries only](#CloudWatch_Synthetics_Library_UIcanaries)
+ [Node.js library classes and functions that apply to API canaries only](#CloudWatch_Synthetics_Library_APIcanaries)

## Node.js library classes and functions that apply to all canaries
<a name="CloudWatch_Synthetics_Library_allcanaries"></a>

The following CloudWatch Synthetics library functions for Node.js are useful for all canaries.

**Topics**
+ [Synthetics class](#CloudWatch_Synthetics_Library_Synthetics_Class_all)
+ [SyntheticsConfiguration class](#CloudWatch_Synthetics_Library_SyntheticsConfiguration)
+ [Synthetics logger](#CloudWatch_Synthetics_Library_SyntheticsLogger)
+ [SyntheticsLogHelper class](#CloudWatch_Synthetics_Library_SyntheticsLogHelper)

### Synthetics class
<a name="CloudWatch_Synthetics_Library_Synthetics_Class_all"></a>

The following functions for all canaries are in the Synthetics class.

**Topics**
+ [addExecutionError(errorMessage, ex);](#CloudWatch_Synthetics_Library_addExecutionError)
+ [getCanaryName();](#CloudWatch_Synthetics_Library_getCanaryName)
+ [getCanaryArn();](#CloudWatch_Synthetics_Library_getCanaryARN)
+ [getCanaryUserAgentString();](#CloudWatch_Synthetics_Library_getCanaryUserAgentString)
+ [getRuntimeVersion();](#CloudWatch_Synthetics_Library_getRuntimeVersion)
+ [getLogLevel();](#CloudWatch_Synthetics_Library_getLogLevel)
+ [setLogLevel();](#CloudWatch_Synthetics_Library_setLogLevel)

#### addExecutionError(errorMessage, ex);
<a name="CloudWatch_Synthetics_Library_addExecutionError"></a>

`errorMessage` describes the error and `ex` is the exception that is encountered

You can use `addExecutionError` to set execution errors for your canary. It fails the canary without interrupting the script execution. It also doesn't impact your `successPercent` metrics.

You should track errors as execution errors only if they are not important to indicate the success or failure of your canary script.

An example of the use of `addExecutionError` is the following. You are monitoring the availability of your endpoint and taking screenshots after the page has loaded. Because the failure of taking a screenshot doesn't determine availability of the endpoint, you can catch any errors encountered while taking screenshots and add them as execution errors. Your availability metrics will still indicate that the endpoint is up and running, but your canary status will be marked as failed. The following sample code block catches such an error and adds it as an execution error.

```
try {
    await synthetics.takeScreenshot(stepName, "loaded");
} catch(ex) {
    synthetics.addExecutionError('Unable to take screenshot ', ex);
}
```

#### getCanaryName();
<a name="CloudWatch_Synthetics_Library_getCanaryName"></a>

Returns the name of the canary.

#### getCanaryArn();
<a name="CloudWatch_Synthetics_Library_getCanaryARN"></a>

Returns the ARN of the canary.

#### getCanaryUserAgentString();
<a name="CloudWatch_Synthetics_Library_getCanaryUserAgentString"></a>

Returns the custom user agent of the canary.

#### getRuntimeVersion();
<a name="CloudWatch_Synthetics_Library_getRuntimeVersion"></a>

This function is available in runtime version `syn-nodejs-puppeteer-3.0` and later. It returns the Synthetics runtime version of the canary. For example, the return value could be `syn-nodejs-puppeteer-3.0`.

#### getLogLevel();
<a name="CloudWatch_Synthetics_Library_getLogLevel"></a>

Retrieves the current log level for the Synthetics library. Possible values are the following:
+ `0` – Debug
+ `1` – Info
+ `2` – Warn
+ `3` – Error

Example:

```
let logLevel = synthetics.getLogLevel();
```

#### setLogLevel();
<a name="CloudWatch_Synthetics_Library_setLogLevel"></a>

Sets the log level for the Synthetics library. Possible values are the following:
+ `0` – Debug
+ `1` – Info
+ `2` – Warn
+ `3` – Error

Example:

```
synthetics.setLogLevel(0);
```

### SyntheticsConfiguration class
<a name="CloudWatch_Synthetics_Library_SyntheticsConfiguration"></a>

This class is available only in the `syn-nodejs-2.1` runtime version or later.

You can use the `SyntheticsConfiguration` class to configure the behavior of Synthetics library functions. For example, you can use this class to configure the `executeStep()` function to not capture screenshots.

You can set CloudWatch Synthetics configurations at the global level, which are applied to all steps of canaries. You can also override these configurations at the step level by passing configuration key and value pairs.

You can pass in options at the step level. For examples, see [async executeStep(stepName, functionToExecute, [stepConfig]);](#CloudWatch_Synthetics_Library_executeStep) and [executeHttpStep(stepName, requestOptions, [callback], [stepConfig])](#CloudWatch_Synthetics_Library_executeHttpStep)

**Topics**
+ [setConfig(options)](#CloudWatch_Synthetics_Library_setConfig)
+ [Visual monitoring](#CloudWatch_Synthetics_Library_SyntheticsLogger_VisualTesting)

#### setConfig(options)
<a name="CloudWatch_Synthetics_Library_setConfig"></a>

` options ` is an object, which is a set of configurable options for your canary. The following sections explain the possible fields in ` options `.

##### setConfig(options) for all canaries
<a name="CloudWatch_Synthetics_Library_setConfigall"></a>

For canaries using `syn-nodejs-puppeteer-3.2` or later, the ** (options)** for **setConfig** can include the following parameters:
+ `includeRequestHeaders` (boolean)— Whether to include request headers in the report. The default is `false`.
+ `includeResponseHeaders` (boolean)— Whether to include response headers in the report. The default is `false`.
+ `restrictedHeaders` (array)— A list of header values to ignore, if headers are included. This applies to both request and response headers. For example, you can hide your credentials by passing ** includeRequestHeaders** as `true` and ** restrictedHeaders** as `['Authorization']`. 
+ `includeRequestBody` (boolean)— Whether to include the request body in the report. The default is `false`.
+ `includeResponseBody` (boolean)— Whether to include the response body in the report. The default is `false`.
**Important**  
If you enable either `includeResponseBody` or ` logResponseBody`, the data object is not returned in the response from some APIs, such as aws-sdk v3 clients. This is because of a limitation of Node.js and the type of response object used.

 **setConfig(options) regarding CloudWatch metrics** 

For canaries using `syn-nodejs-puppeteer-3.1` or later, the ** (options)** for **setConfig** can include the following Boolean parameters that determine which metrics are published by the canary. The default for each of these options is `true`. The options that start with `aggregated` determine whether the metric is emitted without the ` CanaryName` dimension. You can use these metrics to see the aggregated results for all of your canaries. The other options determine whether the metric is emitted with the `CanaryName` dimension. You can use these metrics to see results for each individual canary.

For a list of CloudWatch metrics emitted by canaries, see [CloudWatch metrics published by canaries](CloudWatch_Synthetics_Canaries_metrics.md).
+ `failedCanaryMetric` (boolean)— Whether to emit the ` Failed` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `failedRequestsMetric` (boolean)— Whether to emit the `Failed requests` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `_2xxMetric` (boolean)— Whether to emit the `2xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `_4xxMetric` (boolean)— Whether to emit the `4xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `_5xxMetric` (boolean)— Whether to emit the `5xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `stepDurationMetric` (boolean)— Whether to emit the `Step duration` metric (with the `CanaryName` `StepName` dimensions) for this canary. The default is `true`.
+ `stepSuccessMetric` (boolean)— Whether to emit the `Step success` metric (with the `CanaryName` `StepName` dimensions) for this canary. The default is `true`.
+ `aggregatedFailedCanaryMetric` (boolean)— Whether to emit the `Failed` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregatedFailedRequestsMetric` (boolean)— Whether to emit the `Failed Requests` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated2xxMetric` (boolean)— Whether to emit the ` 2xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated4xxMetric` (boolean)— Whether to emit the ` 4xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated5xxMetric` (boolean)— Whether to emit the ` 5xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `visualMonitoringSuccessPercentMetric` (boolean)— Whether to emit the `visualMonitoringSuccessPercent` metric for this canary. The default is `true`.
+ `visualMonitoringTotalComparisonsMetric` (boolean)— Whether to emit the `visualMonitoringTotalComparisons` metric for this canary. The default is `false`.
+ `includeUrlPassword` (boolean)— Whether to include a password that appears in the URL. By default, passwords that appear in URLs are redacted from logs and reports, to prevent disclosing sensitive data. The default is `false`.
+ `restrictedUrlParameters` (array)— A list of URL path or query parameters to redact. This applies to URLs appearing in logs, reports, and errors. The parameter is case-insensitive. You can pass an asterisk (\$1) as a value to redact all URL path and query parameter values. The default is an empty array.
+ `logRequest` (boolean)— Whether to log every request in canary logs. For UI canaries, this logs each request sent by the browser. The default is `true`.
+ `logResponse` (boolean)— Whether to log every response in canary logs. For UI canaries, this logs every response received by the browser. The default is `true`.
+ `logRequestBody` (boolean)— Whether to log request bodies along with the requests in canary logs. This configuration applies only if `logRequest` is `true`. The default is `false` .
+ `logResponseBody` (boolean)— Whether to log response bodies along with the responses in canary logs. This configuration applies only if `logResponse` is `true`. The default is ` false`.
**Important**  
If you enable either `includeResponseBody` or ` logResponseBody`, the data object is not returned in the response from some APIs, such as aws-sdk v3 clients. This is because of a limitation of Node.js and the type of response object used.
+ `logRequestHeaders` (boolean)— Whether to log request headers along with the requests in canary logs. This configuration applies only if `logRequest` is `true`. The default is ` false`.

  Note that `includeRequestHeaders` enables headers in artifacts.
+ `logResponseHeaders` (boolean)— Whether to log response headers along with the responses in canary logs. This configuration applies only if `logResponse` is `true`. The default is ` false`.

  Note that `includeResponseHeaders` enables headers in artifacts.

**Note**  
The `Duration` and `SuccessPercent` metrics are always emitted for each canary, both with and without the `CanaryName` metric.

##### Methods to enable or disable metrics
<a name="CloudWatch_Synthetics_Library_setConfig_metrics"></a>

 **disableAggregatedRequestMetrics()** 

Disables the canary from emitting all request metrics that are emitted with no `CanaryName` dimension.

 **disableRequestMetrics()** 

Disables all request metrics, including both per-canary metrics and metrics aggregated across all canaries.

 **disableStepMetrics()** 

Disables all step metrics, including both step success metrics and step duration metrics.

 **enableAggregatedRequestMetrics()** 

Enables the canary to emit all request metrics that are emitted with no ` CanaryName` dimension.

 **enableRequestMetrics()** 

Enables all request metrics, including both per-canary metrics and metrics aggregated across all canaries.

 **enableStepMetrics()** 

Enables all step metrics, including both step success metrics and step duration metrics.

 **get2xxMetric()** 

Returns whether the canary emits a `2xx` metric with the ` CanaryName` dimension.

 **get4xxMetric()** 

Returns whether the canary emits a `4xx` metric with the ` CanaryName` dimension.

 **get5xxMetric()** 

Returns whether the canary emits a `5xx` metric with the ` CanaryName` dimension.

 **getAggregated2xxMetric()** 

Returns whether the canary emits a `2xx` metric with no dimension.

 **getAggregated4xxMetric()** 

Returns whether the canary emits a `4xx` metric with no dimension.

 **getAggregatedFailedCanaryMetric()** 

Returns whether the canary emits a `Failed` metric with no dimension.

 **getAggregatedFailedRequestsMetric()** 

Returns whether the canary emits a `Failed requests` metric with no dimension.

 **getAggregated5xxMetric()** 

Returns whether the canary emits a `5xx` metric with no dimension.

 **getFailedCanaryMetric()** 

Returns whether the canary emits a `Failed` metric with the ` CanaryName` dimension.

 **getFailedRequestsMetric()** 

Returns whether the canary emits a `Failed requests` metric with the `CanaryName` dimension.

 **getStepDurationMetric()** 

Returns whether the canary emits a `Duration` metric with the ` CanaryName` dimension for this canary.

 **getStepSuccessMetric()** 

Returns whether the canary emits a `StepSuccess` metric with the ` CanaryName` dimension for this canary.

 **with2xxMetric(\$12xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `2xx` metric with the `CanaryName` dimension for this canary.

 **with4xxMetric(\$14xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `4xx` metric with the `CanaryName` dimension for this canary.

 **with5xxMetric(\$15xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `5xx` metric with the `CanaryName` dimension for this canary.

 **withAggregated2xxMetric(aggregated2xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `2xx` metric with no dimension for this canary.

 **withAggregated4xxMetric(aggregated4xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `4xx` metric with no dimension for this canary.

 **withAggregated5xxMetric(aggregated5xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `5xx` metric with no dimension for this canary.

 ** withAggregatedFailedCanaryMetric(aggregatedFailedCanaryMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed` metric with no dimension for this canary.

 ** withAggregatedFailedRequestsMetric(aggregatedFailedRequestsMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed requests` metric with no dimension for this canary.

 **withFailedCanaryMetric(failedCanaryMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed` metric with the `CanaryName` dimension for this canary.

 **withFailedRequestsMetric(failedRequestsMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed requests` metric with the `CanaryName` dimension for this canary.

 **withStepDurationMetric(stepDurationMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `Duration` metric with the `CanaryName` dimension for this canary.

 **withStepSuccessMetric(stepSuccessMetric)** 

Accepts a Boolean argument, which specifies whether to emit a ` StepSuccess` metric with the `CanaryName` dimension for this canary.

##### Methods to enable or disable other features
<a name="CloudWatch_Synthetics_Library_setConfig_methods"></a>

 **withHarFile()** 

Accepts a Boolean argument, which specifies whether to create a HAR file for this canary.

 **withStepsReport()** 

Accepts a Boolean argument, which specifies whether to report a step execution summary for this canary.

 **withIncludeUrlPassword()** 

Accepts a Boolean argument, which specifies whether to include passwords that appear in URLs in logs and reports.

 **withRestrictedUrlParameters()** 

Accepts an array of URL path or query parameters to redact. This applies to URLs appearing in logs, reports, and errors. You can pass an asterisk (\$1) as a value to redact all URL path and query parameter values

 **withLogRequest()** 

Accepts a Boolean argument, which specifies whether to log every request in the canary's logs.

 **withLogResponse()** 

Accepts a Boolean argument, which specifies whether to log every response in the canary's logs.

 **withLogRequestBody()** 

Accepts a Boolean argument, which specifies whether to log every request body in the canary's logs.

 **withLogResponseBody()** 

Accepts a Boolean argument, which specifies whether to log every response body in the canary's logs.

 **withLogRequestHeaders()** 

Accepts a Boolean argument, which specifies whether to log every request header in the canary's logs.

 **withLogResponseHeaders()** 

Accepts a Boolean argument, which specifies whether to log every response header in the canary's logs.

 **getHarFile()** 

Returns whether the canary creates a HAR file.

 **getStepsReport()** 

Returns whether the canary reports a step execution summary.

 **getIncludeUrlPassword()** 

Returns whether the canary includes passwords that appear in URLs in logs and reports.

 **getRestrictedUrlParameters()** 

Returns whether the canary redacts URL path or query parameters.

 **getLogRequest()** 

Returns whether the canary logs every request in the canary's logs.

 **getLogResponse()** 

Returns whether the canary logs every response in the canary's logs.

 **getLogRequestBody()** 

Returns whether the canary logs every request body in the canary's logs.

 **getLogResponseBody()** 

Returns whether the canary logs every response body in the canary's logs.

 **getLogRequestHeaders()** 

Returns whether the canary logs every request header in the canary's logs.

 **getLogResponseHeaders()** 

Returns whether the canary logs every response header in the canary's logs.

 **Functions for all canaries** 
+ `withIncludeRequestHeaders`(includeRequestHeaders)
+ `withIncludeResponseHeaders`(includeResponseHeaders)
+ `withRestrictedHeaders`(restrictedHeaders)
+ `withIncludeRequestBody`(includeRequestBody)
+ `withIncludeResponseBody`(includeResponseBody)
+ `enableReportingOptions`()— Enables all reporting options-- **includeRequestHeaders**, ** includeResponseHeaders**, **includeRequestBody**, and **includeResponseBody**, .
+ `disableReportingOptions`()— Disables all reporting options-- **includeRequestHeaders**, ** includeResponseHeaders**, **includeRequestBody**, and **includeResponseBody**, .

##### setConfig(options) for UI canaries
<a name="CloudWatch_Synthetics_Library_setConfigUI"></a>

For UI canaries, **setConfig** can include the following Boolean parameters:
+ `continueOnStepFailure` (boolean)— Whether to continue with running the canary script after a step fails (this refers to the ** executeStep** function). If any steps fail, the canary run will still be marked as failed. The default is `false`.
+ `harFile` (boolean)— Whether to create a HAR file. The default is `True`.
+ `screenshotOnStepStart` (boolean)— Whether to take a screenshot before starting a step.
+ `screenshotOnStepSuccess` (boolean)— Whether to take a screenshot after completing a successful step.
+ `screenshotOnStepFailure` (boolean)— Whether to take a screenshot after a step fails.

##### Methods to enable or disable screenshots
<a name="CloudWatch_Synthetics_Library_setConfig_screenshots"></a>

 **disableStepScreenshots()** 

Disables all screenshot options (screenshotOnStepStart, screenshotOnStepSuccess, and screenshotOnStepFailure).

 **enableStepScreenshots()** 

Enables all screenshot options (screenshotOnStepStart, screenshotOnStepSuccess, and screenshotOnStepFailure). By default, all these methods are enabled.

 **getScreenshotOnStepFailure()** 

Returns whether the canary takes a screenshot after a step fails.

 **getScreenshotOnStepStart()** 

Returns whether the canary takes a screenshot before starting a step.

 **getScreenshotOnStepSuccess()** 

Returns whether the canary takes a screenshot after completing a step successfully.

 **withScreenshotOnStepStart(screenshotOnStepStart)** 

Accepts a Boolean argument, which indicates whether to take a screenshot before starting a step.

 **withScreenshotOnStepSuccess(screenshotOnStepSuccess)** 

Accepts a Boolean argument, which indicates whether to take a screenshot after completing a step successfully.

 **withScreenshotOnStepFailure(screenshotOnStepFailure)** 

Accepts a Boolean argument, which indicates whether to take a screenshot after a step fails.

 **Usage in UI canaries** 

First, import the synthetics dependency and fetch the configuration.

```
// Import Synthetics dependency
const synthetics = require('@aws/synthetics-puppeteer');

// Get Synthetics configuration
const synConfig = synthetics.getConfiguration();
```

Then, set the configuration for each option by calling the setConfig method using one of the following options.

```
// Set configuration values
    synConfig.setConfig({
        screenshotOnStepStart: true, 
        screenshotOnStepSuccess: false,
        screenshotOnStepFailure: false
    });
```

Or

```
synConfig.withScreenshotOnStepStart(false).withScreenshotOnStepSuccess(true).withScreenshotOnStepFailure(true)
```

To disable all screenshots, use the `disableStepScreenshots()` function as in this example.

```
synConfig.disableStepScreenshots();
```

You can enable and disable screenshots at any point in the code. For example, to disable screenshots only for one step, disable them before running that step and then enable them after the step.

##### setConfig(options) for API canaries
<a name="CloudWatch_Synthetics_Library_setConfigAPI"></a>

For API canaries, **setConfig** can include the following Boolean parameters:
+ `continueOnHttpStepFailure` (boolean)— Whether to continue with running the canary script after an HTTP step fails (this refers to the **executeHttpStep** function). If any steps fail, the canary run will still be marked as failed. The default is `true`.

#### Visual monitoring
<a name="CloudWatch_Synthetics_Library_SyntheticsLogger_VisualTesting"></a>

Visual monitoring compares screenshots taken during a canary run with screenshots taken during a baseline canary run. If the discrepancy between the two screenshots is beyond a threshold percentage, the canary fails and you can see the areas with differences highlighted in color in the canary run report. Visual monitoring is supported in canaries running **syn-puppeteer-node-3.2** and later. It is not currently supported in canaries running Python and Selenium.

To enable visual monitoring, add the following line of code to the canary script. For more details, see [SyntheticsConfiguration class](#CloudWatch_Synthetics_Library_SyntheticsConfiguration).

```
syntheticsConfiguration.withVisualCompareWithBaseRun(true);
```

The first time that the canary runs successfully after this line is added to the script, it uses the screenshots taken during that run as the baseline for comparison. After that first canary run, you can use the CloudWatch console to edit the canary to do any of the following:
+ Set the next run of the canary as the new baseline.
+ Draw boundaries on the current baseline screenshot to designate areas of the screenshot to ignore during visual comparisons.
+ Remove a screenshot from being used for visual monitoring.

For more information about using the CloudWatch console to edit a canary, see [Edit or delete a canary](synthetics_canaries_deletion.md).

 **Other options for visual monitoring** 

 ** syntheticsConfiguration.withVisualVarianceThresholdPercentage(desiredPercentage)** 

Set the acceptable percentage for screenshot variance in visual comparisons.

 ** syntheticsConfiguration.withVisualVarianceHighlightHexColor("\$1fafa00")** 

Set the highlight color that designates variance areas when you look at canary run reports that use visual monitoring.

 ** syntheticsConfiguration.withFailCanaryRunOnVisualVariance(failCanary)** 

Set whether or not the canary fails when there is a visual difference that is more than the threshold. The default is to fail the canary.

### Synthetics logger
<a name="CloudWatch_Synthetics_Library_SyntheticsLogger"></a>

SyntheticsLogger writes logs out to both the console and to a local log file at the same log level. This log file is written to both locations only if the log level is at or below the desired logging level of the log function that was called.

The logging statements in the local log file are prepended with "DEBUG: ", "INFO: ", and so on to match the log level of the function that was called.

You can use the SyntheticsLogger, assuming you want to run the Synthetics Library at the same log level as your Synthetics canary logging.

Using the SyntheticsLogger is not required to create a log file that is uploaded to your S3 results location. You could instead create a different log file in the ` /tmp` folder. Any files created under the `/tmp` folder are uploaded to the results location in S3 as artifacts. 

To use the Synthetics Library logger:

```
const log = require('@aws/synthetics-logger');
```

Useful function definitions:

 **log.debug(*message*, *ex* );** 

Parameters: *message* is the message to log. * ex* is the exception, if any, to log.

Example:

```
log.debug("Starting step - login.");
```

 **log.error(*message*, *ex* );** 

Parameters: *message* is the message to log. * ex* is the exception, if any, to log.

Example:

```
try {
  await login();
catch (ex) {
  log.error("Error encountered in step - login.", ex);
}
```

 **log.info(*message*, *ex* );** 

Parameters: *message* is the message to log. * ex* is the exception, if any, to log.

Example:

```
log.info("Successfully completed step - login.");
```

 **log.log(*message*, *ex* );** 

This is an alias for `log.info`. 

Parameters: *message* is the message to log. * ex* is the exception, if any, to log.

Example:

```
 log.log("Successfully completed step - login.");
```

 **log.warn(*message*, *ex* );** 

Parameters: *message* is the message to log. * ex* is the exception, if any, to log.

Example:

```
log.warn("Exception encountered trying to publish CloudWatch Metric.", ex);
```

### SyntheticsLogHelper class
<a name="CloudWatch_Synthetics_Library_SyntheticsLogHelper"></a>

The `SyntheticsLogHelper` class is available in the runtime ` syn-nodejs-puppeteer-3.2` and later runtimes. It is already initialized in the CloudWatch Synthetics library and is configured with Synthetics configuration. You can add this as a dependency in your script. This class enables you to sanitize URLs, headers, and error messages to redact sensitive information.

**Note**  
Synthetics sanitizes all URLs and error messages it logs before including them in logs, reports, HAR files, and canary run errors based on the Synthetics configuration setting `restrictedUrlParameters`. You have to use ` getSanitizedUrl` or `getSanitizedErrorMessage` only if you are logging URLs or errors in your script. Synthetics does not store any canary artifacts except for canary errors thrown by the script. Canary run artifacts are stored in your customer account. For more information, see [Security considerations for Synthetics canaries](servicelens_canaries_security.md).

**Topics**
+ [getSanitizedUrl(url, stepConfig = null)](#CloudWatch_Synthetics_Library_getSanitizedUrl)
+ [getSanitizedErrorMessage](#CloudWatch_Synthetics_Library_getSanitizedErrorMessage)
+ [getSanitizedHeaders(headers, stepConfig=null)](#CloudWatch_Synthetics_Library_getSanitizedHeaders)

#### getSanitizedUrl(url, stepConfig = null)
<a name="CloudWatch_Synthetics_Library_getSanitizedUrl"></a>

This function is available in `syn-nodejs-puppeteer-3.2` and later. It returns sanitized url strings based on the configuration. You can choose to redact sensitive URL parameters such as password and access\$1token by setting the property `restrictedUrlParameters`. By default, passwords in URLs are redacted. You can enable URL passwords if needed by setting `includeUrlPassword` to true. 

This function throws an error if the URL passed in is not a valid URL.

 **Parameters ** 
+ *url* is a string and is the URL to sanitize.
+  *stepConfig* (Optional) overrides the global Synthetics configuration for this function. If `stepConfig` is not passed in, the global configuration is used to sanitize the URL.

 **Example ** 

This example uses the following sample URL: ` https://example.com/learn/home?access_token=12345&token_type=Bearer&expires_in=1200`. In this example, `access_token` contains your sensitive information which shouldn't be logged. Note that the Synthetics services doesn't store any canary run artifacts. Artifacts such as logs, screenshots, and reports are all stored in an Amazon S3 bucket in your customer account.

The first step is to set the Synthetics configuration.

```
// Import Synthetics dependency
const synthetics = require('@aws/synthetics-puppeteer');

// Import Synthetics logger for logging url
const log = require('@aws/synthetics-logger');

// Get Synthetics configuration
const synConfig = synthetics.getConfiguration();

// Set restricted parameters
synConfig.setConfig({
   restrictedUrlParameters: ['access_token'];
});
// Import SyntheticsLogHelper dependency
const syntheticsLogHelper = require('@aws/synthetics-log-helper');

const sanitizedUrl = syntheticsLogHelper.getSanitizedUrl('URL');



const urlConfig = {
   restrictedUrlParameters = ['*']
};
const sanitizedUrl = syntheticsLogHelper.getSanitizedUrl('URL', urlConfig);
logger.info('My example url is: ' + sanitizedUrl);
```

Next, sanitize and log the URL

```
// Import SyntheticsLogHelper dependency
const syntheticsLogHelper = require('@aws/synthetics-log-helper');

const sanitizedUrl = syntheticsLogHelper.getSanitizedUrl('https://example.com/learn/home?access_token=12345&token_type=Bearer&expires_in=1200');
```

This logs the following in your canary log.

```
My example url is: https://example.com/learn/home?access_token=REDACTED&token_type=Bearer&expires_in=1200
```

You can override the Synthetics configuration for a URL by passing in an optional parameter containing Synthetics configuration options, as in the following example.

```
const urlConfig = {
   restrictedUrlParameters = ['*']
};
const sanitizedUrl = syntheticsLogHelper.getSanitizedUrl('https://example.com/learn/home?access_token=12345&token_type=Bearer&expires_in=1200', urlConfig);
logger.info('My example url is: ' + sanitizedUrl);
```

The preceding example redacts all query parameters, and is logged as follows:

```
My example url is: https://example.com/learn/home?access_token=REDACTED&token_type=REDACTED&expires_in=REDACTED
```

#### getSanitizedErrorMessage
<a name="CloudWatch_Synthetics_Library_getSanitizedErrorMessage"></a>

This function is available in `syn-nodejs-puppeteer-3.2` and later. It returns sanitized error strings by sanitizing any URLs present based on the Synthetics configuration. You can choose to override the global Synthetics configuration when you call this function by passing an optional `stepConfig` parameter. 

 **Parameters ** 
+ *error* is the error to sanitize. It can be an Error object or a string.
+  *stepConfig* (Optional) overrides the global Synthetics configuration for this function. If `stepConfig` is not passed in, the global configuration is used to sanitize the URL.

 **Example ** 

This example uses the following error: ` Failed to load url: https://example.com/learn/home?access_token=12345&token_type=Bearer&expires_in=1200`

The first step is to set the Synthetics configuration.

```
// Import Synthetics dependency
const synthetics = require('@aws/synthetics-puppeteer');

// Import Synthetics logger for logging url
const log = require('@aws/synthetics-logger');

// Get Synthetics configuration
const synConfig = synthetics.getConfiguration();

// Set restricted parameters
synConfig.setConfig({
   restrictedUrlParameters: ['access_token'];
});
```

Next, sanitize and log the error message

```
// Import SyntheticsLogHelper dependency
const syntheticsLogHelper = require('@aws/synthetics-log-helper');

try {
   // Your code which can throw an error containing url which your script logs
} catch (error) {
    const sanitizedErrorMessage = syntheticsLogHelper.getSanitizedErrorMessage(errorMessage);
    logger.info(sanitizedErrorMessage);
}
```

This logs the following in your canary log.

```
Failed to load url: https://example.com/learn/home?access_token=REDACTED&token_type=Bearer&expires_in=1200
```

#### getSanitizedHeaders(headers, stepConfig=null)
<a name="CloudWatch_Synthetics_Library_getSanitizedHeaders"></a>

This function is available in `syn-nodejs-puppeteer-3.2` and later. It returns sanitized headers based on the `restrictedHeaders` property of ` syntheticsConfiguration`. The headers specified in the `restrictedHeaders` property are redacted from logs, HAR files, and reports. 

 **Parameters ** 
+ *headers* is an object containing the headers to sanitize.
+ *stepConfig* (Optional) overrides the global Synthetics configuration for this function. If `stepConfig` is not passed in, the global configuration is used to sanitize the headers.

## Node.js library classes and functions that apply to UI canaries only
<a name="CloudWatch_Synthetics_Library_UIcanaries"></a>

The following CloudWatch Synthetics library functions for Node.js are useful only for UI canaries.

**Topics**
+ [Synthetics class](#CloudWatch_Synthetics_Library_Synthetics_Class)
+ [BrokenLinkCheckerReport class](#CloudWatch_Synthetics_Library_BrokenLinkCheckerReport)
+ [SyntheticsLink class](#CloudWatch_Synthetics_Library_SyntheticsLink)

### Synthetics class
<a name="CloudWatch_Synthetics_Library_Synthetics_Class"></a>

The following functions are in the Synthetics class.

**Topics**
+ [async addUserAgent(page, userAgentString);](#CloudWatch_Synthetics_Library_addUserAgent)
+ [async executeStep(stepName, functionToExecute, [stepConfig]);](#CloudWatch_Synthetics_Library_executeStep)
+ [getDefaultLaunchOptions();](#CloudWatch_Synthetics_Library_getDefaultLaunchOptions)
+ [getPage();](#CloudWatch_Synthetics_Library_getPage)
+ [getRequestResponseLogHelper();](#CloudWatch_Synthetics_Library_getRequestResponseLogHelper)
+ [launch(options)](#CloudWatch_Synthetics_Library_LaunchOptions)
+ [RequestResponseLogHelper class](#CloudWatch_Synthetics_Library_RequestResponseLogHelper)
+ [setRequestResponseLogHelper();](#CloudWatch_Synthetics_Library_setRequestResponseLogHelper)
+ [async takeScreenshot(name, suffix);](#CloudWatch_Synthetics_Library_takeScreenshot)

#### async addUserAgent(page, userAgentString);
<a name="CloudWatch_Synthetics_Library_addUserAgent"></a>

This function appends *userAgentString* to the specified page's user-agent header.

Example:

```
await synthetics.addUserAgent(page, "MyApp-1.0");
```

Results in the page’s user-agent header being set to ` browsers-user-agent-header-valueMyApp-1.0`

#### async executeStep(stepName, functionToExecute, [stepConfig]);
<a name="CloudWatch_Synthetics_Library_executeStep"></a>

Executes the provided step, wrapping it with start/pass/fail logging, start/pass/fail screenshots, and pass/fail and duration metrics.

**Note**  
If you are using the `syn-nodejs-2.1` or later runtime, you can configure whether and when screenshots are taken. For more information, see [SyntheticsConfiguration class](#CloudWatch_Synthetics_Library_SyntheticsConfiguration).

The `executeStep` function also does the following:
+ Logs that the step started.
+ Takes a screenshot named `<stepName>-starting`.
+ Starts a timer.
+ Executes the provided function.
+ If the function returns normally, it counts as passing. If the function throws, it counts as failing.
+ Ends the timer.
+ Logs whether the step passed or failed
+ Takes a screenshot named `<stepName>-succeeded` or ` <stepName>-failed`.
+ Emits the `stepName` `SuccessPercent` metric, 100 for pass or 0 for failure.
+ Emits the `stepName` `Duration` metric, with a value based on the step start and end times.
+ Finally, returns what the `functionToExecute` returned or re-throws what `functionToExecute` threw.

If the canary uses the `syn-nodejs-2.0` runtime or later, this function also adds a step execution summary to the canary's report. The summary includes details about each step, such as start time, end time, status (PASSED/FAILED), failure reason (if failed), and screenshots captured during the execution of each step.

Example:

```
await synthetics.executeStep('navigateToUrl', async function (timeoutInMillis = 30000) {
           await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis});});
```

Response:

Returns what `functionToExecute` returns.

 **Updates with syn-nodejs-2.2** 

Starting with `syn-nodejs-2.2`, you can optionally pass step configurations to override CloudWatch Synthetics configurations at the step level. For a list of options that you can pass to `executeStep`, see [SyntheticsConfiguration class](#CloudWatch_Synthetics_Library_SyntheticsConfiguration).

The following example overrides the default `false` configuration for ` continueOnStepFailure` to `true` and specifies when to take screenthots.

```
var stepConfig = {
    'continueOnStepFailure': true,
    'screenshotOnStepStart': false,
    'screenshotOnStepSuccess': true,
    'screenshotOnStepFailure': false
}

await executeStep('Navigate to amazon', async function (timeoutInMillis = 30000) {
      await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis});
 }, stepConfig);
```

#### getDefaultLaunchOptions();
<a name="CloudWatch_Synthetics_Library_getDefaultLaunchOptions"></a>

The `getDefaultLaunchOptions()` function returns the browser launch options that are used by CloudWatch Synthetics. For more information, see [Launch options type](https://pptr.dev/browsers-api/browsers.launchoptions/) 

```
// This function returns default launch options used by Synthetics.
const defaultOptions = await synthetics.getDefaultLaunchOptions();
```

#### getPage();
<a name="CloudWatch_Synthetics_Library_getPage"></a>

Returns the current open page as a Puppeteer object. For more information, see [Puppeteer API v1.14.0](https://github.com/puppeteer/puppeteer/blob/v1.14.0/docs/api.md).

Example:

```
let page = await synthetics.getPage();
```

Response:

The page (Puppeteer object) that is currently open in the current browser session.

#### getRequestResponseLogHelper();
<a name="CloudWatch_Synthetics_Library_getRequestResponseLogHelper"></a>

**Important**  
In canaries that use the `syn-nodejs-puppeteer-3.2` runtime or later, this function is deprecated along with the `RequestResponseLogHelper` class. Any use of this function causes a warning to appear in your canary logs. This function will be removed in future runtime versions. If you are using this function, use [RequestResponseLogHelper class](#CloudWatch_Synthetics_Library_RequestResponseLogHelper) instead. 

Use this function as a builder pattern for tweaking the request and response logging flags.

Example:

```
synthetics.setRequestResponseLogHelper(getRequestResponseLogHelper().withLogRequestHeaders(false));;
```

Response:

```
{RequestResponseLogHelper}
```

#### launch(options)
<a name="CloudWatch_Synthetics_Library_LaunchOptions"></a>

The options for this function are available only in the `syn-nodejs-2.1` runtime version or later.

This function is used only for UI canaries. It closes the existing browser and launches a new one.

**Note**  
CloudWatch Synthetics always launches a browser before starting to run your script. You don't need to call launch() unless you want to launch a new browser with custom options.

(options) is a configurable set of options to set on the browser. For more information, [Launch options type](https://pptr.dev/browsers-api/browsers.launchoptions/) .

If you call this function with no options, Synthetics launches a browser with default arguments, `executablePath`, and `defaultViewport`. The default viewport in CloudWatch Synthetics is 1920 by 1080.

You can override launch parameters used by CloudWatch Synthetics and pass additional parameters when launching the browser. For example, the following code snippet launches a browser with default arguments and a default executable path, but with a viewport of 800 x 600.

```
await synthetics.launch({
        defaultViewport: { 
            "deviceScaleFactor": 1, 
            "width": 800,
            "height": 600 
    }});
```

The following sample code adds a new `ignoreHTTPSErrors` parameter to the CloudWatch Synthetics launch parameters:

```
await synthetics.launch({
        ignoreHTTPSErrors: true
 });
```

You can disable web security by adding a `--disable-web-security` flag to args in the CloudWatch Synthetics launch parameters:

```
// This function adds the --disable-web-security flag to the launch parameters
const defaultOptions = await synthetics.getDefaultLaunchOptions();
const launchArgs = [...defaultOptions.args, '--disable-web-security'];
await synthetics.launch({
     args: launchArgs
  });
```

#### RequestResponseLogHelper class
<a name="CloudWatch_Synthetics_Library_RequestResponseLogHelper"></a>

**Important**  
In canaries that use the `syn-nodejs-puppeteer-3.2` runtime or later, this class is deprecated. Any use of this class causes a warning to appear in your canary logs. This function will be removed in future runtime versions. If you are using this function, use [RequestResponseLogHelper class](#CloudWatch_Synthetics_Library_RequestResponseLogHelper) instead.

Handles the fine-grained configuration and creation of string representations of request and response payloads. 

```
class RequestResponseLogHelper {
 
    constructor () {
        this.request = {url: true, resourceType: false, method: false, headers: false, postData: false};
        this.response = {status: true, statusText: true, url: true, remoteAddress: false, headers: false};
    }
 
    withLogRequestUrl(logRequestUrl);
    
    withLogRequestResourceType(logRequestResourceType);
    
    withLogRequestMethod(logRequestMethod);
    
    withLogRequestHeaders(logRequestHeaders);
    
    withLogRequestPostData(logRequestPostData);

        
    withLogResponseStatus(logResponseStatus);
    
    withLogResponseStatusText(logResponseStatusText);
   
    withLogResponseUrl(logResponseUrl);
 
    withLogResponseRemoteAddress(logResponseRemoteAddress);
    
    withLogResponseHeaders(logResponseHeaders);
```

Example:

```
synthetics.setRequestResponseLogHelper(getRequestResponseLogHelper()
.withLogRequestPostData(true)
.withLogRequestHeaders(true)
.withLogResponseHeaders(true));
```

Response:

```
{RequestResponseLogHelper}
```

#### setRequestResponseLogHelper();
<a name="CloudWatch_Synthetics_Library_setRequestResponseLogHelper"></a>

**Important**  
In canaries that use the `syn-nodejs-puppeteer-3.2` runtime or later, this function is deprecated along with the `RequestResponseLogHelper` class. Any use of this function causes a warning to appear in your canary logs. This function will be removed in future runtime versions. If you are using this function, use [RequestResponseLogHelper class](#CloudWatch_Synthetics_Library_RequestResponseLogHelper) instead. 

Use this function as a builder pattern for setting the request and response logging flags.

Example:

```
synthetics.setRequestResponseLogHelper().withLogRequestHeaders(true).withLogResponseHeaders(true);
```

Response:

```
{RequestResponseLogHelper}
```

#### async takeScreenshot(name, suffix);
<a name="CloudWatch_Synthetics_Library_takeScreenshot"></a>

Takes a screenshot (.PNG) of the current page with name and suffix (optional).

Example:

```
await synthetics.takeScreenshot("navigateToUrl", "loaded")
```

This example captures and uploads a screenshot named ` 01-navigateToUrl-loaded.png` to the canary's S3 bucket.

You can take a screenshot for a particular canary step by passing the ` stepName` as the first parameter. Screenshots are linked to the canary step in your reports, to help you track each step while debugging.

CloudWatch Synthetics canaries automatically take screenshots before starting a step (the `executeStep` function) and after the step completion (unless you configure the canary to disable screenshots). You can take more screenshots by passing in the step name in the `takeScreenshot` function.

The following example takes screenshot with the `signupForm` as the value of the `stepName`. The screenshot will be named ` 02-signupForm-address` and will be linked to the step named ` signupForm` in the canary report.

```
await synthetics.takeScreenshot('signupForm', 'address')
```

### BrokenLinkCheckerReport class
<a name="CloudWatch_Synthetics_Library_BrokenLinkCheckerReport"></a>

This class provides methods to add a synthetics link. It's supported only on canaries that use the `syn-nodejs-2.0-beta` version of the runtime or later. 

To use `BrokenLinkCheckerReport`, include the following lines in the script:

```
const BrokenLinkCheckerReport = require('@aws/synthetics-broken-link-checker-report');
            
const brokenLinkCheckerReport = new BrokenLinkCheckerReport();
```

Useful function definitions:

 **addLink(*syntheticsLink*, isBroken)** 

` syntheticsLink ` is a ` SyntheticsLink` object representing a link. This function adds the link according to the status code. By default, it considers a link to be broken if the status code is not available or the status code is 400 or higher. You can override this default behavior by passing in the optional parameter `isBrokenLink` with a value of `true` or `false`.

This function does not have a return value.

 **getLinks()** 

This function returns an array of `SyntheticsLink` objects that are included in the broken link checker report.

 **getTotalBrokenLinks()** 

This function returns a number representing the total number of broken links.

 **getTotalLinksChecked()** 

This function returns a number representing the total number of links included in the report.

 **How to use BrokenLinkCheckerReport** 

The following canary script code snippet demonstrates an example of navigating to a link and adding it to the broken link checker report.

1. Import `SyntheticsLink`, `BrokenLinkCheckerReport`, and ` Synthetics`.

   ```
   const BrokenLinkCheckerReport = require('@aws/synthetics-broken-link-checker-report');
   const SyntheticsLink = require('@aws/synthetics-link');
   
   // Synthetics dependency
   const synthetics = require('@aws/synthetics-puppeteer');
   ```

1. To add a link to the report, create an instance of ` BrokenLinkCheckerReport`.

   ```
   let brokenLinkCheckerReport = new BrokenLinkCheckerReport();
   ```

1. Navigate to the URL and add it to the broken link checker report.

   ```
   let url = "https://amazon.com";
   
   let syntheticsLink = new SyntheticsLink(url);
   
   // Navigate to the url.
   let page = await synthetics.getPage();
   
   // Create a new instance of Synthetics Link
   let link = new SyntheticsLink(url)
   
   try {
       const response = await page.goto(url, {waitUntil: 'domcontentloaded', timeout: 30000});
   } catch (ex) {
       // Add failure reason if navigation fails.
       link.withFailureReason(ex);
   }
   
   if (response) {
       // Capture screenshot of destination page
       let screenshotResult = await synthetics.takeScreenshot('amazon-home', 'loaded');
      
       // Add screenshot result to synthetics link
       link.addScreenshotResult(screenshotResult);
   
       // Add status code and status description to the link
       link.withStatusCode(response.status()).withStatusText(response.statusText())
   }
   
   // Add link to broken link checker report.
   brokenLinkCheckerReport.addLink(link);
   ```

1. Add the report to Synthetics. This creates a JSON file named ` BrokenLinkCheckerReport.json` in your S3 bucket for each canary run. You can see a links report in the console for each canary run along with screenshots, logs, and HAR files.

   ```
   await synthetics.addReport(brokenLinkCheckerReport);
   ```

### SyntheticsLink class
<a name="CloudWatch_Synthetics_Library_SyntheticsLink"></a>

This class provides methods to wrap information. It's supported only on canaries that use the `syn-nodejs-2.0-beta` version of the runtime or later. 

To use `SyntheticsLink`, include the following lines in the script:

```
const SyntheticsLink = require('@aws/synthetics-link');

const syntheticsLink = new SyntheticsLink("https://www.amazon.com");
```

This function returns `syntheticsLinkObject`

Useful function definitions:

 **withUrl(*url*)** 

` url ` is a URL string. This function returns `syntheticsLinkObject`

 **withText(*text*)** 

` text ` is a string representing anchor text. This function returns `syntheticsLinkObject`. It adds anchor text corresponding to the link.

 **withParentUrl(*parentUrl*)** 

` parentUrl ` is a string representing the parent (source page) URL. This function returns `syntheticsLink Object`

 **withStatusCode(*statusCode*)** 

` statusCode ` is a string representing the status code. This function returns `syntheticsLinkObject`

 **withFailureReason(*failureReason*)** 

` failureReason ` is a string representing the failure reason. This function returns `syntheticsLink Object`

 **addScreenshotResult(*screenshotResult*)** 

` screenshotResult ` is an object. It is an instance of `ScreenshotResult` that was returned by the Synthetics function `takeScreenshot`. The object includes the following:
+ `fileName`— A string representing the ` screenshotFileName`
+ `pageUrl` (optional)
+ `error` (optional)

## Node.js library classes and functions that apply to API canaries only
<a name="CloudWatch_Synthetics_Library_APIcanaries"></a>

The following CloudWatch Synthetics library functions for Node.js are useful only for API canaries.

**Topics**
+ [executeHttpStep(stepName, requestOptions, [callback], [stepConfig])](#CloudWatch_Synthetics_Library_executeHttpStep)

### executeHttpStep(stepName, requestOptions, [callback], [stepConfig])
<a name="CloudWatch_Synthetics_Library_executeHttpStep"></a>

Executes the provided HTTP request as a step, and publishes `SuccessPercent` (pass/fail) and `Duration` metrics.

**executeHttpStep** uses either HTTP or HTTPS native functions under the hood, depending upon the protocol specified in the request.

This function also adds a step execution summary to the canary's report. The summary includes details about each HTTP request, such as the following:
+ Start time
+ End time
+ Status (PASSED/FAILED)
+ Failure reason, if it failed
+ HTTP call details such as request/response headers, body, status code, status message, and performance timings. 

**Topics**
+ [Parameters](#CloudWatch_Synthetics_Library_executeHttpStep_parameters)
+ [Examples of using executeHttpStep](#CloudWatch_Synthetics_Library_executeHttpStep_examples)

#### Parameters
<a name="CloudWatch_Synthetics_Library_executeHttpStep_parameters"></a>

 **stepName(*String*)** 

Specifies the name of the step. This name is also used for publishing CloudWatch metrics for this step.

 **requestOptions(*Object or String*)** 

The value of this parameter can be a URL, a URL string, or an object. If it is an object, then it must be a set of configurable options to make an HTTP request. It supports all options in [ http.request(options[, callback])](https://nodejs.org/api/http.html#http_http_request_options_callback) in the Node.js documentation.

In addition to these Node.js options, **requestOptions** supports the additional parameter `body`. You can use the `body` parameter to pass data as a request body.

 **callback(*response*)** 

(Optional) This is a user function which is invoked with the HTTP response. The response is of the type [ Class: http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage).

 **stepConfig(*object*)** 

(Optional) Use this parameter to override global synthetics configurations with a different configuration for this step.

#### Examples of using executeHttpStep
<a name="CloudWatch_Synthetics_Library_executeHttpStep_examples"></a>

The following series of examples build on each other to illustrate the various uses of this option.

This first example configures request parameters. You can pass a URL as ** requestOptions**:

```
let requestOptions = 'https://www.amazon.com';
```

Or you can pass a set of options:

```
let requestOptions = {
        'hostname': 'myproductsEndpoint.com',
        'method': 'GET',
        'path': '/test/product/validProductName',
        'port': 443,
        'protocol': 'https:'
    };
```

The next example creates a callback function which accepts a response. By default, if you do not specify **callback**, CloudWatch Synthetics validates that the status is between 200 and 299 inclusive.

```
// Handle validation for positive scenario
    const callback = async function(res) {
        return new Promise((resolve, reject) => {
            if (res.statusCode < 200 || res.statusCode > 299) {
                throw res.statusCode + ' ' + res.statusMessage;
            }
     
            let responseBody = '';
            res.on('data', (d) => {
                responseBody += d;
            });
     
            res.on('end', () => {
                // Add validation on 'responseBody' here if required. For ex, your status code is 200 but data might be empty
                resolve();
            });
        });
    };
```

The next example creates a configuration for this step that overrides the global CloudWatch Synthetics configuration. The step configuration in this example allows request headers, response headers, request body (post data), and response body in your report and restrict 'X-Amz-Security-Token' and 'Authorization' header values. By default, these values are not included in the report for security reasons. If you choose to include them, the data is only stored in your S3 bucket.

```
// By default headers, post data, and response body are not included in the report for security reasons. 
// Change the configuration at global level or add as step configuration for individual steps
let stepConfig = {
    includeRequestHeaders: true, 
    includeResponseHeaders: true,
    restrictedHeaders: ['X-Amz-Security-Token', 'Authorization'], // Restricted header values do not appear in report generated.
    includeRequestBody: true,
    includeResponseBody: true
};
```

This final example passes your request to **executeHttpStep** and names the step.

```
await synthetics.executeHttpStep('Verify GET products API', requestOptions, callback, stepConfig);
```

With this set of examples, CloudWatch Synthetics adds the details from each step in your report and produces metrics for each step using **stepName**.

 You will see `successPercent` and `duration` metrics for the `Verify GET products API` step. You can monitor your API performance by monitoring the metrics for your API call steps. 

For a sample complete script that uses these functions, see [Multi-step API canary](CloudWatch_Synthetics_Canaries_Samples.md#CloudWatch_Synthetics_Canaries_Samples_APIsteps).

# Library functions available for Python canary scripts using Selenium
<a name="CloudWatch_Synthetics_Canaries_Library_Python"></a>

This section lists the Selenium library functions available for Python canary scripts.

**Topics**
+ [Python and Selenium library classes and functions that apply to all canaries](#CloudWatch_Synthetics_Library_allcanaries_Python)
+ [Python and Selenium library classes and functions that apply to UI canaries only](#CloudWatch_Synthetics_Library_Python_UIcanaries)

## Python and Selenium library classes and functions that apply to all canaries
<a name="CloudWatch_Synthetics_Library_allcanaries_Python"></a>

The following CloudWatch Synthetics Selenium library functions for Python are useful for all canaries.

**Topics**
+ [SyntheticsConfiguration class](#CloudWatch_Synthetics_Library_SyntheticsConfiguration_Python)
+ [SyntheticsLogger class](#CloudWatch_Synthetics_Library_SyntheticsLogger_Python)

### SyntheticsConfiguration class
<a name="CloudWatch_Synthetics_Library_SyntheticsConfiguration_Python"></a>

You can use the SyntheticsConfiguration class to configure the behavior of Synthetics library functions. For example, you can use this class to configure the ` executeStep()` function to not capture screenshots.

You can set CloudWatch Synthetics configurations at the global level.

Function definitions:

#### set\$1config(options)
<a name="CloudWatch_Synthetics_Library_setConfig_Python"></a>

```
from aws_synthetics.common import synthetics_configuration
```

` options ` is an object, which is a set of configurable options for your canary. The following sections explain the possible fields in ` options `.
+ `screenshot_on_step_start` (boolean)— Whether to take a screenshot before starting a step.
+ `screenshot_on_step_success` (boolean)— Whether to take a screenshot after completing a successful step.
+ `screenshot_on_step_failure` (boolean)— Whether to take a screenshot after a step fails.

 **with\$1screenshot\$1on\$1step\$1start(screenshot\$1on\$1step\$1start)** 

Accepts a Boolean argument, which indicates whether to take a screenshot before starting a step.

 **with\$1screenshot\$1on\$1step\$1success(screenshot\$1on\$1step\$1success)** 

Accepts a Boolean argument, which indicates whether to take a screenshot after completing a step successfully.

 **with\$1screenshot\$1on\$1step\$1failure(screenshot\$1on\$1step\$1failure)** 

Accepts a Boolean argument, which indicates whether to take a screenshot after a step fails.

 **get\$1screenshot\$1on\$1step\$1start()** 

Returns whether to take a screenshot before starting a step.

 **get\$1screenshot\$1on\$1step\$1success()** 

Returns whether to take a screenshot after completing a step successfully.

 **get\$1screenshot\$1on\$1step\$1failure()** 

Returns whether to take a screenshot after a step fails.

 **disable\$1step\$1screenshots()** 

Disables all screenshot options (get\$1screenshot\$1on\$1step\$1start, get\$1screenshot\$1on\$1step\$1success, and get\$1screenshot\$1on\$1step\$1failure).

 **enable\$1step\$1screenshots()** 

Enables all screenshot options (get\$1screenshot\$1on\$1step\$1start, get\$1screenshot\$1on\$1step\$1success, and get\$1screenshot\$1on\$1step\$1failure). By default, all these methods are enabled.

 **setConfig(options) regarding CloudWatch metrics** 

For canaries using `syn-python-selenium-1.1` or later, the ** (options)** for **setConfig** can include the following Boolean parameters that determine which metrics are published by the canary. The default for each of these options is `true`. The options that start with ` aggregated` determine whether the metric is emitted without the ` CanaryName` dimension. You can use these metrics to see the aggregated results for all of your canaries. The other options determine whether the metric is emitted with the `CanaryName` dimension. You can use these metrics to see results for each individual canary.

For a list of CloudWatch metrics emitted by canaries, see [CloudWatch metrics published by canaries](CloudWatch_Synthetics_Canaries_metrics.md).
+ `failed_canary_metric` (boolean)— Whether to emit the ` Failed` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `failed_requests_metric` (boolean)— Whether to emit the `Failed requests` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `2xx_metric` (boolean)— Whether to emit the `2xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `4xx_metric` (boolean)— Whether to emit the `4xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `5xx_metric` (boolean)— Whether to emit the `5xx` metric (with the `CanaryName` dimension) for this canary. The default is `true`.
+ `step_duration_metric` (boolean)— Whether to emit the `Step duration` metric (with the `CanaryName` `StepName` dimensions) for this canary. The default is `true`.
+ `step_success_metric` (boolean)— Whether to emit the `Step success` metric (with the `CanaryName` `StepName` dimensions) for this canary. The default is `true`.
+ `aggregated_failed_canary_metric` (boolean)— Whether to emit the `Failed` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated_failed_requests_metric` (boolean)— Whether to emit the `Failed Requests` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated_2xx_metric` (boolean)— Whether to emit the ` 2xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated_4xx_metric` (boolean)— Whether to emit the ` 4xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.
+ `aggregated_5xx_metric` (boolean)— Whether to emit the ` 5xx` metric (without the `CanaryName` dimension) for this canary. The default is `true`.

 **with\$12xx\$1metric(2xx\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `2xx` metric with the `CanaryName` dimension for this canary.

 **with\$14xx\$1metric(4xx\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `4xx` metric with the `CanaryName` dimension for this canary.

 **with\$15xx\$1metric(5xx\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `5xx` metric with the `CanaryName` dimension for this canary.

 **withAggregated2xxMetric(aggregated2xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `2xx` metric with no dimension for this canary.

 **withAggregated4xxMetric(aggregated4xxMetric)** 

Accepts a Boolean argument, which specifies whether to emit a `4xx` metric with no dimension for this canary.

 **with\$1aggregated\$15xx\$1metric(aggregated\$15xx\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `5xx` metric with no dimension for this canary.

 ** with\$1aggregated\$1failed\$1canary\$1metric(aggregated\$1failed\$1canary\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed` metric with no dimension for this canary.

 ** with\$1aggregated\$1failed\$1requests\$1metric(aggregated\$1failed\$1requests\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed requests` metric with no dimension for this canary.

 **with\$1failed\$1canary\$1metric(failed\$1canary\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed` metric with the `CanaryName` dimension for this canary.

 **with\$1failed\$1requests\$1metric(failed\$1requests\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `Failed requests` metric with the `CanaryName` dimension for this canary.

 **with\$1step\$1duration\$1metric(step\$1duration\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `Duration` metric with the `CanaryName` dimension for this canary.

 **with\$1step\$1success\$1metric(step\$1success\$1metric)** 

Accepts a Boolean argument, which specifies whether to emit a `StepSuccess` metric with the `CanaryName` dimension for this canary.

##### Methods to enable or disable metrics
<a name="CloudWatch_Synthetics_Python_setConfig_metrics"></a>

 **disable\$1aggregated\$1request\$1metrics()** 

Disables the canary from emitting all request metrics that are emitted with no ` CanaryName` dimension.

 **disable\$1request\$1metrics()** 

Disables all request metrics, including both per-canary metrics and metrics aggregated across all canaries.

 **disable\$1step\$1metrics()** 

Disables all step metrics, including both step success metrics and step duration metrics.

 **enable\$1aggregated\$1request\$1metrics()** 

Enables the canary to emit all request metrics that are emitted with no ` CanaryName` dimension.

 **enable\$1request\$1metrics()** 

Enables all request metrics, including both per-canary metrics and metrics aggregated across all canaries.

 **enable\$1step\$1metrics()** 

Enables all step metrics, including both step success metrics and step duration metrics.

 **Usage in UI canaries** 

First, import the synthetics dependency and fetch the configuration. Then, set the configuration for each option by calling the setConfig method using one of the following options.

```
from aws_synthetics.common import synthetics_configuration

synthetics_configuration.set_config(
     {
        "screenshot_on_step_start": False,
        "screenshot_on_step_success": False,
        "screenshot_on_step_failure": True
     }
)

or
```

Or

```
synthetics_configuration.with_screenshot_on_step_start(False).with_screenshot_on_step_success(False).with_screenshot_on_step_failure(True)
```

To disable all screenshots, use the disableStepScreenshots() function as in this example.

```
synthetics_configuration.disable_step_screenshots()
```

You can enable and disable screenshots at any point in the code. For example, to disable screenshots only for one step, disable them before running that step and then enable them after the step.

##### set\$1config(options) for UI canaries
<a name="CloudWatch_Synthetics_Library_Python_UI"></a>

Starting with `syn-python-selenium-1.1`, for UI canaries, ` set_config` can include the following Boolean parameters:
+ `continue_on_step_failure` (boolean)— Whether to continue with running the canary script after a step fails (this refers to the ** executeStep** function). If any steps fail, the canary run will still be marked as failed. The default is `false`.

### SyntheticsLogger class
<a name="CloudWatch_Synthetics_Library_SyntheticsLogger_Python"></a>

`synthetics_logger` writes logs out to both the console and to a local log file at the same log level. This log file is written to both locations only if the log level is at or below the desired logging level of the log function that was called.

The logging statements in the local log file are prepended with "DEBUG: ", "INFO: ", and so on to match the log level of the function that was called.

Using `synthetics_logger` is not required to create a log file that is uploaded to your Amazon S3 results location. You could instead create a different log file in the `/tmp` folder. Any files created under the `/tmp` folder are uploaded to the results location in the S3 bucket as artifacts.

To use `synthetics_logger`:

```
from aws_synthetics.common import synthetics_logger
```

****Useful function definitions:

Get log level:

```
log_level = synthetics_logger.get_level()
```

Set log level:

```
synthetics_logger.set_level()
```

Log a message with a specified level. The level can be `DEBUG`, ` INFO`, `WARN`, or `ERROR`, as in the following syntax examples:

```
synthetics_logger.debug(message, *args, **kwargs)
```

```
synthetics_logger.info(message, *args, **kwargs)
```

```
synthetics_logger.log(message, *args, **kwargs)
```

```
synthetics_logger.warning(message, *args, **kwargs)
```

```
synthetics_logger.error(message, *args, **kwargs)
```

For information about debug parameters, see the standard Python documentation at [logging.debug](https://docs.python.org/3/library/logging.html#logging.debug)

In these logging functions, the `message` is the message format string. The `args` are the arguments that are merged into `msg` using the string formatting operator.

There are three keyword arguments in `kwargs`:
+ `exc_info`– If not evaluated as false, adds exception information to the logging message.
+ `stack_info`– defaults to false. If true, adds stack information to the logging message, including the actual logging call.
+ `extra`– The third optional keyword argument, which you can use to pass in a dictionary that is used to populate the `__dict__` of the `LogRecord` created for the logging event with user-defined attributes.

Examples:

Log a message with the level `DEBUG`:

```
synthetics_logger.debug('Starting step - login.')
```

Log a message with the level `INFO`. `logger.log` is a synonym for `logger.info`:

```
synthetics_logger.info('Successfully completed step - login.')
```

or

```
synthetics_logger.log('Successfully completed step - login.')
```

Log a message with the level `WARN`:

```
synthetics_logger.warning('Warning encountered trying to publish %s', 'CloudWatch Metric')
```

Log a message with the level `ERROR`:

```
synthetics_logger.error('Error encountered trying to publish %s', 'CloudWatch Metric')
```

Log an exception:

```
synthetics_logger.exception(message, *args, **kwargs)
```

Logs a message with level `ERROR`. Exception information is added to the logging message. You should call this function only from an exception handler.

For information about exception parameters, see the standard Python documentation at [ logging.exception](https://docs.python.org/3/library/logging.html#logging.exception)

The `message` is the message format string. The `args` are the arguments, which are merged into `msg` using the string formatting operator.

There are three keyword arguments in `kwargs`:
+ `exc_info`– If not evaluated as false, adds exception information to the logging message.
+ `stack_info`– defaults to false. If true, adds stack information to the logging message, including the actual logging call.
+ `extra`– The third optional keyword argument, which you can use to pass in a dictionary that is used to populate the `__dict__` of the `LogRecord` created for the logging event with user-defined attributes.

Example:

```
synthetics_logger.exception('Error encountered trying to publish %s', 'CloudWatch Metric')
```

## Python and Selenium library classes and functions that apply to UI canaries only
<a name="CloudWatch_Synthetics_Library_Python_UIcanaries"></a>

The following CloudWatch Synthetics Selenium library functions for Python are useful only for UI canaries.

**Topics**
+ [SyntheticsBrowser class](#CloudWatch_Synthetics_Library_Python_SyntheticsBrowser)
+ [SyntheticsWebDriver class](#CloudWatch_Synthetics_Library_Python_SyntheticsWebDriver)

### SyntheticsBrowser class
<a name="CloudWatch_Synthetics_Library_Python_SyntheticsBrowser"></a>

**Note**  
`SyntheticsBrowser` is supported only on the Chrome browser.

When you create a browser instance by calling `synthetics_webdriver.Chrome()`, the returned browser instance is of the type `SyntheticsBrowser`. The ` SyntheticsBrowser` class inherits the WebDriver class and provides access to all the methods exposed by the [WebDriver](https://www.selenium.dev/documentation/webdriver/). It controls the ChromeDriver, and enables the canary script to drive the browser, allowing the Selenium WebDriver to work with Synthetics.

**Note**  
Synthetics overrides the WebDriver [ quit](https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_firefox/selenium.webdriver.firefox.webdriver.html) method to take no action. You don't need to worry about quitting the browser, as Synthetics handles that for you.

In addition to the standard Selenium methods, it also provides the following methods. 

**Topics**
+ [set\$1viewport\$1size(width, height)](#CloudWatch_Synthetics_Library_set_viewport_size)
+ [save\$1screenshot(filename, suffix)](#CloudWatch_Synthetics_Library_save_screenshot)

#### set\$1viewport\$1size(width, height)
<a name="CloudWatch_Synthetics_Library_set_viewport_size"></a>

Sets the viewport of the browser. Example:

```
browser.set_viewport_size(1920, 1080)
```

#### save\$1screenshot(filename, suffix)
<a name="CloudWatch_Synthetics_Library_save_screenshot"></a>

Saves screenshots to the `/tmp` directory. The screenshots are uploaded from there to the canary artifacts folder in the S3 bucket.

*filename* is the file name for the screenshot, and * suffix* is an optional string to be used for naming the screenshot.

Example:

```
browser.save_screenshot('loaded.png', 'page1')
```

### SyntheticsWebDriver class
<a name="CloudWatch_Synthetics_Library_Python_SyntheticsWebDriver"></a>

To use this class, use the following in your script:

```
from aws_synthetics.selenium import synthetics_webdriver
```

**Topics**
+ [add\$1execution\$1error(errorMessage, ex);](#CloudWatch_Synthetics_Library_Python_addExecutionError)
+ [add\$1user\$1agent(user\$1agent\$1str)](#CloudWatch_Synthetics_Library_add_user_agent)
+ [execute\$1step(step\$1name, function\$1to\$1execute)](#CloudWatch_Synthetics_Library_Python_execute_step)
+ [get\$1http\$1response(url)](#CloudWatch_Synthetics_Library_Python_get_http_response)
+ [Chrome()](#CloudWatch_Synthetics_Library_Python_Chrome)

#### add\$1execution\$1error(errorMessage, ex);
<a name="CloudWatch_Synthetics_Library_Python_addExecutionError"></a>

`errorMessage` describes the error and `ex` is the exception that is encountered

You can use `add_execution_error` to set execution errors for your canary. It fails the canary without interrupting the script execution. It also doesn't impact your `successPercent` metrics.

You should track errors as execution errors only if they are not important to indicate the success or failure of your canary script.

An example of the use of `add_execution_error` is the following. You are monitoring the availability of your endpoint and taking screenshots after the page has loaded. Because the failure of taking a screenshot doesn't determine availability of the endpoint, you can catch any errors encountered while taking screenshots and add them as execution errors. Your availability metrics will still indicate that the endpoint is up and running, but your canary status will be marked as failed. The following sample code block catches such an error and adds it as an execution error.

```
try:
    browser.save_screenshot("loaded.png")  
except Exception as ex:
   self.add_execution_error("Unable to take screenshot", ex)
```

#### add\$1user\$1agent(user\$1agent\$1str)
<a name="CloudWatch_Synthetics_Library_add_user_agent"></a>

Appends the value of `user_agent_str` to the browser's user agent header. You must assign `user_agent_str` before creating the browser instance.

Example:

```
await synthetics_webdriver.add_user_agent('MyApp-1.0')
```

`add_user_agent` should be used inside an `async` function.

#### execute\$1step(step\$1name, function\$1to\$1execute)
<a name="CloudWatch_Synthetics_Library_Python_execute_step"></a>

Processes one function. It also does the following:
+ Logs that the step started.
+ Takes a screenshot named `<stepName>-starting`.
+ Starts a timer.
+ Executes the provided function.
+ If the function returns normally, it counts as passing. If the function throws, it counts as failing.
+ Ends the timer.
+ Logs whether the step passed or failed
+ Takes a screenshot named `<stepName>-succeeded` or ` <stepName>-failed`.
+ Emits the `stepName` `SuccessPercent` metric, 100 for pass or 0 for failure.
+ Emits the `stepName` `Duration` metric, with a value based on the step start and end times.
+ Finally, returns what the `functionToExecute` returned or re-throws what `functionToExecute` threw.

Example:

```
from selenium.webdriver.common.by import By

def custom_actions():
        #verify contains
        browser.find_element(By.XPATH, "//*[@id=\"id_1\"][contains(text(),'login')]")
        #click a button
        browser.find_element(By.XPATH, '//*[@id="submit"]/a').click()

    await synthetics_webdriver.execute_step("verify_click", custom_actions)
```

#### get\$1http\$1response(url)
<a name="CloudWatch_Synthetics_Library_Python_get_http_response"></a>

Makes an HTTP request to the provided URL and returns the response code of the HTTP request. If an exception occurred during the HTTP request, a string with value "error" is returned instead.

Example:

```
response_code = syn_webdriver.get_http_response(url)
if not response_code or response_code == "error" or response_code < 200 or response_code > 299:
    raise Exception("Failed to load page!")
```

#### Chrome()
<a name="CloudWatch_Synthetics_Library_Python_Chrome"></a>

Launches an instance of the Chromium browser and returns the created instance of the browser.

Example:

```
browser = synthetics_webdriver.Chrome()
browser.get("https://example.com/)
```

To launch a browser in incognito mode, use the following:

```
add_argument('——incognito')
```

To add proxy settings, use the following:

```
add_argument('--proxy-server=%s' % PROXY)
```

Example:

```
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("——incognito")
browser = syn_webdriver.Chrome(chrome_options=chrome_options)
```

# Scheduling canary runs using cron
<a name="CloudWatch_Synthetics_Canaries_cron"></a>

Using a cron expression gives you flexibility when you schedule a canary. Cron expressions contain five or six fields in the order listed in the following table. The fields are separated by spaces. The syntax differs depending on whether you are using the CloudWatch console to create the canary, or the AWS CLI or AWS SDKs. When you use the console, you specify only the first five fields. When you use the AWS CLI or AWS SDKs, you specify all six fields, and you must specify `*` for the `Year` field.


|  **Field**  |  **Allowed values**  |  **Allowed special characters**  | 
| --- | --- | --- | 
|  Minutes  |  0-59  |  , - \$1 /  | 
|  Hours  |  0-23  |  , - \$1 /  | 
|  Day-of-month  |  1-31  |  , - \$1 ? / L W  | 
|  Month  |  1-12 or JAN-DEC  |  , - \$1 /  | 
|  Day-of-week  |  1-7 or SUN-SAT  |  , - \$1 ? L \$1  | 
|  Year  |  \$1  |    | 

**Special characters**
+ The **,** (comma) includes multiple values in the expression for a field. For example, in the Month field, JAN,FEB,MAR would include January, February, and March.
+ The **-** (dash) special character specifies ranges. In the Day field, 1-15 would include days 1 through 15 of the specified month.
+ The **\$1** (asterisk) special character includes all values in the field. In the Hours field, **\$1** includes every hour. You cannot use ** \$1** in both the Day-of-month and Day-of-week fields in the same expression. If you use it in one, you must use **?** in the other.
+ The **/** (forward slash) specifies increments. In the Minutes field, you can enter 1/10 to specify every tenth minute, starting from the first minute of the hour (for example, the eleventh, twenty-first, and thirty-first minute, and so on).
+ The **?** (question mark) specifies one or another. If you enter ** 7** in the Day-of-month field and you don't care what day of the week the seventh is, you can enter **?** in the Day-of-week field.
+ The **L** wildcard in the Day-of-month or Day-of-week fields specifies the last day of the month or week.
+ The **W** wildcard in the Day-of-month field specifies a weekday. In the Day-of-month field, **3W** specifies the weekday closest to the third day of the month.
+ The **\$1** wildcard in the Day-of-week field specifies a certain instance of the specified day of the week within a month. For example, 3\$12 is the second Tuesday of the month. The 3 refers to Tuesday because it is the third day of each week, and the 2 refers to the second day of that type within the month.

**Limitations**
+ You can't specify the Day-of-month and Day-of-week fields in the same cron expression. If you specify a value or `*` (asterisk) in one of the fields, you must use a **?** (question mark) in the other.
+ Cron expressions that lead to rates faster than one minute are not supported.
+ You can't set a canary to wait for more than a year before running, so you can specify only `*` in the `Year` field.

**Examples**  
You can refer to the following sample cron strings when you create a canary. The following examples are the correct syntax for using the AWS CLI or AWS SDKs to create or update a canary. If you are using the CloudWatch console, omit the final `*` in each example.


| Expression | Meaning | 
| --- | --- | 
|   `0 10 * * ? *`   |  Run at 10:00 am (UTC) every day  | 
|   `15 12 * * ? *`   |  Run at 12:15 pm (UTC) every day  | 
|   `0 18 ? * MON-FRI *`   |  Run at 6:00 pm (UTC) every Monday through Friday  | 
|   `0 8 1 * ? *`   |  Run at 8:00 am (UTC) on the first day of each month  | 
|   `0/10 * ? * MON-SAT *`   |  Run every 10 minutes Monday through Saturday of each week  | 
|   `0/5 8-17 ? * MON-FRI *`   |  Run every five minutes Monday through Friday between 8:00 am and 5:55 pm (UTC)   | 

# Configuring your canary to retry automatically
<a name="CloudWatch_Synthetics_Canaries_autoretry"></a>

When you create or update a canary, you can configure your canaries to automatically attempt additional runs when the scheduled one fails. This helps differentiate between genuine failures and temporary glitches, providing more reliable results. This feature is ideal for building more resilient monitoring systems while reducing false alarms and manual intervention.

**To create a auto retry canary**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. In the navigation pane, choose **Application Signals**, **Synthetics Canaries**.

1. Choose **Create Canary**.

1. Under **Additional configuration**, **Auto-retry,** select the desired maximum retry number.

**To update the maximum retry number for a canary**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. In the navigation pane, choose **Application Signals**, **Synthetics Canaries**.

1. You can do one of the following:
   + Select the canary and choose **Actions**, **Enable auto-retry**, and adjust the maximum retries.
   + Select the canary and choose **Actions**, **Edit**. In the **Edit detail** page, under **Additional configuration**, **Auto-retry**, adjust the retry configuration.

 **Limitations** 

Here are the limitations to configure auto retry.
+ Supported only on runtime versions `syn-nodejs-puppeteer-10.0 `or newer, ` syn-nodejs-playwright-2.0` or newer, or `syn-python-selenium-5.1` or newer, or `syn-nodejs-3.0` or newer.
+ Long running canaries which timeout after ten minutes are limited to one retry. All other canaries can support upto two retries

# Using dependencies with CloudWatch Synthetics canaries
<a name="CloudWatch_Synthetics_Canaries_dependencies"></a>

This section explains how to use `Dependencies` in CloudWatch Synthetics canaries. The `Dependencies` field allows you to specify dependencies for your canaries, enabling you to include additional libraries or custom code that your canary scripts can use.

## Overview
<a name="overview"></a>

CloudWatch Synthetics canaries support specifying Lambda layers as dependencies. This feature allows you to:
+ Share common code across multiple canaries
+ Manage dependencies separately from your canary script code
+ Reduce the size of your canary script by moving dependencies to a Lambda layer

## Supported APIs
<a name="supported-apis"></a>

The `Dependencies` field is supported in the following APIs:
+  [CreateCanary](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_CreateCanary.html) 
+  [UpdateCanary](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_UpdateCanary.html) 
+  [ StartCanaryDryRun](https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_StartCanaryDryRun.html) 

## Syntax
<a name="syntax"></a>

The `Dependencies` field is part of the code structure in the request syntax:

```
"Code": { 
  "Handler": "string",
  "S3Bucket": "string",
  "S3Key": "string",
  "S3Version": "string",
  "ZipFile": blob,
  "Dependencies": [
    {
      "Type": "LambdaLayer",
      "Reference": "string"
    }
  ]
}
```

## Using dependencies
<a name="usage"></a>

Here are some examples and instructions for using the `Dependencies` field in different scenarios.

### Creating a Canary with dependencies
<a name="creating-canary"></a>

When creating a canary, you can specify a Lambda layer as a dependency:

```
{
  "Name": "my-canary",
  "Code": {
    "Handler": "pageLoadBlueprint.handler",
    "S3Bucket": "my-bucket",
    "S3Key": "my-canary-script.zip",
    "Dependencies": [
      {
        "Type": "LambdaLayer",
        "Reference": "arn:aws:lambda:us-west-2:123456789012:layer:my-custom-layer:1"
      }
    ]
  },
  "ArtifactS3Location": "s3://my-bucket/artifacts/",
  "ExecutionRoleArn": "arn:aws:iam::123456789012:role/my-canary-role",
  "Schedule": {
    "Expression": "rate(5 minutes)"
  },
  "RuntimeVersion": "syn-nodejs-puppeteer-3.9"
}
```

### Updating a Canary's dependencies
<a name="updating-canary"></a>

You can update a canary's dependencies using the UpdateCanary API:

```
{
  "Name": "my-canary",
  "Code": {
    "Dependencies": [
      {
        "Type": "LambdaLayer",
        "Reference": "arn:aws:lambda:us-west-2:123456789012:layer:my-updated-layer:2"
      }
    ]
  }
}
```

### Removing dependencies
<a name="removing-dependencies"></a>

To remove dependencies from a canary, provide an empty array for the Dependencies field:

```
{
  "Name": "my-canary",
  "Code": {
    "Dependencies": []
  }
}
```

### Testing dependencies with StartCanaryDryRun
<a name="testing-dependencies"></a>

Before updating a canary with new dependencies, you can test them using the StartCanaryDryRun API:

```
{
  "Name": "my-canary",
  "Code": {
    "Dependencies": [
      {
        "Type": "LambdaLayer",
        "Reference": "arn:aws:lambda:us-west-2:123456789012:layer:my-test-layer:3"
      }
    ]
  }
}
```

## Limitations and considerations
<a name="limitations"></a>
+ Only one Lambda layer can be specified as a dependency
+ The role being used to create a canary with dependencies should have ` lambda:GetLayerVersion` access to the dependency layer in addition to the [necessary roles and permissions](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Roles.html)

## Creating compatible Lambda layers
<a name="creating-compatible-layers"></a>

For information on how to create and package layers, see [Managing Lambda dependencies with layers ](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html) and to understand the packaging structure of a canary check based on the canary packing structure, see [Writing a canary script](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_WritingCanary.html).