

# Monitor WebSocket APIs in API Gateway
<a name="websocket-api-monitor"></a>

You can use CloudWatch metrics and CloudWatch Logs to monitor WebSocket APIs. By combining logs and metrics, you can log errors and monitor your API's performance.

**Note**  
API Gateway might not generate logs and metrics in the following cases:  
413 Request Entity Too Large errors
Excessive 429 Too Many Requests errors
400 series errors from requests sent to a custom domain that has no API mapping
500 series errors caused by internal failures

**Topics**
+ [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md)
+ [Configure logging for WebSocket APIs in API Gateway](websocket-api-logging.md)

# Monitor WebSocket API execution with CloudWatch metrics
<a name="apigateway-websocket-api-logging"></a>

You can use [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) metrics to monitor WebSocket APIs. The configuration is similar to that used for REST APIs. For more information, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md).

The following metrics are supported for WebSocket APIs:


| Metric | Description | 
| --- | --- | 
| ConnectCount | The number of messages sent to the \$1connect route integration. | 
| MessageCount | The number of messages sent to the WebSocket API, either from or to the client. | 
| IntegrationError | The number of requests that return a 4XX/5XX response from the integration. | 
| ClientError | The number of requests that have a 4XX response returned by API Gateway before the integration is invoked. | 
| ExecutionError | Errors that occurred when calling the integration. | 
| IntegrationLatency | The time difference between API Gateway sending the request to the integration and API Gateway receiving the response from the integration. Suppressed for callbacks and mock integrations. | 

You can use the dimensions in the following table to filter API Gateway metrics.


| Dimension | Description | 
| --- | --- | 
| ApiId | Filters API Gateway metrics for an API with the specified API ID. | 
| ApiId, Stage | Filters API Gateway metrics for an API stage with the specified API ID and stage ID. | 
| ApiId, Method, Resource, Stage |  Filters API Gateway metrics for an API method with the specified API ID, stage ID, resource path, and route ID. API Gateway will not send these metrics unless you have explicitly enabled detailed CloudWatch metrics. You can do this by calling the [UpdateStage](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-stages-stagename.html) action of the API Gateway V2 REST API to update the `detailedMetricsEnabled` property to `true`. Alternatively, you can call the [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) AWS CLI command to update the `DetailedMetricsEnabled` property to `true`. Enabling such metrics will incur additional charges to your account. For pricing information, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/).  | 

# Configure logging for WebSocket APIs in API Gateway
<a name="websocket-api-logging"></a>

You can enable logging to write logs to CloudWatch Logs. There are two types of API logging in CloudWatch: execution logging and access logging. In execution logging, API Gateway manages the CloudWatch Logs. The process includes creating log groups and log streams, and reporting to the log streams any caller's requests and responses. 

To improve your security posture, we recommend that you use execution logging at the `ERROR` or `INFO` level. You might need to do this to comply with various compliance frameworks. For more information, see [Amazon API Gateway controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html) in the *AWS Security Hub User Guide*.

In access logging, you, as an API developer, want to log who has accessed your API and how the caller accessed the API. You can create your own log group or choose an existing log group that could be managed by API Gateway. To specify the access details, you select `$context` variables (expressed in a format of your choosing) and choose a log group as the destination.

For instructions on how to set up CloudWatch logging, see [Set up CloudWatch API logging using the API Gateway console](set-up-logging.md#set-up-access-logging-using-console).

When you specify the **Log Format**, you can choose which context variables to log. The following variables are supported.


| Parameter | Description | 
| --- | --- | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$1context.authorize.error | The authorization error message. | 
| \$1context.authorize.latency | The authorization latency in ms. | 
| \$1context.authorize.status | The status code returned from an authorization attempt. | 
| \$1context.authorizer.error | The error message returned from an authorizer. | 
| \$1context.authorizer.integrationLatency | The Lambda authorizer latency in ms. | 
| \$1context.authorizer.integrationStatus | The status code returned from a Lambda authorizer. | 
| \$1context.authorizer.latency | The authorizer latency in ms. | 
| \$1context.authorizer.requestId | The AWS endpoint's request ID. | 
| \$1context.authorizer.status | The status code returned from an authorizer. | 
| \$1context.authorizer.principalId |  The principal user identification that is associated with the token sent by the client and returned from an API Gateway Lambda authorizer Lambda function. (A Lambda authorizer was formerly known as a custom authorizer.)  | 
| \$1context.authorizer.property |  The stringified value of the specified key-value pair of the `context` map returned from an API Gateway Lambda authorizer function. For example, if the authorizer returns the following `context` map:  <pre>"context" : {<br />                            "key": "value",<br />                            "numKey": 1,<br />                            "boolKey": true<br />                            }</pre> calling `$context.authorizer.key` returns the `"value"` string, calling `$context.authorizer.numKey` returns the `"1"` string, and calling `$context.authorizer.boolKey` returns the `"true"` string.  | 
| \$1context.authenticate.error | The error message returned from an authentication attempt. | 
| \$1context.authenticate.latency | The authentication latency in ms. | 
| \$1context.authenticate.status | The status code returned from an authentication attempt. | 
| \$1context.connectedAt |  The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted connection time.  | 
| \$1context.connectionId |  A unique ID for the connection that can be used to make a callback to the client.  | 
| \$1context.domainName |  A domain name for the WebSocket API. This can be used to make a callback to the client (instead of a hardcoded value).  | 
| \$1context.error.message |  A string that contains an API Gateway error message.  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  The error response type.  | 
| \$1context.error.validationErrorString |  A string that contains a detailed validation error message.  | 
| \$1context.eventType |  The event type: `CONNECT`, `MESSAGE`, or `DISCONNECT`.  | 
| \$1context.extendedRequestId | Equivalent to \$1context.requestId. | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  The API owner key associated with key-enabled API request.  | 
| \$1context.identity.apiKeyId | The API key ID associated with the key-enabled API request | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for routes that use IAM authorization.  | 
| \$1context.identity.cognitoAuthenticationProvider |  A comma-separated list of all the Amazon Cognito authentication providers used by the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  For example, for an identity from an Amazon Cognito user pool, `cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` For information about the available Amazon Cognito authentication providers, see [Using Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) in the *Amazon Cognito Developer Guide*. | 
| \$1context.identity.cognitoAuthenticationType |  The Amazon Cognito authentication type of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. Possible values include `authenticated` for authenticated identities and `unauthenticated` for unauthenticated identities. | 
| \$1context.identity.cognitoIdentityId |  The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.cognitoIdentityPoolId |  The Amazon Cognito identity pool ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.principalOrgId |  The [AWS organization ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html). Supported for routes that use IAM authorization.  | 
| \$1context.identity.sourceIp |  The source IP address of the TCP connection making the request to API Gateway.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for routes that use IAM authorization.  | 
| \$1context.identity.userAgent |  The user agent of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication.  | 
| \$1context.integration.error | The error message returned from an integration. | 
| \$1context.integration.integrationStatus | For Lambda proxy integration, the status code returned from AWS Lambda, not from the backend Lambda function code. | 
| \$1context.integration.latency | The integration latency in ms. Equivalent to \$1context.integrationLatency. | 
| \$1context.integration.requestId | The AWS endpoint's request ID. Equivalent to \$1context.awsEndpointRequestId. | 
| \$1context.integration.status | The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns. Equivalent to \$1context.integrationStatus. | 
| \$1context.integrationLatency | The integration latency in ms, available for access logging only. | 
| \$1context.messageId |  A unique server-side ID for a message. Available only when the `$context.eventType` is `MESSAGE`.  | 
| \$1context.requestId |  Same as `$context.extendedRequestId`.  | 
| \$1context.requestTime | The [CLF](https://httpd.apache.org/docs/current/logs.html#common)-formatted request time (dd/MMM/yyyy:HH:mm:ss \$1-hhmm). | 
| \$1context.requestTimeEpoch | The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted request time, in milliseconds. | 
| \$1context.routeKey |  The selected route key.  | 
| \$1context.stage |  The deployment stage of the API call (for example, beta or prod).  | 
| \$1context.status |  The response status.  | 
| \$1context.waf.error | The error message returned from AWS WAF. | 
| \$1context.waf.latency | The AWS WAF latency in ms. | 
| \$1context.waf.status | The status code returned from AWS WAF. | 

Examples of some commonly used access log formats are shown in the API Gateway console and are listed as follows.
+ `CLF` ([Common Log Format](https://httpd.apache.org/docs/current/logs.html#common)):

  ```
  $context.identity.sourceIp $context.identity.caller \
  $context.identity.user [$context.requestTime] "$context.eventType $context.routeKey $context.connectionId" \
  $context.status $context.requestId
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+  `JSON`: 

  ```
  {
  "requestId":"$context.requestId", \
  "ip": "$context.identity.sourceIp", \
  "caller":"$context.identity.caller", \
  "user":"$context.identity.user", \
  "requestTime":"$context.requestTime", \
  "eventType":"$context.eventType", \
  "routeKey":"$context.routeKey", \
  "status":"$context.status", \
  "connectionId":"$context.connectionId"
  }
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+ `XML`: 

  ```
  <request id="$context.requestId"> \
   <ip>$context.identity.sourceIp</ip> \
   <caller>$context.identity.caller</caller> \
   <user>$context.identity.user</user> \
   <requestTime>$context.requestTime</requestTime> \
   <eventType>$context.eventType</eventType> \
   <routeKey>$context.routeKey</routeKey> \
   <status>$context.status</status> \
   <connectionId>$context.connectionId</connectionId> \
  </request>
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+ `CSV` (comma-separated values):

  ```
  $context.identity.sourceIp,$context.identity.caller, \
  $context.identity.user,$context.requestTime,$context.eventType, \
  $context.routeKey,$context.connectionId,$context.status, \
  $context.requestId
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.