

# CloudWatch RUM
<a name="CloudWatch-RUM"></a>

With CloudWatch RUM, you can perform real user monitoring to collect and view client-side data about your web and mobile application performance from actual user sessions in near real time. For Web applications, you can analyze page load times, client-side errors, and user behavior. For Mobile applications, you can monitor screen load times, app launch times, network errors, crashes, and platform-specific issues such as Android Application Not Responding (ANR) and iOS App Hangs. When you view this data, you can see it all aggregated together and also see breakdowns by device types, operating systems, and other characteristics of your application usage.

You can use the collected data to quickly identify and debug client-side performance issues. CloudWatch RUM helps you visualize anomalies in your application performance and find relevant debugging data such as error messages, stack traces, and user sessions. You can also use RUM to understand the range of end user impact including the number of users, geolocations, and browsers/devices used.

End user data that you collect for CloudWatch RUM is retained for 30 days and then automatically deleted. If you want to keep the RUM telemetry data for a longer time, you can choose to have the app monitor send copies of the telemetry to CloudWatch Logs in your account. Then, you can adjust the retention period for that log group.

To use RUM, you create an *app monitor* and provide some information. RUM generates a code snippet that you can use to add a dependency injection into your application. The snippet pulls in the RUM client code as needed. The RUM client captures data from a percentage of your application's user sessions, which is displayed in a pre-built dashboard. You can specify what percentage of user sessions to gather data from.

 CloudWatch RUM is integrated with [Application Signals](CloudWatch-Application-Monitoring-Sections.md), which can discover and monitor your application services, clients, Synthetics canaries, and service dependencies. Use Application Signals to see a list or visual map of your services, view health metrics based on your service level objectives (SLOs), and drill down to see correlated X-Ray traces for more detailed troubleshooting. To see RUM client page requests in Application Signals, turn on X-Ray active tracing when [creating an app monitor](CloudWatch-RUM-get-started-create-app-monitor.md). For web applications, you can also enable this by [manually configuring the RUM web client](CloudWatch-RUM-configure-client.md). Your RUM clients are displayed on the [Application Map](ServiceMap.md) connected to your services, and in the [Service detail](ServiceDetail.md) page of the services they call. 

The RUM clients are open source. For more information, see [CloudWatch RUM web client](https://github.com/aws-observability/aws-rum-web), the [AWS Distro for OpenTelemetry (ADOT) Android SDK](https://github.com/aws-observability/aws-otel-android), and [AWS Distro for OpenTelemetry (ADOT) iOS SDK](https://github.com/aws-observability/aws-otel-swift).

**RUM Pricing**

For information about pricing, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/). 

**Region availability**

CloudWatch RUM is currently available in the following Regions:
+ US East (N. Virginia)
+ US East (Ohio)
+ US West (N. California)
+ US West (Oregon)
+ Africa (Cape Town)
+ AWS GovCloud (US-East)
+ AWS GovCloud (US-West)
+ Asia Pacific (Mumbai)
+ Asia Pacific (Hyderabad)
+ Asia Pacific (Melbourne)
+ Asia Pacific (Osaka)
+ Asia Pacific (Seoul)
+ Asia Pacific (Singapore)
+ Asia Pacific (Sydney)
+ Asia Pacific (Jakarta)
+ Asia Pacific (Malaysia)
+ Asia Pacific (Thailand)
+ Asia Pacific (Tokyo)
+ Asia Pacific (Hong Kong)
+ Canada (Central)
+ Europe (Frankfurt)
+ Europe (Ireland)
+ Europe (London)
+ Europe (Milan)
+ Europe (Paris)
+ Europe (Spain)
+ Europe (Stockholm)
+ Europe (Zurich)
+ AWS European Sovereign Cloud (Germany)
+ Middle East (Bahrain)
+ Middle East (UAE)
+ Mexico (Central)
+ South America (São Paulo)
+ Israel (Tel Aviv)
+ Canada West (Calgary)

# Set up a mobile application to use CloudWatch RUM
<a name="CloudWatch-RUM-web-mobile"></a>

To monitor mobile applications, you create an app monitor, configure it for mobile platforms, and integrate the AWS Distro for OpenTelemetry (ADOT) SDK into your application. Mobile RUM uses the OpenTelemetry Protocol (OTLP) to send telemetry data to a dedicated OTLP endpoint. 

## To create an app monitor for a mobile platform
<a name="mobile-platform-app-monitor"></a>

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**, **RUM**.

1. Choose **Add app monitor**.

1. For **App monitor name**, enter a name to be used to identify this app monitor within the CloudWatch RUM console.

1. Select **Android** or **iOS** as the platform.

1. Under **Data storage**, you can choose to store copies of RUM OTEL log events and spans in CloudWatch Logs and configure retention. By default, the CloudWatch Logs log group retains the data for 30 days. You can adjust the retention period in the CloudWatch Logs console.

1. (Optional) Under **Resource Based Policy**, choose to add a resource-based policy to control who can send requests to your app monitor. If you choose **Create public policy**, a resource policy will be attached that enables anyone to send requests to your app monitor. For more information, see [Using resource-based policies with CloudWatch RUM](CloudWatch-RUM-resource-policies.md).

1. To enable AWS X-Ray tracing of sampled user sessions, choose **Active tracing** and select **Trace my service with AWS X-Ray**.

   If selected, OTEL spans generated during sampled user sessions are traced. You can then see traces and spans from these sessions in the RUM dashboard, and the X-Ray trace map and trace details pages. These user sessions will also show up as client pages in Application Signals after you have enabled it for your application.

1. (Optional) To add tags to the app monitor:

   1. Choose **Tags**, **Add new tag**.

   1. For **Key**, enter a name for the tag. You can add an optional value in **Value**.

   1. To add another tag, choose **Add new tag** again.

   For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/tagging/latest/userguide/tagging-resources.html) in the *AWS Tagging and Tag Editor User Guide*.

1. Choose **Add app monitor**.

1. In the **Sample code** section, you can copy the code snippet to add to your application. Using the AWS Distro for OpenTelemetry (ADOT) SDK, you can choose between **Manual Instrumentation** to configure the monitoring in your application code, or **Zero-Code Instrumentation** which requires minimal configuration changes.

   For both Android and iOS applications, Zero-Code Instrumentation is the simplest option as it automatically initializes telemetry collection using a configuration file. Manual Instrumentation gives you more control over the initialization and configuration process.

1. Choose **Copy** or **Download**, and then choose **Done**.

### iOS Application Setup
<a name="CloudWatch-RUM-ios-setup"></a>

For iOS applications, integrate the [AWS Distro for OpenTelemetry (ADOT) iOS SDK](https://github.com/aws-observability/aws-otel-swift) to enable RUM monitoring. The SDK supports iOS 16 and later versions and provides automatic instrumentation for common performance scenarios.

### Android Application Setup
<a name="CloudWatch-RUM-android-setup"></a>

For Android applications, integrate the [AWS Distro for OpenTelemetry (ADOT) Android SDK](https://github.com/aws-observability/aws-otel-android) to enable RUM monitoring. The SDK provides automatic instrumentation and supports both signed and unsigned authentication models.

## Authentication and Security
<a name="CloudWatch-RUM-authentication"></a>

Mobile RUM supports flexible authentication models as defined in their SDKs.
+ iOS applications use the [AWS Distro for OpenTelemetry (ADOT) iOS SDK](https://github.com/aws-observability/aws-otel-swift). 
+ Android applications use the [AWS Distro for OpenTelemetry (ADOT) Android SDK](https://github.com/aws-observability/aws-otel-android).

# IAM policies to use CloudWatch RUM
<a name="CloudWatch-RUM-permissions"></a>

To be able to fully manage CloudWatch RUM, you must be signed in as an IAM user or role that has the **AmazonCloudWatchRUMFullAccess** IAM policy. Additionally, you may need other policies or permissions:
+ To create an app monitor that creates a new Amazon Cognito identity pool for authorization, you need to have the **Admin** IAM role or the **AdministratorAccess** IAM policy.
+ To create an app monitor that sends data to CloudWatch Logs, you must be logged on to an IAM role or policy that has the following permission:

  ```
  {
      "Effect": "Allow",
      "Action": [
          "logs:PutResourcePolicy"
      ],
      "Resource": [
          "*"
      ]
  }
  ```
+ To enable JavaScript source maps in an app monitor, you will need to upload your source map files to a Amazon S3 bucket. Your IAM role or policy needs specific Amazon S3 permissions that allow creating Amazon S3 buckets, setting bucket policies, and managing files in the bucket. For security, scope these permissions to specific resources. The example policy below restricts access to buckets containing `rum` in their names and uses the `aws:ResourceAccount` condition key to limit permissions to the principal account only.

  ```
  {
      "Sid": "AllowS3BucketCreationAndListing",
      "Effect": "Allow",
      "Action": [
          "s3:CreateBucket",
          "s3:ListAllMyBuckets"
      ],
      "Resource": "arn:aws:s3:::*",
      "Condition": {
          "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
          }
      }
  },
  {
      "Sid": "AllowS3BucketActions",
      "Effect": "Allow",
      "Action": [
          "s3:GetBucketLocation",
          "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::*rum*",
      "Condition": {
          "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
          }
      }
  },
  {
      "Sid": "AllowS3BucketPolicyActions",
      "Effect": "Allow",
      "Action": [
          "s3:PutBucketPolicy",
          "s3:GetBucketPolicy"
      ],
      "Resource": "arn:aws:s3:::*rum*",
      "Condition": {
          "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
          }
      }
  },
  {
      "Sid": "AllowS3ObjectActions",
      "Effect": "Allow",
      "Action": [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject",
          "s3:AbortMultipartUpload"
      ],
      "Resource": "arn:aws:s3:::*rum*",
      "Condition": {
          "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
          }
      }
  }
  ```
+ To use your own AWS KMS keys for server-side encryption on your source map bucket, your IAM role or policy will need specific AWS KMS permissions that allows creating a key, updating the key policy, using the AWS KMS key with Amazon S3 and setting the encryption configuration of your Amazon S3 bucket. For security, scope these permissions to specific purposes. The example below restricts access to keys for a specific region and accountId and has similar S3 restrictions as the above example. 

  ```
  {
      "Sid": "AllowKMSKeyCreation",
      "Effect": "Allow",
      "Action": [
          "kms:CreateKey",
          "kms:CreateAlias"
      ],
      "Resource": "*"
  },
  {
      "Sid": "KMSReadPermissions",
      "Effect": "Allow",
      "Action": [
          "kms:ListAliases"
      ],
      "Resource": "*"
  },
  {
      "Sid": "AllowUpdatingKeyPolicy",
      "Effect": "Allow",
      "Action": [
          "kms:PutKeyPolicy",
          "kms:GetKeyPolicy",
          "kms:ListKeyPolicies"
      ],
      "Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/*"
  },
  {
      "Sid": "AllowUseOfKMSKeyForS3",
      "Effect": "Allow",
      "Action": [
          "kms:DescribeKey",
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:GenerateDataKey"
      ],
      "Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/*"
  },
  {
      "Sid": "AllowS3EncryptionConfiguration",
      "Effect": "Allow",
      "Action": [
          "s3:PutEncryptionConfiguration",
          "s3:GetEncryptionConfiguration"
      ],
      "Resource": "arn:aws:s3:::*rum*",
      "Condition": {
          "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
          }
      }
  }
  ```

Other users who need to view CloudWatch RUM data but don't need to create CloudWatch RUM resources, can be granted the **AmazonCloudWatchRUMReadOnlyAccess** policy.

# Set up a web application to use CloudWatch RUM
<a name="CloudWatch-RUM-get-started"></a>

Use the steps in these sections to set up your web application to begin using CloudWatch RUM to collect performance data from real user sessions.

**Topics**
+ [

# Authorize your web application to send data to AWS
](CloudWatch-RUM-get-started-authorization.md)
+ [

# Creating a CloudWatch RUM app monitor for a web application
](CloudWatch-RUM-get-started-create-app-monitor.md)
+ [

# Modifying the code snippet to configure the CloudWatch RUM web client (optional)
](CloudWatch-RUM-modify-snippet.md)
+ [

# Inserting the CloudWatch app monitor code snippet into your application
](CloudWatch-RUM-get-started-insert-code-snippet.md)
+ [

# Testing your CloudWatch app monitor setup by generating user events
](CloudWatch-RUM-get-started-generate-data.md)

# Authorize your web application to send data to AWS
<a name="CloudWatch-RUM-get-started-authorization"></a>

You have four options to set up data authentication:
+ Use Amazon Cognito and let CloudWatch RUM create a new Amazon Cognito identity pool for the application. This method requires the least effort to set up.

  The identity pool will contain an unauthenticated identity. This allows the CloudWatch RUM web client to send data to CloudWatch RUM without authenticating the user of the application.

  The Amazon Cognito identity pool has an attached IAM role. The Amazon Cognito unauthenticated identity allows the web client to assume the IAM role that is authorized to send data to CloudWatch RUM.
+ Use Amazon Cognito for authentication. If you use this, you can use an existing Amazon Cognito identity pool or create a new one to use with this app monitor. If you use an existing identity pool, you must also modify the IAM role that is attached to the identity pool. Use this option for identity pools that support unauthenticated users. You can use identity pools only from the same Region.
+ Use authentication from an existing identity provider that you have already set up. In this case, you must get credentials from the identity provider and your application must forward these credentials to the RUM web client.

  Use this option for identity pools that support only authenticated users.
+ Use resource-based policies to manage access to your app monitor. This includes the ability to send unauthenticated requests to CloudWatch RUM without AWS credentials. To learn more about resource based policies and RUM, see [Using resource-based policies with CloudWatch RUM](CloudWatch-RUM-resource-policies.md).

The following sections include more details about these options.

## Use an existing Amazon Cognito identity pool
<a name="CloudWatch-RUM-get-started-authorization-existingcognito"></a>

If you choose to use a Amazon Cognito identity pool, you specify the identity pool when you add the application to CloudWatch RUM. The pool must support enabling access to unauthenticated identities. You can use identity pools only from the same Region.

You also must add the following permissions to the IAM policy that is attached to the IAM role that is associated with this identity pool.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        { 
            "Effect": "Allow",
            "Action": [
                "rum:PutRumEvents"
            ],
            "Resource": "arn:aws:rum:us-east-1:123456789012:appmonitor/app monitor name" 
        }
    ]
}
```

------

Amazon Cognito will then send the necessary security token to enable your application to access CloudWatch RUM.

## Third-party provider
<a name="CloudWatch-RUM-get-started-authorization-thirdparty"></a>

If you choose to use private authentication from a third-party provider, you must get credentials from the identity provider and forward them to AWS. The best way to do this is by using a *security token vendor*. You can use any security token vendor, including Amazon Cognito with AWS Security Token Service. For more information about AWS STS, see [Welcome to the AWS Security Token Service API Reference](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html). 

If you want to use Amazon Cognito as the token vendor in this scenario, you can configure Amazon Cognito to work with an authentication provider. For more information, see [Getting Started with Amazon Cognito Identity Pools (Federated Identities)](https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-with-identity-pools.html).

After you configure Amazon Cognito to work with your identity provider, you also need to do the following:
+ Create an IAM role with the following permissions. Your application will use this role to access AWS.

------
#### [ JSON ]

****  

  ```
  { 
   "Version":"2012-10-17",		 	 	 
   "Statement": [ 
     { 
       "Effect": "Allow",
       "Action": "rum:PutRumEvents",
       "Resource": "arn:aws:rum:us-east-2:123456789012:appmonitor/AppMonitorName"
     }
   ]
  }
  ```

------
+ Add the following to your application to have it pass the credentials from your provider to CloudWatch RUM. Insert the line so that it runs after a user has signed in to your application and the application has received the credentials to use to access AWS.

  ```
  cwr('setAwsCredentials', {/* Credentials or CredentialProvider */});
  ```

For more information about credential providers in the AWS JavaScript SDK, see [Setting credentials in a web browser](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-browser.html) in the v3 developer guide for SDK for JavaScript, [Setting credentials in a web browser](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-browser.html) in the v2 developer guide for SDK for JavaScript, , and [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers). 

You can also use the SDK for the CloudWatch RUM web client to configure the web client authentication methods. For more information about the web client SDK, see [CloudWatch RUM web client SDK](https://github.com/aws-observability/aws-rum-web). 

# Creating a CloudWatch RUM app monitor for a web application
<a name="CloudWatch-RUM-get-started-create-app-monitor"></a>

To start using CloudWatch RUM with your application, you create an *app monitor*. When the app monitor is created, RUM generates a code snippet for you to paste into your application. The snippet pulls in the RUM client code. The RUM client captures data from your application's user sessions and sends it to RUM.

## To create an app monitor for a web platform
<a name="web-platform-app-monitor"></a>

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**, **RUM**.

1. Choose **Add app monitor**.

1. For **App monitor name**, enter a name to be used to identify this app monitor within the CloudWatch RUM console.

1. Select **Web** as the platform.

1. For **Application domain list**, enter the registered domain names where your application has administrative authority. You can also use a wildcard character `*` to allow any sub-domain or top-level domains (for example, \$1.amazon.com, amazon.\$1, \$1.amazon.\$1).

1. For **Configure RUM data collection**, specify whether you want the app monitor to collect each of the following:
   + **Performance telemetry** – Collects information about page load and resource load times
   + **JavaScript errors** – Collects information about unhandled JavaScript errors raised by your application

     You can select **Unminify JavaScript error stack traces** to debug unminified JavaScript errors. To use this feature, upload your source map files to an Amazon S3 bucket or folder and provide the Amazon S3 URI. Once enabled, RUM will use these source maps and enrich JavaScript error events by adding the unminified stack trace. Note that after enabling, this feature only processes new JavaScript error events and cannot be used on previously collected data. For more information, see [Enabling unminification of JavaScript error stack traces](CloudWatch-RUM-JavaScriptStackTraceSourceMaps.md).
   + **HTTP errors** – Collects information about HTTP errors thrown by your application

   Selecting these options provides more information about your application, but also generates more CloudWatch RUM events and thus incurs more charges.

   If you don't select any of these, the app monitor still collects session start events and page IDs so that you can see how many users are using your application, including breakdowns by operating system type and version, browser type and version, device type, and location.

1. Select **Check this option to allow the CloudWatch RUM Web Client to set cookies** if you want to be able to collect user IDs and session IDs from sampled user sessions. The user IDs are randomly generated by RUM. For more information, see [CloudWatch RUM web client cookies (or similar technologies)](CloudWatch-RUM-privacy.md#CloudWatch-RUM-cookies).

1. For **Session samples**, enter the percentage of user sessions that will be used to gather RUM data. The default is 100%. Reducing this number gives you less data, but reduces your charges. For more information about RUM pricing, see [RUM pricing](CloudWatch-RUM.md#RUMpricing).

1. End user data that you collect for CloudWatch RUM is retained for 30 days and then deleted. If you want to keep copies of RUM events in CloudWatch Logs and configure how long to retain these copies, choose **Check this option to store your application telemetry data in your CloudWatch Logs account** under **Data storage**. By default, the CloudWatch Logs log group retains the data for 30 days. You can adjust the retention period in the CloudWatch Logs console.

1. (Optional) Choose to add a resource-based policy to your app monitor to control who can send `PutRumEvents` requests to your app monitor. If you choose **Create public policy**, a resource policy will be attached to your app monitor that enables anyone to send `PutRumEvents` requests to your app monitor. For more information about this method, see [Using resource-based policies with CloudWatch RUM](CloudWatch-RUM-resource-policies.md).

1. If you attached a resource-based policy in the previous step, then you don't need to sign requests to CloudWatch RUM with AWS credentials, and you can skip setting up authorization. Otherwise, for **Authorization**, specify whether to use a new or existing Amazon Cognito identity pool or use a different identity provider. Creating a new identity pool is the simplest option that requires no other setup steps. For more information, see see [Authorize your web application to send data to AWS](CloudWatch-RUM-get-started-authorization.md).

   Creating a new Amazon Cognito identity pool requires administrative permissions. For more information, see [IAM policies to use CloudWatch RUM](CloudWatch-RUM-permissions.md).

1. (Optional) By default, when you add the RUM code snippet to your application, the web client injects the JavaScript tag to monitor usage into the HTML code of all pages of your application. To change this, choose **Configure pages** and then choose either **Include only these pages** or **Exclude these pages**. Then, specify the pages to include or exclude. To specify a page to include or exclude, enter its complete URLs. To specify additional pages, choose **Add URL**.

1. To enable AWS X-Ray tracing of the user sessions that are sampled by the app monitor, choose **Active tracing** and select **Trace my service with AWS X-Ray.**

   If you select this, `XMLHttpRequest` and `fetch` requests made during user sessions sampled by the app monitor are traced. You can then see traces and segments from these user sessions in the RUM dashboard, and the X-Ray trace map and trace details pages. These user sessions will also show up as client pages in [Application Signals](CloudWatch-Application-Monitoring-Sections.md) after you have enabled it for your application.

   By making additional configuration changes to the CloudWatch RUM web client, you can add an X-Ray trace header to HTTP requests to enable end-to-end tracing of user sessions through to downstream AWS managed services. For more information, see [Enabling X-Ray end-to-end tracing](CloudWatch-RUM-modify-snippet.md#CloudWatch-RUM-xraytraceheader).

1. (Optional) To add tags to the app monitor, choose **Tags**, **Add new tag**.

   Then, for **Key**, enter a name for the tag. You can add an optional value for the tag in **Value**. 

   To add another tag, choose **Add new tag** again.

   For more information, see [Tagging AWS Resources](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html).

1. Choose **Add app monitor**.

1. In the **Sample code** section, you can copy the code snippet to use to add to your application. We recommend that you choose **JavaScript** or **TypeScript** and use NPM to install the CloudWatch RUM web client as a JavaScript module.

   Alternatively, you can choose **HTML** to use a content delivery network (CDN) to install the CloudWatch RUM web client. The disadvantage of using a CDN is that the web client is often blocked by ad blockers.

1. Choose **Copy** or **Download**, and then choose **Done**.

# Modifying the code snippet to configure the CloudWatch RUM web client (optional)
<a name="CloudWatch-RUM-modify-snippet"></a>

You can modify the code snippet before inserting it into your application, to activate or deactivate several options. For more information, see the [ CloudWatch RUM web client documentation.](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md)

There are four configuration options that you should definitely be aware of, as discussed in these sections.

## Preventing the collection of resource URLs that might contain personal information
<a name="CloudWatch-RUM-resourceURL"></a>

By default, the CloudWatch RUM web client is configured to record the URLs of resources downloaded by the application. These resources include HTML files, images, CSS files, JavaScript files, and so on. For some applications, URLs may contain personally identifiable information (PII).

If this is the case for your application, we strongly recommend that you disable the collection of resource URLs by setting `recordResourceUrl: false` in the code snippet configuration, before inserting it into your application.

## Manually recording page views
<a name="CloudWatch-RUM-pageload"></a>

By default, the web client records page views when the page first loads and when the browser's history API is called. The default page ID is `window.location.pathname`. However, in some cases you might want to override this behavior and instrument the application to record page views programmatically. Doing so gives you control over the page ID and when it is recorded. For example, consider a web application that has a URI with a variable identifier, such as `/entity/123` or `/entity/456`. By default, CloudWatch RUM generates a page view event for each URI with a distinct page ID matching the pathname, but you might want to group them by the same page ID instead. To accomplish this, disable the web client's page view automation by using the `disableAutoPageView` configuration, and use the `recordPageView` command to set the desired page ID. For more information, see [ Application-specific Configurations](https://github.com/aws-observability/aws-rum-web/blob/main/docs/configuration.md) on GitHub.

**Embedded script example:**

```
cwr('recordPageView', { pageId: 'entityPageId' });
```

**JavaScript module example:**

```
awsRum.recordPageView({ pageId: 'entityPageId' });
```

## Enabling X-Ray end-to-end tracing
<a name="CloudWatch-RUM-xraytraceheader"></a>

When you create the app monitor, selecting **Trace my service with AWS X-Ray** enables the tracing of `XMLHttpRequest` and `fetch` requests made during user sessions that are sampled by the app monitor. You can then see traces from these HTTP requests in the CloudWatch RUM dashboard, and the X-Ray Trace Map and Trace details pages.

By default, these client-side traces are not connected to downstream server-side traces. To connect client-side traces to server-side traces and enable end-to-end tracing, set the `addXRayTraceIdHeader` option to `true` in the web client. This causes the CloudWatch RUM web client to add an X-Ray trace header to HTTP requests.

The following code block shows an example of adding client-side traces. Some configuration options are omitted from this sample for readibility.

```
<script>
    (function(n,i,v,r,s,c,u,x,z){...})(
        'cwr',
        '00000000-0000-0000-0000-000000000000',
        '1.0.0',
        'us-west-2',
        'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js',
        {
            enableXRay: true,
            telemetries: [ 
                'errors', 
                'performance',
                [ 'http', { addXRayTraceIdHeader: true } ]
            ]
        }
    );
</script>
```

**Warning**  
Configuring the CloudWatch RUM web client to add an X-Ray trace header to HTTP requests can cause cross-origin resource sharing (CORS) to fail or invalidate the request's signature if the request is signed with SigV4. For more information, see the [ CloudWatch RUM web client documentation](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md). We strongly recommend that you test your application before adding a client-side X-Ray trace header in a production environment.

For more information, see the [ CloudWatch RUM web client documentation](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md#http)

## Sending unsigned requests to CloudWatch RUM
<a name="CloudWatch-RUM-unsigned"></a>

By default, the RUM web client signs all requests sent to RUM. If you set `signing:false` in the client configuration, requests will be unsigned when they are sent to CloudWatch RUM. Data will be ingested to RUM only if there is a public resource based policy attached to the app monitor. For more information, see [Using resource-based policies with CloudWatch RUM](CloudWatch-RUM-resource-policies.md).

# Inserting the CloudWatch app monitor code snippet into your application
<a name="CloudWatch-RUM-get-started-insert-code-snippet"></a>

Next, you insert the code snippet that you created in the previous section into your application.

**Warning**  
The web client, downloaded and configured by the code snippet, uses cookies (or similar technologies) to help you collect end user data. Before you insert the code snippet, see [Filtering by metadata attributes in the consoleData protection and data privacy with CloudWatch RUM](CloudWatch-RUM-privacy.md).

If you don't have the code snippet that was previously generated, you can find it by following the directions in [How do I find a code snippet that I've already generated?](CloudWatch-RUM-find-code-snippet.md).

**To insert the CloudWatch RUM code snippet into your application**

1. Insert the code snippet that you copied or downloaded in the previous section inside the `<head>` element of your application. Insert it before the `<body>` element or any other `<script>` tags.

   The following is an example of a generated code snippet:

   ```
   <script>
   (function (n, i, v, r, s, c, x, z) {
       x = window.AwsRumClient = {q: [], n: n, i: i, v: v, r: r, c: c};
       window[n] = function (c, p) {
           x.q.push({c: c, p: p});
       };
       z = document.createElement('script');
       z.async = true;
       z.src = s;
       document.head.insertBefore(z, document.getElementsByTagName('script')[0]);
   })('cwr',
       '194a1c89-87d8-41a3-9d1b-5c5cd3dafbd0',
       '1.0.0',
       'us-east-2',
       'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js',
       {
           sessionSampleRate: 1,
           identityPoolId: "us-east-2:c90ef0ac-e3b8-4d1a-b313-7e73cfd21443",
           endpoint: "https://dataplane.rum.us-east-2.amazonaws.com",
           telemetries: ["performance", "errors", "http"],
           allowCookies: true,
           enableXRay: false
       });
   </script>
   ```

1. If your application is a multipage web application, you must repeat step 1 for each HTML page that you want included in the data collection.

# Testing your CloudWatch app monitor setup by generating user events
<a name="CloudWatch-RUM-get-started-generate-data"></a>

After you have inserted the code snippet and your updated application is running, you can test it by manually generating user events. To test this, we recommend that you do the following. This testing incurs standard CloudWatch RUM charges.
+ Navigate between pages in your web application.
+ Create multiple user sessions, using different browsers and devices.
+ Make requests.
+ Cause JavaScript errors.

After you have generated some events, view them in the CloudWatch RUM dashboard. For more information, see [Viewing the CloudWatch RUM dashboard](CloudWatch-RUM-view-data.md).

Data from user sessions might take up to 15 minutes to appear in the dashboard.

If you don't see data 15 minutes after you generated events in the application, see [Troubleshooting CloudWatch RUM](CloudWatch-RUM-troubleshooting.md).

# Using resource-based policies with CloudWatch RUM
<a name="CloudWatch-RUM-resource-policies"></a>

You can attach a resource policy to a CloudWatch RUM app monitor. By default, app monitors do not have a resource policy attached to them. CloudWatch RUM resource based policies do not support cross-account access.

To learn more about AWS resource policies, see [Identity-based policies and resource-based policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html).

To learn more about how resource policies and identity policies are evaluated, see [Policy evaluation logic](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html).

To learn more about IAM policy grammar, see [IAM JSON policy element reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html).

## Supported actions
<a name="RUM-resource-policies-actions"></a>

Resource-based policies on app monitors support the `rum:PutRumEvents` action.

## Sample policies to use with CloudWatch RUM
<a name="RUM-resource-policies-samples"></a>

The following example allows anyone to write data to your app monitor, including those without SigV4 credentials.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "rum:PutRumEvents",
            "Resource": "arn:aws:rum:us-east-1:123456789012:appmonitor/app monitor name",
            "Principal": "*"
        }
    ]
}
```

------

You can modify the policy to block specified source IP addresses by using the `aws:SourceIp` condition key. With this example, Using this policy, PutRumEvents from the IP address listed will be rejected. All other requests from other IP addresses will be accepted. For more information about this condition key, see [Properties of the network](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-network-properties) in the IAM User Guide.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "rum:PutRumEvents",
            "Resource": "arn:aws:rum:us-east-1:123456789012:appmonitor/AppMonitorName",
            "Principal": "*"
        },
        {
            "Effect": "Deny",
            "Action": "rum:PutRumEvents",
            "Resource": "arn:aws:rum:us-east-1:123456789012:appmonitor/AppMonitorName",
            "Principal": "*",
            "Condition": {
                "NotIpAddress": {
                "aws:SourceIp": "198.51.100.252"
                }
            }
        }
    ]
}
```

------

Additionally, you can use the `rum:alias` service context key to control which requests are accepted. 

For web app monitors, you must configure your web client to send `Alias` using version 1.20 or later of the CloudWatch RUM web client, as described in [ Application-specific Configurations](https://github.com/aws-observability/aws-rum-web/blob/main/docs/configuration.md) on GitHub.

For mobile app monitors, you must configure your instrumentation according to the SDK.
+ iOS applications use the [AWS Distro for OpenTelemetry (ADOT) iOS SDK](https://github.com/aws-observability/aws-otel-swift). 
+ Android applications use the [AWS Distro for OpenTelemetry (ADOT) Android SDK](https://github.com/aws-observability/aws-otel-android).

In the following example, the resource policy requires that requests must contain either `alias1` or `alias2` for the event to be accepted.

```
    {
    "Version":"2012-10-17",                   
    "Statement": [
        {
            "Sid": "AllowRUMPutEvents",
            "Effect": "Allow",
            "Action": "rum:PutRumEvents",
            "Resource": "arn:aws:rum:us-east-1:123456789012:appmonitor/MyApplication",
            "Principal": "*",
            "Condition": {
                "StringEquals": {
                    "rum:alias":["alias1", "alias2"]
                }
            }
        }
    ]
}
```

# Configuring the CloudWatch RUM web client
<a name="CloudWatch-RUM-configure-client"></a>

Your applications can use one of the code snippets generated by CloudWatch RUM to install the CloudWatch RUM web client. The generated snippets support two installation methods: as a JavaScript module through NPM, or from a content delivery network (CDN). For best performance, we recommend using the NPM installation method. For more information about using this method, see [ Installing as a JavaScript Module](https://github.com/aws-observability/aws-rum-web/blob/main/docs/npm_installation.md).

If you use the CDN installation option, ad blockers might block the default CDN provided by CloudWatch RUM. This disables application monitoring for users who have ad blockers installed. Because of this, we recommend that you use the default CDN only for initial onboarding with CloudWatch RUM. For more information about the ways to mitigate this issue, see [ Instrument the application](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md#instrument-the-application).

The code snippet sits in the `<head>` tag of an HTML file and installs the web client by downloading the web client, and then configuring the web client for the application it is monitoring. The snippet is a self-executing function which looks similar to the following. In this example, the body of the snippet's function has been omitted for readability.

```
<script>
(function(n,i,v,r,s,c,u,x,z){...})(
'cwr',
'00000000-0000-0000-0000-000000000000',
'1.0.0',
'us-west-2',
'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js',
{ /* Configuration Options Here */ }
);
<script>
```

## Arguments
<a name="CloudWatch-RUM-configure-client-arguments"></a>

The code snippet accepts six arguments:
+ A namespace for running commands on the web client, such as `'cwr'`
+ The ID of the app monitor, such as `'00000000-0000-0000-0000-000000000000'`
+ The application version, such as `'1.0.0'`
+ The AWS Region of the app monitor, such as `'us-west-2'`
+ The URL of the web client, such as `'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js'`
+ Application-specific configuration options. For more information, see the following section.

## Ignoring errors
<a name="CloudWatch-RUM-configure-ignore-errors"></a>

The CloudWatch RUM web client listens to all types of errors that happen in your applications. If your application emits JavaScript errors that you do not want to view in the CloudWatch RUM dashboard, you can configure the CloudWatch RUM web client to filter out these errors so that you see only the relevant error events on the CloudWatch RUM dashboard. For example, you might choose not to view some JavaScript errors in the dashboard because you have already identified a fix for them and the volume of these errors is masking other errors. You might also want to ignore errors that you can't fix because they are owned by a library owned by a third party.

For more information about how to instrument the web client to filter out specific JavaScript errors, see the example in [ Errors](https://github.com/aws-observability/aws-rum-web/blob/main/docs/configuration.md#errors) in the web client Github documentation.

## Configuration options
<a name="CloudWatch-RUM-configure-options"></a>

For information about the configuration options available for the CloudWatch RUM web client, see the [ CloudWatch RUM web client documentation](https://github.com/aws-observability/aws-rum-web/blob/main/docs/configuration.md)

# Enabling unminification of JavaScript error stack traces
<a name="CloudWatch-RUM-JavaScriptStackTraceSourceMaps"></a>

When your web application JavaScript source code is minified, error stack traces can be difficult to read. You can enable unminification to the stack traces by uploading your source maps to Amazon S3. CloudWatch RUM will retrieve the source maps to map the line and column numbers in the minified source code back to the original unminified source code. This will improve readability of your error stack traces and help identify the location of the error in the original source code. 

## Requirements and syntax
<a name="CloudWatch-RUM-RequirementsJavaScriptStackTraceSourceMaps"></a>

Source maps are crucial for debugging and tracking issues in your web application across different releases. Make sure that each web application release has a unique source map. Each release should have its own unique releaseId. A releaseId must be a string between 1 and 200 characters long and can only contain letters, numbers, underscores, hyphens, colons, forward slashes, and periods. To add the `releaseId` as metadata to RUM events, configure the CloudWatch RUM web client.

Source maps are expected to be plain JSON files following the structure defined by the [Source Map V3 specification](https://sourcemaps.info/spec.html). The required fields are: `version`, `file`, `sources`, `names`, and `mappings`.

Make sure the size of each source map does not exceed the limit of 50 MB. In addition, RUM service will only retrieve up to 50 MB of source maps per stack trace. If needed, split the source code into multiple smaller chunks. For more information, see [Code Splitting with WebpackJS](https://webpack.js.org/guides/code-splitting/).

**Topics**
+ [

## Requirements and syntax
](#CloudWatch-RUM-RequirementsJavaScriptStackTraceSourceMaps)
+ [

## Configure your Amazon S3 bucket resource policy to allow RUM service access
](#CloudWatch-RUM-ConfigureS3)
+ [

## Upload source maps
](#CloudWatch-RUM-UploadSourceMaps)
+ [

## Configure releaseId in your CloudWatch RUM web client
](#CloudWatch-RUM-ConfigureRumID)
+ [

## Enabling CloudWatch RUM app monitor to unminify JavaScript stack traces
](#CloudWatch-RUM-unminifyjavascript)
+ [

## Viewing unminified stack traces in the RUM console
](#CloudWatch-RUM-viewunminifiedstacktraces)
+ [

## Viewing unminified stack traces in CloudWatch Logs
](#CloudWatch-RUM-viewunminifiedstacktracesCWL)
+ [

## Troubleshooting source maps
](#CloudWatch-RUM-troubleshootsourcemaps)

## Configure your Amazon S3 bucket resource policy to allow RUM service access
<a name="CloudWatch-RUM-ConfigureS3"></a>

Make sure your Amazon S3 bucket is in the same region as your RUM appMonitor. Configure your Amazon S3 bucket to allow RUM service access for retrieving source map files. Include the `aws:SourceArn` and `aws:SourceAccount` global condition context keys to limit the service’s permissions to the resource. This is the most effective way to protect against the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).

The following example shows how you can use the `aws:SourceArn` and `aws:SourceAccount` global condition context keys in Amazon S3 to prevent the confused deputy problem.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "RUM Service S3 Read Permissions",
            "Effect": "Allow",
            "Principal": {
                "Service": "rum.amazonaws.com"
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::BUCKET_NAME",
                "arn:aws:s3:::BUCKET_NAME/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "ACCOUNT_ID",
                    "aws:SourceArn": "arn:aws:rum:REGION:ACCOUNT_ID:appmonitor/APP_MONITOR_NAME"
                }
            }
        }
    ]
}
```

------

If you are using AWS KMS keys to encrypt the data, make sure the key’s resource policy is configured similarly to include the `aws:SourceArn` and `aws:SourceAccount` global condition context keys to give RUM service access to use the keys to retrieve the source map files.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "RUM Service KMS Read Permissions",
            "Effect": "Allow",
            "Principal": {
                "Service": "rum.amazonaws.com"
            },
            "Action": "kms:Decrypt",
            "Resource": "arn:aws:kms:us-east-1:123456789012:key/KEY_ID",
            "Condition": {
                "StringEquals": {
                "aws:SourceAccount": "123456789012",
    "aws:SourceArn": "arn:aws:rum:us-east-1:123456789012/APP_MONITOR_NAME"
                }
            }
        }
    ]
}
```

------

## Upload source maps
<a name="CloudWatch-RUM-UploadSourceMaps"></a>

Configure your JavaScript bundle to generate source maps during minification. When you build your application, the bundle will create a directory (for example, dist) containing the minified JavaScript files and their corresponding source maps. See below for an example.

```
./dist
    |-index.d5a07c87.js
    |-index.d5a07c87.js.map
```

Upload the source map files to your Amazon S3 bucket. The files should be located in a folder with the `releaseId` as the name. For example, if my bucket name is `my-application-source-maps` and the `releaseId` is 2.0.0, then the source map file is located at the following location:

```
my-application-source-maps
    |-2.0.0
        |-index.d5a07c87.js.map
```

To automate uploading your source maps, you can create the following bash script and execute it as part of your build process.

```
#!/bin/bash
# Ensure the script is called with required arguments
if [ "$#" -ne 2 ]; then
 echo "Usage: $0 S3_BUCKET_NAME RELEASE_ID"
 exit 1
fi

# Read arguments
S3_BUCKET="$1"
RELEASE_ID="$2"

# Set the path to your build directory
BUILD_DIR="./dist"


# Upload all .map files recursively
 if aws s3 cp "$BUILD_DIR" "s3://$S3_BUCKET/$RELEASE_ID/" --recursive --exclude "*" --include "*.map"; then
    echo "Successfully uploaded all source map files"
else
    echo "Failed to upload source map files"
fi
```

## Configure releaseId in your CloudWatch RUM web client
<a name="CloudWatch-RUM-ConfigureRumID"></a>

CloudWatch RUM uses the configured `releaseId` to determine the folder to retrieve the source map files. Name the `releaseId` the same as your source map files folder. If you used the provided bash script above or a similar one, the `releaseId` configured in the script should be the same as the one configured in your CloudWatch RUM web client. You must use version 1.21.0 or later of the CloudWatch RUM web client.

```
import { AwsRum, AwsRumConfig } from "aws-rum-web";

try {
    const config: AwsRumConfig = {
        sessionSampleRate: 1,
        endpoint: "https://dataplane.rum.us-west-2.amazonaws.com",
        telemetries: ["performance", "errors", "http"],
        allowCookies: true,
        releaseId: "RELEASE_ID", //Add this
    };

    const APPLICATION_ID: string = "APP_MONITOR_ID";
    const APPLICATION_VERSION: string = "1.0.0";
    const APPLICATION_REGION: string = "us-west-2";

    new AwsRum(APPLICATION_ID, APPLICATION_VERSION, APPLICATION_REGION, config);
} catch (error: any) {
    // Ignore errors thrown during CloudWatch RUM web client initialization
}
```

## Enabling CloudWatch RUM app monitor to unminify JavaScript stack traces
<a name="CloudWatch-RUM-unminifyjavascript"></a>

To unminify JavaScript stack traces, set the app monitor's SourceMap status to `ENABLED`. Provide the Amazon S3 URI to the bucket or folder containing all source maps for your app monitor.

When storing source maps directly in the main bucket (not in a subfolder), then the Amazon S3 URI should be formatted as `Amazon S3://BUCKET_NAME`. In this case, source map files should be located at the following location.

```
BUCKET_NAME
    |- RELEASE_ID
        |-index.d5a07c87.js.map
```

When a child directory is the root, then the Amazon S3 URI should be formatted as `Amazon S3://BUCKET_NAME/DIRECTORY`. In this case, source map files should be located at the following location.

```
BUCKET_NAME
    |- DIRECTORY
        |-RELEASE_ID
            |-index.d5a07c87.js.map
```

## Viewing unminified stack traces in the RUM console
<a name="CloudWatch-RUM-viewunminifiedstacktraces"></a>

After uploading your source maps to Amazon S3, enabling source maps on your RUM app monitor, and deploying your web application with the `releaseId` configured in the CloudWatch RUM web client, select **Events** in the RUM console. This tab displays the raw RUM event data. Filter by the JS error event type and view the latest JS error event. You will see the unminified stack trace in the new `event_details.unminifiedStack` field for events ingested after the feature was enabled.

## Viewing unminified stack traces in CloudWatch Logs
<a name="CloudWatch-RUM-viewunminifiedstacktracesCWL"></a>

Enable RUM event storage in CloudWatch Logs by turning on **Data storage**. Once enabled, you can search the new **event\$1details.unminifiedStack** field. This allows you to analyze trends and relate issues across multiple sessions using CloudWatch Logs queries.

## Troubleshooting source maps
<a name="CloudWatch-RUM-troubleshootsourcemaps"></a>

CloudWatch RUM provides out of the box metrics to troubleshoot your source map setup. These metrics are published in the metric namespace named `AWS/RUM`. The following metrics are published with an application\$1name dimension. The value of this dimension is the name of the app monitor. The metrics are also published with an `aws:releaseId` dimension. The value of this dimension is the `releaseId` associated with the JavaScript error event.


| MetricName | Unit | Description | 
| --- | --- | --- | 
|  UnminifyLineFailureCount  |  Count  |  The count of stack trace lines in the JS error event that failed to be unminified. Additional details regarding the failure will be added to the specific line that failed in the event\$1details.unminifiedStack field.  | 
|  UnminifyLineSuccessCount  |  Count  | The count of stack trace lines in the JS error event that were successfully unminified. | 
| UnminifyEventFailureCount | Count | The count of JS error events that failed to have any lines unminified. Additional details regarding the failure will be added in the event\$1details.unminifiedStack field. | 
| UnminifyEventSuccessCount | Count | The count of JS error events that succeeded to have at least one stack trace line unminified. | 

CloudWatch RUM may fail to unminify a line in the stack trace for various reasons, including but not limited to:
+ Failure to retrieve corresponding source map file due to permission issues. Make sure the bucket resource policy is configured correctly.
+ Corresponding source map file does not exist. Make sure the source map files have been uploaded to the correct bucket or folder that has the same name as the releaseId configured in your CloudWatch RUM web client.
+ Corresponding source map file is too big. Split your source code into smaller chunks.
+ 50 MB worth of source map files already retrieved for the stack trace. Reduce the stack trace length as 50 MB is service side limitation.
+ Source map is invalid and could not be indexed. Make sure the source map is a plain JSON following the structure defined by the Source Map V3 specification and includes the following fields: version, file, sources, names, mappings.
+ Source map could not map the minified source code back to the unminified stack trace. Make sure the source map is the correct source map for the given releaseId.

# Regionalization
<a name="CloudWatch-RUM-Regionalization"></a>

This section illustrates strategies for using CloudWatch RUM with applications in different Regions.

## My application is deployed in multiple AWS Regions
<a name="CloudWatch-RUM-Regionalization-multiple"></a>

If your application is deployed in multiple AWS Regions, you have three options:
+ Deploy one app monitor in one Region, in one account, serving all Regions.
+ Deploy separate app monitors for each Region, in unique accounts.
+ Deploy separate app monitors for each Region, all in one account.

The advantage of using one app monitor is that all data will be centralized into one visualization, and all logs are written to the same log group in CloudWatch Logs. With a single app monitor there is a small amount of extra latency for requests, and a single point of failure.

Using multiple app monitors removes the single point of failure, but prevents all data from being combined into one visualization.

### CloudWatch RUM hasn't launched in some Regions that my application is deployed in
<a name="CloudWatch-RUM-Regionalization-notavailable"></a>

CloudWatch RUM is launched into many Regions and has wide geographical coverage. By setting up CloudWatch RUM in the Regions where it is available, you can get the benefits. End users can be anywhere and still have their sessions included if you have set up an app monitor in the Region that they are connecting to.

However, CloudWatch RUM is not yet launched in any Regions in China. You are not able to send data to CloudWatch RUM from these Regions.

# Use page groups
<a name="CloudWatch-RUM-page-groups"></a>

Use page groups to associate different pages in your application with each other so that you can see aggregated analytics for groups of pages. For example, you might want to see the aggregated page load times of all of your landing pages. 

You put pages into page groups by adding one or more tags to page view events in the CloudWatch RUM web client. The following examples put the `/home` page into the page group named `en` and the page group named `landing`.

**Embedded script example**

```
cwr('recordPageView', { pageId: '/home', pageTags: ['en', 'landing']});
```

**JavaScript module example**

```
awsRum.recordPageView({ pageId: '/home', pageTags: ['en', 'landing']});
```

**Note**  
Page groups are intended to facilitate aggregating analytics across different pages. For information about how to define and manipulate `pageIds` for your application, see the **Manually recording page views** section in [Modifying the code snippet to configure the CloudWatch RUM web client (optional)](CloudWatch-RUM-modify-snippet.md).

# Specify custom metadata
<a name="CloudWatch-RUM-custom-metadata"></a>

CloudWatch RUM attaches additional data to each event as metadata. Event metadata consists of attributes in the form of key-value pairs. You can use these attributes to search or filter events in the CloudWatch RUM console. By default, CloudWatch RUM creates some metadata for you. For more information about the default metadata, see [RUM event metadata](CloudWatch-RUM-datacollected.md#CloudWatch-RUM-datacollected-metadata).

You can also use the CloudWatch RUM web client to add custom metadata to CloudWatch RUM events. The custom metadata can include session attributes and page attributes.

To add custom metadata, you must use version 1.10.0 or later of the CloudWatch RUM web client.

## Requirements and syntax
<a name="CloudWatch-RUM-custom-metadata-syntax"></a>

Each event can include as many as 10 custom attributes in the metadata. The syntax requirements for custom attributes are as follows:
+ **Keys**
  + Maximum of 128 characters
  + Can include alphanumeric characters, colons (:), and underscores (\$1)
  + Can't begin with `aws:`.
  + Can't consist entirely of any of the reserved keywords listed in the following section. Can use those keywords as part of a longer key name.
+ **Values**
  + Maximum of 256 characters
  + Must be strings, numbers, or Boolean values

**Reserved keywords**

You can't use the following reserved keywords as complete key names. You can use the following keywords as part of a longer key name, such as `applicationVersion`.
+ `browserLanguage`
+ `browserName`
+ `browserVersion`
+ `countryCode`
+ `deviceType`
+ `domain`
+ `interaction`
+ `osName`
+ `osVersion`
+ `pageId`
+ `pageTags`
+ `pageTitle`
+ `pageUrl`
+ `parentPageId`
+ `platformType`
+ `referrerUrl`
+ `subdivisionCode`
+ `title`
+ `url`
+ `version`

**Note**  
CloudWatch RUM removes custom attributes from RUM events if an attribute includes a key or value that is not valid, or if the limit of 10 custom attributes per event has already been reached. 

## Add session attributes
<a name="CloudWatch-RUM-session-attributes"></a>

If you configure custom session attributes, they are added to all events in a session. You configure session attributes either during CloudWatch RUM web client initialization or at runtime by using the `addSessionAttributes` command.

For example, you can add your application’s version as a session attribute. Then, in the CloudWatch RUM console, you can filter errors by version to find whether an increased error rate is associated with a particular version of your application. 

**Adding a session attribute at initialization, NPM example**

The code section in bold adds the session attribute.

```
import { AwsRum, AwsRumConfig } from 'aws-rum-web';

try {
  const config: AwsRumConfig = {
    allowCookies: true,
    endpoint: "https://dataplane.rum.us-west-2.amazonaws.com",
    guestRoleArn: "arn:aws:iam::000000000000:role/RUM-Monitor-us-west-2-000000000000-00xx-Unauth",
    identityPoolId: "us-west-2:00000000-0000-0000-0000-000000000000",
    sessionSampleRate: 1,
    telemetries: ['errors', 'performance'],
    sessionAttributes: {
        applicationVersion: "1.3.8"
    }
  };

  const APPLICATION_ID: string = '00000000-0000-0000-0000-000000000000';
  const APPLICATION_VERSION: string = '1.0.0';
  const APPLICATION_REGION: string = 'us-west-2';

  const awsRum: AwsRum = new AwsRum(
    APPLICATION_ID,
    APPLICATION_VERSION,
    APPLICATION_REGION,
    config
  );
} catch (error) {
  // Ignore errors thrown during CloudWatch RUM web client initialization
}
```

**Adding a session attribute at runtime, NPM example**

```
awsRum.addSessionAttributes({ 
    applicationVersion: "1.3.8"    
})
```

**Adding a session attribute at initialization, embedded script example**

The code section in bold adds the session attribute.

```
<script>
    (function(n,i,v,r,s,c,u,x,z){...})(
        'cwr',
        '00000000-0000-0000-0000-000000000000',
        '1.0.0',
        'us-west-2',
        'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js',
        {
            sessionSampleRate:1,
            guestRoleArn:'arn:aws:iam::000000000000:role/RUM-Monitor-us-west-2-000000000000-00xx-Unauth',
            identityPoolId:'us-west-2:00000000-0000-0000-0000-000000000000',
            endpoint:'https://dataplane.rum.us-west-2.amazonaws.com',
            telemetries:['errors','http','performance'],
            allowCookies:true,
            sessionAttributes: {
                applicationVersion: "1.3.8"
            }
        }
    );
</script>
```

**Adding a session attribute at runtime, embedded script example**

```
<script>
    function addSessionAttribute() {
        cwr('addSessionAttributes', {
            applicationVersion: "1.3.8"
        })
    }
            
</script>
```

## Add page attributes
<a name="CloudWatch-RUM-page-attributes"></a>

If you configure custom page attributes, they are added to all events on the current page. You configure page attributes either during CloudWatch RUM web client initialization or at runtime by using the `recordPageView` command.

For example, you can add your page template as a page attribute. Then, in the CloudWatch RUM console, you can filter errors by page templates to find whether an increased error rate is associated with a particular page template of your application. 

**Adding a page attribute at initialization, NPM example**

The code section in bold adds the page attribute.

```
const awsRum: AwsRum = new AwsRum(
    APPLICATION_ID,
    APPLICATION_VERSION,
    APPLICATION_REGION,
    { disableAutoPageView:  true // optional }
);
awsRum.recordPageView({  
    pageId:'/home',  
    pageAttributes: {
      template: 'artStudio'
    }
});
const credentialProvider = new CustomCredentialProvider();
if(awsCreds) awsRum.setAwsCredentials(credentialProvider);
```

**Adding a page attribute at runtime, NPM example**

```
awsRum.recordPageView({ 
    pageId: '/home', 
    pageAttributes: {
        template: 'artStudio'
    } 
});
```

**Adding a page attribute at initialization, embedded script example**

The code section in bold adds the page attribute.

```
<script>
    (function(n,i,v,r,s,c,u,x,z){...})(
        'cwr',
        '00000000-0000-0000-0000-000000000000',
        '1.0.0',
        'us-west-2',
        'https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js',
        {
            disableAutoPageView: true //optional
        }
    );
    cwr('recordPageView', { 
       pageId: '/home',  
       pageAttributes: {
           template: 'artStudio'
       }
    });
    const awsCreds = localStorage.getItem('customAwsCreds');
    if(awsCreds) cwr('setAwsCredentials', awsCreds)
</script>
```

**Adding a page attribute at runtime, embedded script example**

```
<script>
    function recordPageView() {
        cwr('recordPageView', { 
            pageId: '/home', 
            pageAttributes: {
                template: 'artStudio'
            }
        });
    }        
</script>
```

## Filtering by metadata attributes in the console
<a name="CloudWatch-RUM-custom-attiributes-console"></a>

To filter the visualizations in the CloudWatch RUM console with any built-in or custom metadata attribute, use the search bar. In the search bar, you can specify as many as 20 filter terms in the form of **key=value** to apply to the visualizations. For example, to filter data for only the Chrome browser, you could add the filter term **browserName=Chrome**.

By default, the CloudWatch RUM console retrieves the 100 most common attributes keys and values to display in the dropdown in the search bar. To add more metadata attributes as filter terms, enter the complete attribute key and value into the search bar. 

A filter can include as many as 20 filter terms, and you can save up to 20 filters per app monitor. When you save a filter, it is saved in the **Saved filters** dropdown. You can also delete a saved filter. 

# Send custom events
<a name="CloudWatch-RUM-custom-events"></a>

CloudWatch RUM records and ingests the events listed in [Information collected by the CloudWatch RUM web client](CloudWatch-RUM-datacollected.md). If you use version 1.12.0 or later of the CloudWatch RUM web client, you can define, record, and send additional custom events. You define the event type name and the data to send for each event type that you define. Each custom event payload can be up to 6 KB.

Custom events are ingested only if the app monitor has custom events enabled. To update the configuration settings of your app monitor, use the CloudWatch RUM console or the [UpdateAppMonitor](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_UpdateAppMonitor.html) API. 

After you enable custom events, and then define and send custom events, you can search for them. To search for them, use the **Events** tab in the CloudWatch RUM console. Search by using the event type.

## Requirements and syntax
<a name="CloudWatch-RUM-custom-event-syntax"></a>

Custom events consist of an event type and event details. The requirements for these are as follows:
+ **Event type**
  + This can be either the **type** or **name** of your event. For example, the CloudWatch RUM built-in event type called **JsError** has an event type of `com.amazon.rum.js_error_event`.
  + Must be between 1 and 256 characters.
  + Can be a combination of alphanumeric characters, underscores, hyphens, and periods.
+ **Event details**
  + Contains the actual data that you want to record in CloudWatch RUM.
  + Must be an object that consists of fields and values.

## Examples of recording custom events
<a name="CloudWatch-RUM-custom-event-examples"></a>

There are two ways to record custom events in the CloudWatch RUM web client. 
+ Use the CloudWatch RUM web client's `recordEvent` API.
+ Use a customized plugin.

**Send a custom event using the `recordEvent` API, NPM example**

```
awsRum.recordEvent('my_custom_event', {
        location: 'IAD', 
        current_url: 'amazonaws.com', 
        user_interaction: {
            interaction_1 : "click",
            interaction_2 : "scroll"
        }, 
        visit_count:10
    }
)
```

**Send a custom event using the `recordEvent` API, embedded script example**

```
cwr('recordEvent', {
    type: 'my_custom_event', 
    data: {
        location: 'IAD', 
        current_url: 'amazonaws.com', 
        user_interaction: {
            interaction_1 : "click",
            interaction_2 : "scroll"
        }, 
        visit_count:10
    }
})
```

**Example of sending a custom event using a customized plugin**

```
// Example of a plugin that listens to a scroll event, and
// records a 'custom_scroll_event' that contains the timestamp of the event.
class MyCustomPlugin implements Plugin {
    // Initialize MyCustomPlugin.
    constructor() {
        this.enabled;
        this.context;
        this.id = 'custom_event_plugin';
    }
    // Load MyCustomPlugin.
    load(context) {
        this.context = context;
        this.enable();
    }
    // Turn on MyCustomPlugin.
    enable() {
        this.enabled = true;
        this.addEventHandler();
    }
    // Turn off MyCustomPlugin.
    disable() {
        this.enabled = false;
        this.removeEventHandler();
    }
    // Return MyCustomPlugin Id.
    getPluginId() {
        return this.id;
    }
    // Record custom event.
    record(data) {
        this.context.record('custom_scroll_event', data);
    }
    // EventHandler.
    private eventHandler = (scrollEvent: Event) => {
        this.record({timestamp: Date.now()})
    }
    // Attach an eventHandler to scroll event.
    private addEventHandler(): void {
        window.addEventListener('scroll', this.eventHandler);
    }
    // Detach eventHandler from scroll event.
    private removeEventHandler(): void {
        window.removeEventListender('scroll', this.eventHandler);
    }
}
```

# Viewing the CloudWatch RUM dashboard
<a name="CloudWatch-RUM-view-data"></a>

CloudWatch RUM helps you collect data from user sessions about your application's performance, including load times, Apdex score, device information, geolocation of user sessions, and sessions with errors. All of this information is displayed in a dashboard.

To view the RUM dashboard:

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**, **RUM**.

The RUM console displays a list view of all your app monitors. The **Platform** column indicates whether each app monitor is for Web, Android, or iOS applications. Select an app monitor to access detailed views with **Performance**, **Errors**, **Sessions**, **Metrics** and **Configuration** tabs.

## Web Application Dashboard
<a name="CloudWatch-RUM-web-dashboard"></a>

When you select a web application monitor, you'll see the following tabs:
+ The **Performance** tab displays page performance information including load times, request information, web vitals, and page loads over time. This view features interactive web vitals graphs where you can see the different percentile values of core web vitals for your pages and choose datapoints on the graph to view associated events captured by CloudWatch RUM. From there, you can either explore more events related to the metric spike or view page details for a selected event to identify specific conditions causing performance issues.

  On this tab you can also toggle the view between **Page loads**, **Requests**, and **Location** to see more details about page performance.
+ The **Errors** tab displays Javascript error information including the error message most frequently seen by users and the devices and browsers with the most errors. This view includes a histogram of the errors and a list view of errors. You can filter the list of errors by user and event details. Choose an error message to see more details.
+ The **HTTP requests** tab displays HTTP request information including the request URL with most errors and the devices and browsers with the most errors. This tab includes a histogram of the requests, a list view of requests, and a list view of network errors. You can filter the lists by user and event details. Choose a response code or an error message to see more details about the request or network error, respectively.
+ The **Sessions** tab displays session metrics. This tab includes a histogram of session start events and a list view of sessions. You can filter the list of sessions by event type, user details, and event details. Choose a **sessionId** to see more details about a session.
+ The **Events** tab displays a histogram of RUM events and a list view of the events. You can filter the list of events by event type, user details, and event details. Choose a RUM event to see the raw event.
+ The **Browsers & Devices** tab displays information such as the performance and usage of different browsers and devices to access your application. This view includes controls to toggle the view between focusing on **Browsers** and **Devices**.

  If you narrow the scope to a single browser, you see the data broken down by browser version.
+ The **User Journey** tab displays the paths that your customers use to navigate your application. You can see where your customers enter your application and what page they exit your application from. You can also see the paths that they take and the percentage of customers that follow those paths. You can pause on a node to get more details about that page. You can choose a single path to highlight the connections for easier viewing.
+  The **Metrics** tab displays all default CloudWatch metrics published by your app monitor, including performance web vitals, error metrics (JavaScript errors, HTTP errors/faults), volume, user flow and apdex metrics. If you created extended metrics for your application, the tab also includes a subset of these metrics in the extended metrics section. This subset includes metrics of type PageViewCount, PerformanceNavigationDuration, Http4xxCount, Http5xxCount and JsErrorCount. The dashboard shows three metric variations per metric type. Since these are CloudWatch metrics, you can also export this tab to your own dashboard using the **Add to dashboard** option and update it to include more metrics. 

(Optional) On any of the first six tabs, you can choose the **Pages** button and select a page or page group from the list. This narrows down the displayed data to a single page or group of pages of your application. You can also mark pages and page groups in the list as favorites.

## Mobile Application Dashboard
<a name="CloudWatch-RUM-mobile-dashboard"></a>

When you select a mobile application monitor, you'll see the following tabs:
+ The **Performance** tab provides insights into the performance of your mobile application including screen load times, app launch times (cold and warm), performance metrics, and Apdex scores over time. The detailed view breaks down performance by screen names, OS versions, app versions, devices, and countries. Clicking a screen load time, app launch time, or location datapoint in the chart will open the diagnostic panel on the right that provides further insights relevant to the datapoint consisting the most recent correlated sessions and links to the **Sessions** tab for troubleshooting.

  On this tab you can also toggle the view between **Screen loads**, **App launches**, and **Location** to see more details about application performance.

  The tab also features the application performance index (Apdex) score which indicates end users' level of satisfaction. Scores range from 0 (least satisfied) to 1 (most satisfied). The scores are based on application performance only. For more information about Apdex scores, see [How CloudWatch RUM sets Apdex scores](#CloudWatch-RUM-apdex).
+ The **Errors** tab breaks down application issues in three categories: Network Errors, Crashes, and ANRs (Android)/App Hangs (iOS). The **Network Errors** tab has a line chart showing network latency, client errors (4xx status code), and server errors (5xx status code). Clicking on a data point for any of these lines in the chart will open the diagnostic panel. The bottom table lists the 100 most common network routes. Clicking on a radio button will filter the line chart by the network route selected.

  Similarly, the **Crashes** and **ANRs/App Hangs** tabs show a line series for the count of each error, and these are intractable. The bottom table displays the most common top crash message or ANR/App Hang stack trace. Clicking on a radio button will filter the chart, and clicking the error message will show the complete stack trace.
+ The **Sessions** tab displays a table that lists all sessions in descending chronological order. At the bottom, a waterfall visualization shows all telemetry for the selected session, helping you track user interactions and identify performance issues. Each row in the waterfall can be selected to open the diagnostic panel. For HTTP requests, you'll see a **traceId** that links to the Traces console.

  For HTTP requests with non-2xx status codes, crashes, or ANRs (Android)/ App Hangs (iOS), the diagnostic panel includes an **Exception** tab with the stack trace. The **View** button in the waterfall provides quick access to this information.
+ The **Metrics** tab displays all default CloudWatch metrics published by your app monitor, including performance metrics (screen load times, cold app launch times), error metrics (crashes, ANRs/App Hangs, HTTP errors/faults), volume and apdex metrics. If you created extended metrics for your application, the tab also includes a subset of these metrics in the extended metrics section. This subset includes metrics of type ScreenLoadTime, ScreenLoadCount, CrashCount, Http4xxCount, Http5xxCount, ANRCount/AppHangCount, ColdLaunchTime and WarmLaunchTime. The dashboard shows three metric variations per metric type. Since these are CloudWatch metrics, you can also export this tab to your own dashboard using the **Add to dashboard** option and update it to include more metrics.
+ The **Configuration** tab provides access to your app monitor's general settings and configuration details. You can also access the **Code snippets** tab which contains instructions for instrumenting your mobile application with the ADOT SDK, including both Manual and Zero-Code instrumentation options.

### How CloudWatch RUM sets Apdex scores
<a name="CloudWatch-RUM-apdex"></a>

Apdex (Application Performance Index) is an open standard that defines a method to report, benchmark, and rate application response time. An Apdex score helps you understand and identify the impact on application performance over time.

The Apdex score indicates the end users' level of satisfaction. Scores range from 0 (least satisfied) to 1 (most satisfied). The scores are based on application performance only. Users are not asked to rate the application.

Each individual Apdex score falls into one of three thresholds. Based on the Apdex threshold and actual application response time, there are three kinds of performance, as follows:
+ **Satisfied**— The actual application response time is less than or equal to the Apdex threshold. For CloudWatch RUM, this threshold is 2000 ms or less.
+ **Tolerable**— The actual application response time is greater than the Apdex threshold, but less than or equal to four times the Apdex threshold. For CloudWatch RUM, this range is 2000—8000 ms.
+ **Frustrating**— The actual application response time is greater than four times the Apdex threshold. For CloudWatch RUM, this range is over 8000 ms.

The total 0-1 Apdex score is calculated using the following formula:

`(positive scores + tolerable scores/2)/total scores * 100`

# CloudWatch metrics that you can collect with CloudWatch RUM
<a name="CloudWatch-RUM-metrics"></a>

The tables in this section lists the metrics that you automatically collect with CloudWatch RUM from web applications, mobile applications, or both. You can see these metrics in the CloudWatch console. For more information, see [View available metrics](viewing_metrics_with_cloudwatch.md).

You can also optionally send extended metrics to CloudWatch. For more information, see [Extended metrics](CloudWatch-RUM-custom-and-extended-metrics.md#CloudWatch-RUM-vended-metrics).

These metrics are published in the metric namespace named `AWS/RUM`. All of the following metrics are published with an `application_name` dimension. The value of this dimension is the name of the app monitor. Some metrics are also published with additional dimensions, as listed in the following table.


**Web metrics**  

| Metric | Unit | Description | 
| --- | --- | --- | 
|  `HttpStatusCodeCount` |  Count  |  The count of HTTP responses in the application, by their response status code. Additional dimensions: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html)  | 
|  `Http4xxCount` |  Count  |  The count of HTTP responses in the application, with 4xx response status code. These are calculated based on `http_event` RUM events that result in 4xx codes.  | 
|  `Http4xxCountPerSession` |  Count  |  The count of HTTP responses in a session, with 4xx response status code. These are calculated based on `http_event` RUM events that result in 4xx codes.  | 
|  `Http4xxCountPerPageView` |  Count  |  The count of HTTP responses in a page review, with 4xx response status code. These are calculated based on `http_event` RUM events that result in 4xx codes.  | 
|  `Http5xxCount` |  Count  |  The count of HTTP responses in the application, with 5xx response status code. These are calculated based on `http_event` RUM events that result in 5xx codes.  | 
|  `Http5xxCountPerSession` |  Count  |  The count of HTTP responses in the session, with 5xx response status code. These are calculated based on `http_event` RUM events that result in 5xx codes.  | 
|  `Http5xxCountPerPageView` |  Count  |  The count of HTTP responses in a page review, with 5xx response status code. These are calculated based on `http_event` RUM events that result in 5xx codes.  | 
|  `JsErrorCount` |  Count  |  The count of JavaScript error events ingested.   | 
|  `JsErrorCountPerSession` |  Count  |  The count of JavaScript error events ingested in a session.  | 
|  `JsErrorCountPerPageView` |  Count  |  The count of JavaScript error events ingested in a page review.  | 
|  `NavigationFrustratedTransaction` |  Count  |  The count of navigation events with a `duration` higher than the frustrating threshold, which is 8000ms. The duration of navigation events is tracked in the `PerformanceNavigationDuration` metric.  | 
|  `NavigationSatisfiedTransaction` |  Count  |  The count of navigation events with a `duration` that is less than the Apdex objective, which is 2000ms. The duration of navigation events is tracked in the `PerformanceNavigationDuration` metric.  | 
|  `NavigationToleratedTransaction` |  Count  |  The count of navigation events with a `duration` between 2000ms and 8000ms. The duration of navigation events is tracked in the `PerformanceNavigationDuration` metric.  | 
|  `PageViewCount` |  Count  |  The count of page view events ingested by the app monitor. This is calculated by counting the `page_view_event` RUM events.  | 
|  `PageViewCountPerSession` |  Count  |  The count of page view events in a session. | 
|  `PerformanceResourceDuration` |  Milliseconds  |  The `duration` of a resource event. Additional dimensions: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html)  | 
|  `PerformanceNavigationDuration` |  Milliseconds  |  The `duration` of a navigation event.  | 
|  `RumEventPayloadSize` |  Bytes  |  The size of every event ingested by CloudWatch RUM. You can also use the `SampleCount` statistic for this metric to monitor the number of events that an app monitor is ingesting.  | 
|  `SessionCount` |  Count  |  The count of session start events ingested by the app monitor. In other words, the number of new sessions started.  | 
|  `SessionDuration` |  Milliseconds  |  The duration of a session. These are calculated based on the time between first and last events in a session.  | 
|  `TimeOnPage` |  Milliseconds  |  The duration of a page view. These are calculated based on the time until next page view, except for the final page in a session where it's the time between first and last events on that page.  | 
|  `WebVitalsCumulativeLayoutShift` |  None  |  Tracks the value of the cumulative layout shift events.  | 
|  `WebVitalsFirstInputDelay` |  Milliseconds  |  Tracks the value of the first input delay events.  | 
|  `WebVitalsLargestContentfulPaint` |  Milliseconds  |  Tracks the value of the largest contentful paint events.  | 
|  `WebVitalsInteractionToNextPaint` |  Milliseconds  |  Tracks the value of the interaction to next paint events.  | 

You can configure extended metrics for your mobile application to provide additional dimensions for analysis.


**Mobile metrics**  

| Metric | Unit | Description | 
| --- | --- | --- | 
|  `ANRCount`  |  Count  |  For Android only: The number of Application Not Responding (ANR) incidents, occurring when the application is unresponsive for more than 5 seconds, resulting in application crash.  | 
|  `AppHangCount`  |  Count  |  For iOS only: The number of times the application became unresponsive for more than 250ms on the main loop.  | 
|  `ColdAppLaunchFrustratedTransaction`  |  Count  |  The number of cold app launches that took longer than 8 seconds to complete, likely causing user frustration.  | 
|  `ColdAppLaunchSatisfiedTransaction`  |  Count  |  The number of cold app launches that completed in less than 2 seconds, providing a satisfactory user experience.  | 
|  `ColdAppLaunchToleratedTransaction`  |  Count  |  The number of cold app launches that completed between 2 and 8 seconds, providing a tolerable, but not ideal, user experience.  | 
|  `ColdLaunchTime`  |  Milliseconds  |  Time taken to launch the application from a terminated state. For Android: Time from Application `onCreate` until the first Activity finishes creating. For iOS: Time from application start (determined by `sysctl` process start command) until `didBecomeActiveNotification`.  | 
|  `CrashCount`  |  Count  |  The number of unexpected application terminations caused by unhandled exceptions or OS termination. For Android: Crashes due to unhandled exceptions or system termination. For iOS: Crashes due to unhandled exceptions, fatal errors, or system termination. Crash data is stored locally and reported on next app launch.  | 
|  `DroppedEventsCount`  |  Count  |  The number of log events that were dropped because they exceeded the maximum size limit of 30KB per event.  | 
|  `DroppedSpansCount`  |  Count  |  The number of spans that were dropped because they exceeded the maximum size limit of 30KB per span.  | 
|  `Http4xxCount`  |  Count  |  Records the number of HTTP client errors encountered by the web or mobile application during HTTP requests.  | 
|  `Http5xxCount`  |  Count  |  Records the number of HTTP server errors encountered by the web or mobile application during HTTP requests.  | 
|  `LogPayloadSize`  |  Bytes  |  The size in bytes of the log telemetry data being sent to CloudWatch RUM. You can also use the `SampleCount` statistic for this metric to monitor the number of Log Events that an app monitor is ingesting.  | 
|  `NetworkLatency`  |  Milliseconds  |  The time taken for network requests to complete, measuring the round-trip time from request initiation to response completion.  | 
|  `ScreenLoadCount`  |  Count  |  The total number of screen loads.  | 
|  `ScreenLoadToleratedTransaction`  |  Count  |  The number of screen loads that completed between 2 and 8 seconds, providing a tolerable, but not ideal, user experience.  | 
|  `SessionCount`  |  Count  |  The total number of unique user sessions with the application. A session begins when the user opens the app and ends after 30 minutes of inactivity or when explicitly terminated.  | 
|  `SpanPayloadSize`  |  Bytes  |  The size in bytes of the span telemetry data being sent to CloudWatch RUM. You can also use the `SampleCount` statistic for this metric to monitor the number of Spans that an app monitor is ingesting.  | 
|  `WarmAppLaunchFrustratedTransaction`  |  Count  |  The number of warm app launches that took longer than 8 seconds to complete, likely causing user frustration.  | 
|  `WarmAppLaunchSatisfiedTransaction`  |  Count  |  The number of warm app launches that completed in less than 2 seconds, providing a satisfactory user experience.  | 
|  `WarmAppLaunchToleratedTransaction`  |  Count  |  The number of warm app launches that completed between 2 and 8 seconds, providing a tolerable, but not ideal, user experience.  | 
|  `WarmLaunchTime`  |  Milliseconds  |  Time taken to launch the application from background state. For Android: Time from Application `onCreate` until the first Activity finishes creating. For iOS: Time from `UIApplicationWillEnterForegroundNotification` until `didBecomeActiveNotification`.  | 

# Custom metrics and extended metrics that you can send to CloudWatch
<a name="CloudWatch-RUM-custom-and-extended-metrics"></a>

By default, RUM app monitors send metrics to CloudWatch. These default metrics and dimensions are listed in [CloudWatch metrics that you can collect with CloudWatch RUM](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html).

You can also set up an app monitor to export metric. The app monitor can send extended metrics, custom metrics, or both. It can send them to CloudWatch.
+ **Custom metrics**— Custom metrics are metrics that you define. With custom metrics, you can use any metric name and namespace. To derive the metrics, you can use any custom events, built-in events, custom attributes, or default attributes.

  You can send custom metrics to CloudWatch.
+ **Extended metrics**— You can send any of the default CloudWatch RUM metrics to CloudWatch with additional dimensions. This way, these metrics can give you a more fine-grained view.

**Topics**
+ [

## Custom metrics
](#CloudWatch-RUM-custom-metrics)
+ [

## Extended metrics
](#CloudWatch-RUM-vended-metrics)

## Custom metrics
<a name="CloudWatch-RUM-custom-metrics"></a>

To send custom metrics, you must use the AWS APIs or AWS CLI instead of the console. For more information about using the AWS APIs, see [PutRumMetricsDestination](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_PutRumMetricsDestination.html) and [BatchCreateRumMetricDefinitions](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_BatchCreateRumMetricDefinitions.html).

The maximum number of extended metric and custom metric definitions that one destination can contain is 2000. For each custom metric or extended metric that you send to each destination, each combination of dimension name and dimension value counts toward this limit. You are not charged for custom metrics derived from any kind of events or attributes of CloudWatch RUM.

The following example shows how to create a custom metric derived from a custom event. Here is the example custom event that is used:

```
cwr('recordEvent', {
    type: 'my_custom_event', 
    data: {
        location: 'IAD', 
        current_url: 'amazonaws.com', 
        user_interaction: {
            interaction_1 : "click",
            interaction_2 : "scroll"
        }, 
        visit_count:10
    }
})
```

Given this custom event, you can create a custom metric that counts the number of visits to the `amazonaws.com` URL from Chrome browsers. The following definition creates a metric named `AmazonVisitsCount` in your account, in the `RUM/CustomMetrics/PageVisits` namespace.

```
{
    "AppMonitorName":"customer-appMonitor-name",
    "Destination":"CloudWatch",
    "MetricDefinitions":[
        {
            "Name":"AmazonVisitsCount",
            "Namespace":"PageVisit",
            "ValueKey":"event_details.visit_count",
            "UnitLabel":"Count",
            "DimensionKeys":{
                "event_details.current_url": "URL"
            },
            "EventPattern":"{\"metadata\":{\"browserName\":[\"Chrome\"]},\"event_type\":[\"my_custom_event\"],\"event_details\": {\"current_url\": [\"amazonaws.com\"]}}" 
        }
    ]
}
```

## Extended metrics
<a name="CloudWatch-RUM-vended-metrics"></a>

If you set up extended metrics, you can send any of the default CloudWatch RUM metrics to CloudWatch with additional dimensions so that the metrics give you a more fine-grained view.

For more information about the default CloudWatch RUM metrics, see [CloudWatch metrics that you can collect with CloudWatch RUM](CloudWatch-RUM-metrics.md).

The maximum number of extended metric and custom metric definitions that one destination can contain is 2000. For each extended or custom metric that you send to each destination, each combination of dimension name and dimension value counts as an extended metric for this limit.

When you send extended metrics to CloudWatch, you can use the CloudWatch RUM console to create CloudWatch alarms on them.

You are not charged for extended metrics that are created for the default metrics of CloudWatch RUM.

### Web Application Extended Metrics
<a name="CloudWatch-RUM-web-extended-metrics"></a>

The following dimensions are supported for web application extended metrics:
+ `BrowserName`

  Example dimension values: `Chrome`, `Firefox`, `Chrome Headless`
+ `CountryCode` This uses the ISO-3166 format, with two-letter codes.

  Example dimension values: `US`, `JP`, `DE`
+ `DeviceType`

  Example dimension values: `desktop`, `mobile`, `tablet`, `embedded`
+ `FileType`

  Example dimension values: `Image`, `Stylesheet`
+ `OSName`

  Example dimension values: `Linux`, `Windows`, `iOS`, `Android`
+ `PageId`

### Mobile Application Extended Metrics
<a name="CloudWatch-RUM-mobile-extended-metrics"></a>

The following dimensions are supported for mobile application extended metrics:
+ `ScreenName`
  + Value from the screen name attribute - `attributes.screen.name` of your application
  + Example values: HomeScreen, SettingsView, ProfilePage
+ `DeviceModel`
  + Value from the device model attribute - `resource.attributes.device.model.name`
  + Example values: iPhone14,3, SM-G998B
+ `OSVersion`
  + Value from the operating system version attribute - `resource.attributes.os.version`
  + Example values: 16.0, 13.0

**Note**  
Currently supported default metrics for mobile applications: `ScreenLoadTime`, `ScreenLoadCount`, `NetworkLatency`, `Http4xxCount`, `Http5xxCount`, `CrashCount`, `ANRCount`, `AppHangCount`, `ColdLaunchTime`, `WarmLaunchTime`, `SessionCount`, `SpanPayloadSize` and `LogPayloadSize`.

### Set up extended metrics using the console
<a name="CloudWatch-RUM-extended-metrics-console"></a>

To use the console to send extended metrics to CloudWatch, use the following steps.

For information about using the AWS APIs to send extended metrics to either CloudWatch, see [PutRumMetricsDestination](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_PutRumMetricsDestination.html) and [BatchCreateRumMetricDefinitions](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_BatchCreateRumMetricDefinitions.html).

**To use the console to set up an app monitor and send RUM extended metrics to CloudWatch**

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**, **RUM**.

1. Choose the name of the app monitor that is to send the metrics.

1. Choose the **Configuration** tab and then choose **RUM extended metrics**.

1. Choose **Send metrics**.

1. Select one or more metric names to send with additional dimensions.

1. Select one or more factors to use as dimensions for these metrics. As you make your choices, the number of extended metrics that your choices create is displayed in **Number of extended metrics**.

   This number is calculated by multiplying the number of chosen metric names by the number of different dimensions that you create.

   1. To send a metric with page ID as a dimension, choose **Browse for page ID** and then select the page IDs to use.

   1. To send a metric with device type as a dimension, choose either **Desktop devices** or **Mobile and tablets**.

   1. To send a metric with operating system as a dimension, select one or more operating systems under **Operating system**.

   1. To send a metric with browser type as a dimension, select one or more browsers under **Browsers**.

   1. To send a metric with geolocation as a dimension, select one or more locations under **Locations**.

      Only the locations where this app monitor has reported metrics from will appear in the list to choose from.

1. When you are finished with your choices, choose **Send metrics**.

1. (Optional) In the **Extended metrics** list, to create an alarm that watches one of the metrics, choose **Create alarm** in that metric's row.

   For general information about CloudWatch alarms, see [Using Amazon CloudWatch alarms](CloudWatch_Alarms.md). For a tutorial for setting an alarm on a CloudWatch RUM extended metric, see [Tutorial: create an extended metric and alarm it](#CloudWatch-RUM-extended-metrics-alarmtutorial).

**Stop sending extended metrics**

**To use the console to stop sending extended metrics**

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**, **RUM**.

1. Choose the name of the app monitor that is to send the metrics.

1. Choose the **Configuration** tab and then choose **RUM extended metrics**.

1. Select one or more metric name and dimension combinations to stop sending. Then choose **Actions**, **Delete**.

### Tutorial: create an extended metric and alarm it
<a name="CloudWatch-RUM-extended-metrics-alarmtutorial"></a>

This tutorial demonstrates how to set up an extended metric to be sent to CloudWatch, and then how to set an alarm on that metric. In this tutorial, you create a metric that tracks JavaScript errors on the Chrome browser.

**To set up this extended metric and set an alarm on it**

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**, **RUM**.

1. Choose the name of the app monitor that is to send the metric.

1. Choose the **Configuration** tab and then choose **RUM extended metrics**.

1. Choose **Send metrics**.

1. Select **JSErrorCount**.

1. Under **Browsers**, select **Chrome**.

   This combination of **JSErrorCount** and **Chrome** will send one extended metric to CloudWatch. The metric counts JavaScript errors only for user sessions that use the Chrome browser. The metric name will be **JsErrorCount** and the dimension name will be **Browser**.

1. Choose **Send metrics**.

1. In the **Extended metrics** list, choose **Create alarm** in the row that displays **JsErrorCount** under **Name** and displays **Chrome** under **BrowserName**.

1. Under **Specify metric and conditions**, confirm that the **Metric name** and **BrowserName** fields are pre-filled with the correct values.

1. For **Statistic**, select the statistic that you want to use for the alarm. **Average** is a good choice for this type of counting metric.

1. For **Period**, select **5 minutes**.

1. Under **Conditions**, do the following:
   + Choose **Static**.
   + Choose **Greater** to specify that the alarm should go into ALARM state when the number of errors is higher than the threshold you are about to specify.
   + Under **than...**, enter the number for the alarm threshold. The alarm goes into ALARM state when the number of errors over a 5-minute period exceeds this number.

1. (Optional) By default, the alarm goes into ALARM state as soon as the number of errors exceeds the threshold number you set during a 5-minute period. You can optionally change this so that the alarm goes into ALARM state only if this number is exceeded for more than one 5-minute period.

   To do so, choose **Additional configuration** and then for **Datapoints to alarm**, specify how many 5-minute periods need to have the error number over the threshold to trigger the alarm. For example, you can select 2 out of 2 to have the alarm trigger only when two consecutive 5-minute periods are over the threshold, or 2 out of 3 to have the alarm trigger if any two of three consecutive 5-minute periods are over the threshold. 

   For more information about this type of alarm evaluation, see [Alarm evaluation](alarm-evaluation.md).

1. Choose **Next**.

1. For **Configure actions**, specify what should happen when the alarm goes into alarm state. To receive a notification with Amazon SNS, do the following:
   + Choose **Add notification**.
   + Choose **In alarm**.
   + Either select an existing SNS topic or create a new one. If you create a new one, specify a name for it and add at least one email address to it.

1. Choose **Next**.

1. Enter a name and optional description for the alarm, and choose **Next**.

1. Review the details and choose **Create alarm**.

# Data protection and data privacy with CloudWatch RUM
<a name="CloudWatch-RUM-privacy"></a>

The AWS [ shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) applies to data protection and data privacy in Amazon CloudWatch RUM. As described in this model, AWS is responsible for protecting the global infrastructure that runs all of the AWS cloud. You are responsible for maintaining control over your content that is hosted on this infrastructure. For more information about data privacy, see the [ Data Privacy FAQ](https://aws.amazon.com/compliance/data-privacy-faq/). For information about data protection in Europe, see [ The AWS Shared Responsibility Model and GDPR](https://aws.amazon.com/blogs/security/the-aws-shared-responsibility-model-and-gdpr/) blog post on the AWS Security Blog. For more resources about complying with GDPR requirements, see the [ General Data Protection Regulation (GDPR) Center](https://aws.amazon.com/compliance/gdpr-center/).

Amazon CloudWatch RUM generates a code snippet for you to embed into your website or web application code, based on your input of end user data that you want to collect. The web client, downloaded and configured by the code snippet, uses cookies (or similar technologies) to help you collect end user data. The use of cookies (or similar technologies) is subject to data privacy regulations in certain jurisdictions. Before using Amazon CloudWatch RUM, we strongly recommend that you assess your compliance obligations under applicable law, including any applicable legal requirements to provide legally adequate privacy notices and obtain any necessary consents for the use of cookies and the processing (including collection) of end user data. For more information about how the web client uses cookies (or similar technologies) and what end-user data the web client collects, see [Information collected by the CloudWatch RUM web client](CloudWatch-RUM-datacollected.md) and [CloudWatch RUM web client cookies (or similar technologies)](#CloudWatch-RUM-cookies).

We strongly recommend that you never put sensitive identifying information, such as your end users’ account numbers, email addresses, or other personal information, into free-form fields. Any data that you enter into Amazon CloudWatch RUM or other services might be included in diagnostic logs. 



## CloudWatch RUM web client cookies (or similar technologies)
<a name="CloudWatch-RUM-cookies"></a>

The CloudWatch RUM web client collects certain data about user sessions by default. You can choose to enable cookies to have the web client collect a user ID and session ID that persist across page loads. The user ID is randomly generated by RUM.

If these cookies are enabled, RUM is able to display the following types of data when you view the RUM dashboard for this app monitor.
+ Aggregated data based on user IDs, such as number of unique users and the number of different users who experienced an error. 
+ Aggregated data based on session IDs, such as number of sessions and the number of sessions that experienced an error. 
+ The *user journey*, which is the sequence of pages that each sampled user session includes. 

**Important**  
If you do not enable these cookies (or similar technologies), the web client still records certain information about end user sessions such as browser type/version, operating system type/version, device type, and so on. These are collected to provide aggregated page-specific insights, such as web vitals, page views, and pages that experienced errors. For more information about the data recorded, see [Information collected by the CloudWatch RUM web client](CloudWatch-RUM-datacollected.md).

# Information collected by the CloudWatch RUM web client
<a name="CloudWatch-RUM-datacollected"></a>

This section documents the **PutRumEvents** schema, which defines the structure of the data that you can collect from user sessions using CloudWatch RUM.

A **PutRumEvents** request sends a data structure with the following fields to CloudWatch RUM.
+ The ID of this batch of RUM events
+ App monitor details, which includes the following:
  + App monitor ID
  + Monitored application version
+ User details, which includes the following.** This is collected only if the app monitor has cookies enabled.**
  + A user ID generated by the web client
  + Session ID
+ The array of [RUM events](#CloudWatch-RUM-datacollected-event) in this batch.

## RUM event schema
<a name="CloudWatch-RUM-datacollected-event"></a>

The structure of each RUM event includes the following fields.
+ The ID of the event
+ A timestamp
+ The event type
+ The user agent
+ [Metadata](#CloudWatch-RUM-datacollected-metadata)
+ [RUM event details](#CloudWatch-RUM-datacollected-eventDetails)

## RUM event metadata
<a name="CloudWatch-RUM-datacollected-metadata"></a>

The metadata includes page metadata, user agent metadata, geolocation metadata, and domain metadata.

### Page metadata
<a name="CloudWatch-RUM-datacollected-metadata-page"></a>

The page metadata includes the following:
+ Page ID
+ Page title
+ Parent page ID. – **This is collected only if the app monitor has cookies enabled.**
+ Interaction depth – **This is collected only if the app monitor has cookies enabled.**
+ Page tags – You can add tags to page events to group pages together. For more information, see [Use page groups](CloudWatch-RUM-page-groups.md).

### User agent metadata
<a name="CloudWatch-RUM-datacollected-metadata-useragent"></a>

The user agent metadata includes the following:
+ Browser language
+ Browser name
+ Browser version
+ Operating system name
+ Operating system version
+ Device type
+ Platform type

### Geolocation metadata
<a name="CloudWatch-RUM-datacollected-metadata-geolocation"></a>

The geolocation metadata includes the following:
+ Country code
+ Subdivision code

### Domain metadata
<a name="CloudWatch-RUM-datacollected-metadata-domain"></a>

The domain metadata includes the URL domain.

## RUM event details
<a name="CloudWatch-RUM-datacollected-eventDetails"></a>

The details of an event follow one of the following type of schemas, depending on the event type.

### Session start event
<a name="CloudWatch-RUM-datacollected-sessionstart"></a>

This event contains no fields. **This is collected only if the app monitor has cookies enabled.**

### Page view schema
<a name="CloudWatch-RUM-datacollected-pageview"></a>

A **Page view** event contains the following properties. You can deactivate page view collection by configuring the web client. For more information, see the [ CloudWatch RUM web client documentation](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md).


| Name | Type | Description | 
| --- | --- | --- | 
|  **Page ID** |  String  |  An ID that uniquely represents this page within the application. By default, this is the URL path.  | 
|  **Parent page ID** |  String  |  The ID of the page that the user was on when they navigated to the current page. **This is collected only if the app monitor has cookies enabled.**   | 
|  **Interaction depth** |  String  |  **This is collected only if the app monitor has cookies enabled.**   | 

### JavaScript error schema
<a name="CloudWatch-RUM-datacollected-JavaScriptError"></a>

JavaScript error events generated by the agent contain the following properties. The web client collects these events only if you selected to collect the errors telemetry.


| Name | Type | Description | 
| --- | --- | --- | 
|  **Error type** |  String  |  The error's name, if one exists. For more information, see [Error.prototype.name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name). Some browsers might not support error types.  | 
|  **Error message** |  String  |  The error's message. For more information, see [Error.prototype.message](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message). If the error field does not exist, this is the message of the error event. For more information, see [ErrorEvent](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent).  Error messages might not be consistent across different browsers.  | 
|  **Stack trace** |  String  |  The error's stack trace, if one exists, truncated to 150 characters. For more information, see [Error.prototype.stack](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack).  Some browsers might not support stack traces.  | 

### DOM event schema
<a name="CloudWatch-RUM-datacollected-DOMEvent"></a>

Document object model (DOM) events generated by the agent contain the following properties. These events are not collected by default. They are collected only if you activate the interactions telemetry. For more information, see the [ CloudWatch RUM web client documentation](https://github.com/aws-observability/aws-rum-web/blob/main/docs/cdn_installation.md).


| Name | Type | Description | 
| --- | --- | --- | 
|  **Event** |  String  |  The type of DOM event, such as click, scroll, or hover. For more information, see [Event reference](https://developer.mozilla.org/en-US/docs/Web/Events).  | 
|  **Element** |  String  |  The DOM element type  | 
|  **Element ID** |  String  |  If the element that generated the event has an ID, this property stores that ID. For more information, see [Element.id](https://developer.mozilla.org/en-US/docs/Web/API/Element/id).  | 
|  **CSSLocator** |  String  |  The CSS locator used to identify the DOM element.  | 
|  **InteractionId** |  String  |  A unique ID for the interaction between the user and the UI.  | 

### Navigation event schema
<a name="CloudWatch-RUM-datacollected-NavigationEvent"></a>

Navigation events are collected only if the app monitor has performance telemetry activated.

Navigation events use [Navigation timing Level 1](https://www.w3.org/TR/navigation-timing/#performancetiming) and [Navigation timing Level 2](https://w3c.github.io/navigation-timing) APIs. Level 2 APIs are not supported on all browsers, so these newer fields are optional.

**Note**  
Timestamp metrics are based on [DOMHighResTimestamp](https://www.w3.org/TR/hr-time-2/#sec-domhighrestimestamp). With Level 2 APIs, all timings are by default relative to the `startTime`. But for Level 1, the `navigationStart` metric is subtracted from timestamp metrics to obtain relative values. All timestamp values are in milliseconds.

Navigation events contain the following properties.


| Name | Type | Description | Notes | 
| --- | --- | --- | --- | 
|  **initiatorType** |  String  |  Represents the type of resource that initiated the performance event.  |  **Value:** "navigation" **Level 1:** "navigation" **Level 2:** entryData.initiatorType | 
|  **navigationType** |  String  |  Represents the type of navigation. This attribute is not required. |  **Value:** The value must be one of the following: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-datacollected.html) | 
|  **startTime** |  Number  |  Indicates when the event is triggered.  |  **Value:** 0 **Level 1:** entryData.navigationStart - entryData.navigationStart  **Level 2:** entryData.startTime | 
|  **unloadEventStart** |  Number  |  Indicates the time when the previous document in the window began to unload after the `unload` event was thrown.  |  **Value:** If there is no previous document or if the previous document or one of the needed redirects is not of the same origin, the value returned is 0. **Level 1:** <pre>entryData.unloadEventStart > 0<br />  ? entryData.unloadEventStart - entryData.navigationStart<br />  : 0<br /></pre> **Level 2:** entryData.unloadEventStart | 
|  **promptForUnload** |  Number  |  The time taken to unload the document. In other words, the time between `unloadEventStart` and `unloadEventEnd`. `UnloadEventEnd` represents the moment in milliseconds when the unload event handler finishes.  |  **Value:** If there is no previous document or if the previous document or one of the needed redirects is not of the same origin, the value returned is 0. **Level 1:** entryData.unloadEventEnd - entryData.unloadEventStart **Level 2:** entryData.unloadEventEnd - entryData.unloadEventStart | 
|  **redirectCount** |  Number  |  A number representing the number of redirects since the last non-redirect navigation under the current browsing context.  This attribute is not required. |  **Value:** If there is no redirect or if there is any redirect that is not of the same origin as the destination document, the value returned is 0. **Level 1:** Not available **Level 2:** entryData.redirectCount | 
|  **redirectStart** |  Number  |  The time when the first HTTP redirect starts.   |  **Value:** If there is no redirect or if there is any redirect that is not of the same origin as the destination document, the value returned is 0. **Level 1:** <pre>entryData.redirectStart > 0<br />  ? entryData.redirectStart - entryData.navigationStart<br />  : 0</pre> **Level 2:** entryData.redirectStart | 
|  **redirectTime** |  Number  |  The time taken for the HTTP redirect. This is the difference between `redirectStart` and `redirectEnd`.   |  **Level 1:** : entryData.redirectEnd - entryData.redirectStart **Level 2:** : entryData.redirectEnd - entryData.redirectStart | 
|  **workerStart** |  Number  |  This is a property of the `PerformanceResourceTiming` interface. It marks the beginning of worker thread operation. This attribute is not required. |  **Value:** If a Service Worker thread is already running, or immediately before starting the Service Worker thread, this property returns the time immediately before dispatching `FetchEvent`. It returns 0 if the resource is not intercepted by a Service Worker. **Level 1:** Not available **Level 2:** entryData.workerStart | 
|  **workerTime** |  Number  |  If the resource is intercepted by a Service Worker, this returns the time required for worker thread operation. This attribute is not required. |  **Level 1:** Not available  **Level 2:** <pre>entryData.workerStart > 0<br />   ? entryData.fetchStart - entryData.workerStart<br />   : 0</pre>  | 
|  **fetchStart** |  Number  |  The time when the browser is ready to fetch the document using an HTTP request. This is before checking any application cache. |  **Level 1:**  <pre>: entryData.fetchStart > 0<br />  ? entryData.fetchStart - entryData.navigationStart<br />  : 0</pre> **Level 2:** entryData.fetchStart | 
|  **domainLookupStart** |  Number  |  The time when the domain lookup starts. |  **Value:** If a persistent connection is used or if the information is stored in a cache or local resource, the value will be the same as `fetchStart`. **Level 1:** <pre>entryData.domainLookupStart > 0<br />  ? entryData.domainLookupStart - entryData.navigationStart<br />  : 0</pre> **Level 2:** entryData.domainLookupStart | 
|  **dns** |  Number  |  The time required for domain lookup. |  **Value:** If the resources and DNS records are cached, the expected value is 0. **Level 1:** entryData.domainLookupEnd - entryData.domainLookupStart **Level 2:** entryData.domainLookupEnd - entryData.domainLookupStart | 
|  **nextHopProtocol** |  String  |  A string representing the network protocol used to fetch the resource. This attribute is not required. |  **Level 1:** Not available **Level 2:** entryData.nextHopProtocol | 
|  **connectStart** |  Number  |  The time immediately before the user agent starts establishing the connection to the server to retrieve the document. |  **Value:** If an RFC2616 persistent connection is used, or if the current document is retrieved from relevant application caches or local resources, this attribute returns the value of `domainLookupEnd`. **Level 1:** <pre>entryData.connectStart > 0<br />  ? entryData.connectStart - entryData.navigationStart<br />  : 0</pre> **Level 2:** entryData.connectStart  | 
|  **connect** |  Number  |  Measures the time required to establish the transport connections or to perform SSL authentication. It also includes the blocked time that is taken when there are too many concurrent requests issued by the browser.  |  **Level 1:** entryData.connectEnd - entryData.connectStart **Level 2:** entryData.connectEnd - entryData.connectStart | 
|  **secureConnectionStart** |  Number  |  If the URL scheme of the current page is "https", this attribute returns the time immediately before the user agent starts the handshake process to secure the current connection. It returns 0 if HTTPS is not used. For more information about URL schemes, see [URL representation](https://url.spec.whatwg.org/#concept-url-scheme).  |  **Formula:** entryData.secureConnectionStart | 
|  **tlsTime** |  Number  |  The time taken to complete an SSL handshake.  |  **Level 1:** <pre>entryData.secureConnectionStart > 0<br />   ? entryData.connectEnd - entryData.secureConnectionStart<br />   : 0</pre> **Level 2:** <pre>entryData.secureConnectionStart > 0<br />   ? entryData.connectEnd - entryData.secureConnectionStart<br />   : 0</pre>  | 
|  **requestStart** |  Number  |  The time immediately before the user agent starts requesting the resource from the server, or from relevant application caches, or from local resources.   | **Level 1:** <pre>: entryData.requestStart > 0<br />  ? entryData.requestStart - entryData.navigationStart<br />  : 0<br /></pre> **Level 2:** entryData.requestStart | 
|  **timeToFirstByte** |  Number  |  The time taken to receive the first byte of information after a request is made. This time is relative to the `startTime`.   | **Level 1:** entryData.responseStart - entryData.requestStart **Level 2:** entryData.responseStart - entryData.requestStart | 
|  **responseStart** |  Number  |  The time immediately after the user agent's HTTP parser receives the first byte of the response from the relevant application caches, or from local resources, or from the server.   | **Level 1:** <pre>entryData.responseStart > 0<br />   ? entryData.responseStart - entryData.navigationStart<br />   : 0</pre> **Level 2:** entryData.responseStart   | 
|  **responseTime** |  String  |  The time taken to receive a complete response in the form of bytes from the relevant application caches, or from local resources, or from the server.   | **Level 1:** <pre>entryData.responseStart > 0<br />  ? entryData.responseEnd - entryData.responseStart<br />  : 0</pre> **Level 2:** <pre>entryData.responseStart > 0<br />  ? entryData.responseEnd - entryData.responseStart<br />  : 0</pre>  | 
|  **domInteractive** |  Number  |  The time when the parser finished its work on the main document, and the HTML DOM is constructed. At this time, its `Document.readyState` changes to "interactive" and the corresponding `readystatechange` event is thrown.  | **Level 1:** <pre>entryData.domInteractive > 0<br />  ? entryData.domInteractive - entryData.navigationStart<br />  : 0</pre> **Level 2:** entryData.domInteractive  | 
|  **domContentLoadedEventStart** |  Number  |  Represents the time value equal to the time immediately before the user agent fires the DOMContentLoaded event at the current document. TheDOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed. At this time, the main HTML document has finished parsing, the browser begins constructing the render tree, and subresources still have to be loaded. This does not wait for style sheets, images, and subframes to finish loading.  | **Level 1:** <pre>entryData.domContentLoadedEventStart > 0<br />  ? entryData.domContentLoadedEventStart - entryData.navigationStart<br />  : 0<br /></pre> **Level 2:** entryData.domContentLoadedEventStart  | 
|  **domContentLoaded** |  Number  |  This start and end time of render tree construction is marked by the `domContentLoadedEventStart` and `domContentLoadedEventEnd`. It lets CloudWatch RUM track execution. This property is the difference between `domContentLoadedStart` and `domContentLoadedEnd`. During this time, DOM and CSSOM are ready. This property waits on script execution, except for asynchronous and dynamically created scripts. If the scripts depend on style sheets, `domContentLoaded` waits on the style sheets, too. It does not wait on images.   The actual values of `domContentLoadedStart` and `domContentLoadedEnd` approximate to `domContentLoaded` in Google Chrome's Network panel. It indicates HTML DOM \$1 CSSOM render tree construction time from the beginning of the page loading process. In the case of navigation metrics, the `domContentLoaded` value represents the difference between start and end values, which is the time required for downloading subresources and render-tree construction only.    | **Level 2:** entryData.domContentLoadedEventEnd - entryData.domContentLoadedEventStart  **Level 2:** entryData.domContentLoadedEventEnd - entryData.domContentLoadedEventStart  | 
|  **domComplete** |  Number  |  The time immediately before the browser sets the current document readiness of the current document to complete. At this point, the loading of subresources, such as images, is complete. This includes the time taken for downloading blocking content such as CSS and synchronous JavaScript. This approximates to `loadTime` in Google Chrome’s Network panel.   | **Level 1:** <pre>entryData.domComplete > 0<br />  ? entryData.domComplete - entryData.navigationStart<br />  : 0<br /></pre> **Level 2:** entryData.domComplete  | 
|  **domProcessingTime** |  Number  |  The total time between the response and the load event start.  | **Level 1:** entryData.loadEventStart - entryData.responseEnd **Level 2:** entryData.loadEventStart - entryData.responseEnd  | 
|  **loadEventStart** |  Number  |  The time immediately before the `load` event of the current document is fired.  |  **Level 1:** <pre>entryData.loadEventStart > 0<br />  ? entryData.loadEventStart - entryData.navigationStart<br />  : 0<br /></pre> **Level 2:** entryData.loadEventStart | 
|  **loadEventTime** |  Number  |  The difference between `loadEventStart` and `loadEventEnd`. Additional functions or logic waiting for this load event will be fired during this time. |  **Level 1:** entryData.loadEventEnd - entryData.loadEventStart **Level 2:** entryData.loadEventEnd - entryData.loadEventStart | 
|  **duration** |  String  |  Duration is the total page load time. It records the timing for downloading the main page and all of its synchronous subresources, and also for rendering the page. Asynchronous resources such as scripts continue to download later. This is the difference between the `loadEventEnd` and `startTime` properties.  | **Level 1:** entryData.loadEventEnd - entryData.navigationStart **Level 2:** entryData.duration | 
|  **headerSize** |  Number  |  Returns the difference between `transferSize` and `encodedBodySize`. This attribute is not required.  | **Level 1:** Not available **Level 2:** entryData.transferSize - entryData.encodedBodySize **Level 2:** entryData.transferSize - entryData.encodedBodySize | 
|  **compressionRatio** |  Number  |  The ratio of `encodedBodySize` and `decodedBodySize`. The value of `encodedBodySize` is the compressed size of the resource excluding the HTTP headers. The value of `decodedBodySize` is the decompressed size of the resource excluding the HTTP headers. This attribute is not required.  | **Level 1:** Not available. **Level 2:**<pre>entryData.encodedBodySize > 0<br />  ? entryData.decodedBodySize / entryData.encodedBodySize<br />  : 0</pre>  | 
|  **navigationTimingLevel** |  Number  |  The navigation timing API version.  | **Value:** 1 or 2  | 

### Resource event schema
<a name="CloudWatch-RUM-datacollected-ResourceEvent"></a>

Resource events are collected only if the app monitor has performance telemetry activated.

Timestamp metrics are based on [The DOMHighResTimeStamp typedef](https://www.w3.org/TR/hr-time-2/#sec-domhighrestimestamp). With Level 2 APIs, by default all timings are relative to the `startTime`. But for Level 1 APIs, the `navigationStart` metric is subtracted from timestamp metrics to obtain relative values. All timestamp values are in milliseconds.

Resource events generated by the agent contain the following properties.


| Name | Type | Description | Notes | 
| --- | --- | --- | --- | 
|  **targetUrl** |  String  |  Returns the resource's URL.  |  **Formula:** [entryData.name](http://entrydata.name/) | 
|  **initiatorType** |  String  |  Represents the type of resource that initiated the performance resource event.  |  **Value:** "resource" **Formula:** entryData.initiatorType | 
|  **duration** |  String  |  Returns the difference between the `responseEnd` and `startTime` properties.This attribute is not required.  | **Formula:** entryData.duration | 
|  **transferSize** |  Number  |  Returns the size (in octets) of the fetched resource, including the response header fields and the response payload body.This attribute is not required.  | **Formula:** entryData.transferSize | 
|  **fileType** |  String  |  Extensions derived from the target URL pattern.  |   | 

### Largest contentful paint event schema
<a name="CloudWatch-RUM-datacollected-LargestPaintEvent"></a>

Largest contentful paint events contain the following properties.

These events are collected only if the app monitor has performance telemetry activated.


| Name | Description | 
| --- | --- | 
|  **Value** |  For more information, see [Web Vitals](https://web.dev/vitals/).  | 

### First input delay event
<a name="CloudWatch-RUM-datacollected-FirstInputDelayEvent"></a>

First input delay events contain the following properties.

These events are collected only if the app monitor has performance telemetry activated.


| Name | Description | 
| --- | --- | 
|  **Value** |  For more information, see [Web Vitals](https://web.dev/vitals/).  | 

### Cumulative layout shift event
<a name="CloudWatch-RUM-datacollected-CumulativeShift"></a>

Cumulative layout shift events contain the following properties.

These events are collected only if the app monitor has performance telemetry activated.


| Name | Description | 
| --- | --- | 
|  **Value** |  For more information, see [Web Vitals](https://web.dev/vitals/).  | 

### HTTP event
<a name="CloudWatch-RUM-datacollected-HTTP"></a>

HTTP events can contain the following properties. It will contain either a `Response` field or an `Error` field, but not both.

These events are collected only if the app monitor has HTTP telemetry activated.


| Name | Description | 
| --- | --- | 
|  **Request** |  The request field includes the following: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-datacollected.html)  | 
|  **Response** |  The response field includes the following: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-datacollected.html)  | 
|  **Error** |  The error field includes the following: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-datacollected.html)  | 

### X-Ray trace event schema
<a name="CloudWatch-RUM-datacollected-xraytraceEvent"></a>

These events are collected only if the app monitor has X-Ray tracing activated.

For information about X-Ray trace event schemas, see [AWS X-Ray segment documents](https://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html).

# Route change timing for single-page applications
<a name="CloudWatch-RUM-route-change-timing"></a>

In a traditional multi-page application, when a user requests for new content to be loaded, the user is actually requesting a new HTML page from the server. As a result, the CloudWatch RUM web client captures the load times using the regular performance API metrics.

However, single-page web applications use JavaScript and Ajax to update the interface without loading a new page from the server. Single-page updates are not recorded by the browser timing API, but instead use route change timing.

CloudWatch RUM supports the monitoring of both full page loads from the server and single-page updates, with the following differences:
+ For route change timing, there are no browser-provided metrics such as `tlsTime`, `timeToFirstByte`, and so on.
+ For route change timing, the `initiatorType` field will be `route_change`. 

The CloudWatch RUM web client listens to user interactions that may lead to a route change, and when such a user interaction is recorded, the web client records a timestamp. Then route change timing will begin if both of the following are true:
+ A browser history API (except browser forward and back buttons) was used to perform the route change.
+ The difference between the time of route change detection and latest user interaction timestamp is less than 1000 ms. This avoids data skew.

Then, once route change timing begins, that timing completes if there are no ongoing AJAX requests and DOM mutations. Then the timestamp of the latest completed activity will be used as the completion timestamp.

Route change timing will time out if there are ongoing AJAX requests or DOM mutations for more than 10 seconds (by default). In this case, the CloudWatch RUM web client will no longer record timing for this route change.

As a result, the duration of a route change event is calculated as the following:

```
(time of latest completed activity) - (latest user interaction timestamp)
```

# Manage your applications that use CloudWatch RUM
<a name="CloudWatch-RUM-manage"></a>

Use the steps in these sections to manage your applications' use of CloudWatch RUM.

**Topics**
+ [

# How do I find a code snippet that I've already generated?
](CloudWatch-RUM-find-code-snippet.md)
+ [

# Editing your CloudWatch RUM app monitor settings
](CloudWatch-RUM-edit-application.md)
+ [

# Stopping using CloudWatch RUM or deleting an app monitor
](CloudWatch-RUM-delete-appmonitor.md)

# How do I find a code snippet that I've already generated?
<a name="CloudWatch-RUM-find-code-snippet"></a>

To find a CloudWatch RUM code snippet that you've already generated for an application, follow these steps.

**To find a code snippet that you've already generated**

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**, **RUM**.

1. Navigate to the **Configuration** tab, **Code snippets** section.

1. Choose **Copy/Download** for your respective instrumentation.

# Editing your CloudWatch RUM app monitor settings
<a name="CloudWatch-RUM-edit-application"></a>

To change an app monitor's settings, follow these steps. You can change any settings except the app monitor name.

**To edit how your application uses CloudWatch RUM**

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**, **RUM**.

1. Choose the button next to the name of the application, and then choose **Actions**, **Edit**.

1. Change any settings except the application name. For more information about the settings, see [Creating a CloudWatch RUM app monitor for a web application](CloudWatch-RUM-get-started-create-app-monitor.md).

1. When finished, choose **Save**.

   Changing the settings changes the code snippet. You must now paste the updated code snippet into your application.

1. After the code snippet is created, choose **Copy to clipboard** or **Download**, and then choose **Done**.

   To start monitoring with the new settings, you insert the code snippet into your application.

# Stopping using CloudWatch RUM or deleting an app monitor
<a name="CloudWatch-RUM-delete-appmonitor"></a>

To stop using CloudWatch RUM with an application, remove the code snippet that RUM generated from your application's code.

To delete a RUM app monitor, follow these steps.

**To delete an app monitor**

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**, **RUM**.

1. Choose the button next to the name of the application, and then choose **Actions**, **Delete**.

1. In the confirmation box, enter **Delete** and then choose **Delete**.

1. If you haven't done so already, delete the CloudWatch RUM code snippet from your application's code.

# Troubleshooting CloudWatch RUM
<a name="CloudWatch-RUM-troubleshooting"></a>

This section contains tips to help you troubleshoot CloudWatch RUM.

## There is no data for my application
<a name="CloudWatch-RUM-troubleshooting-nodata"></a>

First, make sure that the code snippet has been correctly inserted into your application. For more information, see [Inserting the CloudWatch app monitor code snippet into your application](CloudWatch-RUM-get-started-insert-code-snippet.md).

If that is not the issue, then maybe there has been no traffic to your application yet. Generate some traffic by accessing your application the same way that a user would.

## Data has stopped being recorded for my application
<a name="CloudWatch-RUM-troubleshooting-nonewdata"></a>

Your application might have been updated and now no longer contains a CloudWatch RUM code snippet. Check your application code.

Another possibility is that someone may have updated the code snippet but then didn't insert the updated snippet into the application. Find the current correct code snippet by following the directions in [How do I find a code snippet that I've already generated?](CloudWatch-RUM-find-code-snippet.md) and compare it to the code snippet that is pasted into your application.