

# 为 API Gateway 中的 REST API 设置 CloudWatch 日志记录
<a name="set-up-logging"></a>

 为了帮助调试与请求执行或客户端对 API 的访问的相关问题，您可以启用 Amazon CloudWatch Logs 以记录 API 调用。有关 CloudWatch 的更多信息，请参阅[使用 Amazon CloudWatch 指标监控 REST API 执行](monitoring-cloudwatch.md)。

## 用于 API Gateway 的 CloudWatch 日志格式
<a name="apigateway-cloudwatch-log-formats"></a>

 在 CloudWatch 中有两种类型的 API 日志记录：执行日志记录和访问日志记录。在执行日志记录中，API Gateway 管理 CloudWatch Logs。该过程包括创建日志组和日志流，以及向日志流报告任意调用方的请求和响应。

记录的数据包括错误或执行跟踪（例如，请求或响应的参数值或负载）、Lambda 授权方（以前称为自定义授权方）使用的数据、是否需要 API 密钥、是否启用了使用计划以及其它信息。API Gateway 会从记录的数据中删除授权标头、API 密钥值和类似的敏感请求参数。

为了改善您的安全状况，我们建议您使用 `ERROR` 或 `INFO` 级别的执行日志记录。为遵守各种合规性框架，您可能需要执行此操作。有关更多信息，请参阅《AWS Security Hub User Guide》**中的 [Amazon API Gateway Controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)。

部署 API 时，API Gateway 创建日志组和日志组下的日志流。日志组以 `API-Gateway-Execution-Logs_{rest-api-id}/{stage_name}` 格式命名。在每个日志组内，日志进一步划分到日志流中，后者在报告记录的数据时按照**上次事件时间**排序。

在访问日志记录中，作为 API 开发人员，您想要记录谁访问了您的 API 以及调用方访问 API 的方式。您可以创建自己的日志组，或者选择可由 API Gateway 管理的现有日志组。要指定访问详细信息，可以选择 [`$context`](api-gateway-variables-for-access-logging.md) 变量、日志格式和日志组目标。

访问日志格式必须至少包括 `$context.requestId` 或 `$context.extendedRequestId`。作为最佳实践，请在日志格式中包含 `$context.requestId` 和 `$context.extendedRequestId`。

**`$context.requestId`**  
这会将值记录在 `x-amzn-RequestId` 标头中。客户端可以用通用唯一标识符 (UUID) 格式的值覆盖 `x-amzn-RequestId` 标头中的值。API Gateway 返回 `x-amzn-RequestId` 响应标头中的此请求 ID。API Gateway 将不采用 UUID 格式的被覆盖的请求 ID 替换为访问日志中的 `UUID_REPLACED_INVALID_REQUEST_ID`。

**`$context.extendedRequestId`**  
extendedRequestID 是 API Gateway 生成的唯一 ID。API Gateway 返回 `x-amz-apigw-id` 响应标头中的此请求 ID。API 调用者无法提供或覆盖此请求 ID。您可能需要向 AWS Support 提供此值，来协助排查 API 的问题。有关更多信息，请参阅 [API Gateway 的访问日志记录的变量](api-gateway-variables-for-access-logging.md)。

选择您的分析后端也采用的日志格式，例如[常用日志格式](https://httpd.apache.org/docs/current/logs.html#common) (CLF)、JSON、XML 或 CSV。然后，您可以将访问日志直接输送到其中，以计算和呈现您的指标。要定义日志格式，请在[阶段](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html)的 [accessLogSettings/destinationArn](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#destinationArn) 属性上设置日志组 ARN。您可以在 CloudWatch 控制台中获取日志组 ARN。要定义访问日志格式，请在[阶段](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html)的 [accessLogSetting/format](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#format) 属性上设置选定格式。

一些常用访问日志格式的示例在 API Gateway 控制台中显示，下面列出了这些格式。
+ `CLF`（[常用日志格式](https://httpd.apache.org/docs/current/logs.html#common)）：

  ```
  $context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime]"$context.httpMethod $context.resourcePath $context.protocol" $context.status $context.responseLength $context.requestId $context.extendedRequestId
  ```
+  `JSON`: 

  ```
  { "requestId":"$context.requestId", "extendedRequestId":"$context.extendedRequestId","ip": "$context.identity.sourceIp", "caller":"$context.identity.caller", "user":"$context.identity.user", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod", "resourcePath":"$context.resourcePath", "status":"$context.status", "protocol":"$context.protocol", "responseLength":"$context.responseLength" }
  ```
+ `XML`: 

  ```
  <request id="$context.requestId"> <extendedRequestId>$context.extendedRequestId</extendedRequestId> <ip>$context.identity.sourceIp</ip> <caller>$context.identity.caller</caller> <user>$context.identity.user</user> <requestTime>$context.requestTime</requestTime> <httpMethod>$context.httpMethod</httpMethod> <resourcePath>$context.resourcePath</resourcePath> <status>$context.status</status> <protocol>$context.protocol</protocol> <responseLength>$context.responseLength</responseLength> </request>
  ```
+ `CSV`（逗号分隔值）：

  ```
  $context.identity.sourceIp,$context.identity.caller,$context.identity.user,$context.requestTime,$context.httpMethod,$context.resourcePath,$context.protocol,$context.status,$context.responseLength,$context.requestId,$context.extendedRequestId
  ```

## CloudWatch 日志记录的权限
<a name="set-up-access-logging-permissions"></a>

要启用 CloudWatch Logs，您必须向 API Gateway 授予权限，才能针对您的账户读取日志和将日志写入到 CloudWatch。[AmazonAPIGatewayPushToCloudWatchLogs](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonAPIGatewayPushToCloudWatchLogs.html) 具有所需的全部权限。

**注意**  
API Gateway 将调用 AWS Security Token Service 以恢复 IAM 角色，因此请确保已为区域启用 AWS STS。有关更多信息，请参阅[在AWS区域中管理AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)。

要将这些权限授予您的账户，请使用 `apigateway.amazonaws.com` 作为其可信实体创建一个 IAM 角色，将之前的策略附加到此 IAM 角色，然后在您[账户](https://docs.aws.amazon.com/apigateway/latest/api/API_GetAccount.html)的 [cloudWatchRoleArn](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAccount.html#cloudWatchRoleArn) 属性上设置 IAM 角色 ARN。您必须为要在其中启用 CloudWatch Logs 的每个AWS区域单独设置 [cloudWatchRoleArn](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAccount.html#cloudWatchRoleArn) 属性。

如果您在设置 IAM 角色 ARN 时收到错误，请检查您的 AWS Security Token Service 账户设置，以确保在您所使用的区域中启用了 AWS STS。有关启用 AWS STS 的更多信息，请参阅 *IAM 用户指南*中的在AWS区域中[管理AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html#sts-regions-activate-deactivate)。

## 使用 API Gateway 控制台设置 CloudWatch API 日志记录
<a name="set-up-access-logging-using-console"></a>

要设置 CloudWatch API 日志记录，您必须已经将 API 部署到某个阶段。您还必须已经为账户配置了[合适的 CloudWatch Logs 角色](#set-up-access-logging-permissions) ARN。

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 在主导航窗格上选择**设置**，然后在**日志记录**下选择**编辑**。

1. 对于 **CloudWatch 日志角色 ARN**，输入具有相应权限的 IAM 角色的 ARN。对于每个使用 API Gateway 创建 API 的 AWS 账户，您都需要执行一次此操作。

1. 在主导航窗格中，选择 **API**，然后执行以下操作之一：

   1.  选择现有 API，然后选择一个阶段。

   1.  创建 API，然后将其部署到阶段。

1. 在主导航窗格中，选择**阶段**。

1.  在**日志和跟踪**部分中，选择**编辑**。

1. 启用执行日志记录：

   1. 从 **CloudWatch Logs** 下拉菜单中选择日志记录级别。日志记录级别如下所示：
      + **关闭** - 不对此阶段开启日志记录。
      + **仅限错误** - 仅对错误启用日志记录。
      + **错误和信息日志** - 对所有事件启用日志记录。

   1. （可选）选择**数据跟踪**，来为阶段启用数据跟踪日志记录。这对于排除 API 故障非常有用，但可能会导致记录敏感数据。
**注意**  
建议不要为生产 API 启用**数据跟踪**。

   1. （可选）选择**详细指标**来开启详细的 CloudWatch 指标。

   有关 CloudWatch 指标的更多信息，请参阅[使用 Amazon CloudWatch 指标监控 REST API 执行](monitoring-cloudwatch.md)。

1. 启用访问日志记录：

   1. 开启**自定义访问日志记录**。

   1. 对于**访问日志目标 ARN**，输入日志组的 ARN。ARN 格式为 `arn:aws:logs:{region}:{account-id}:log-group:log-group-name`。

   1. 对于**日志格式**，输入日志格式。您可以选择 **CLF**、**JSON**、**XML** 或 **CSV**。要了解有关示例日志格式的更多信息，请参阅[用于 API Gateway 的 CloudWatch 日志格式](#apigateway-cloudwatch-log-formats)。

1. 选择**保存更改**。

**注意**  
您可以分别启用执行日志记录和访问日志记录，这两者相互独立。

API Gateway 现已准备好记录对您 API 的请求。在更新阶段设置、日志或阶段变量时，您无需重新部署 API。

## 使用 CloudFormation 设置 CloudWatch API 日志记录
<a name="set-up-access-logging-using-cloudformation"></a>

使用以下示例 CloudFormation 模板创建 Amazon CloudWatch Logs 日志组并配置阶段的执行和访问日志记录。要启用 CloudWatch Logs，您必须向 API Gateway 授予权限，才能针对您的账户读取日志和将日志写入到 CloudWatch。要了解更多信息，请参阅《AWS CloudFormation 用户指南》**中的[将账户与 IAM 角色关联](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-account.html#aws-resource-apigateway-account--examples)。

```
  TestStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      StageName: test
      RestApiId: !Ref MyAPI
      DeploymentId: !Ref Deployment
      Description: "test stage description"
      MethodSettings:
        - ResourcePath: "/*"
          HttpMethod: "*"
          LoggingLevel: INFO
      AccessLogSetting:
        DestinationArn: !GetAtt MyLogGroup.Arn
        Format: $context.extendedRequestId $context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime] "$context.httpMethod $context.resourcePath $context.protocol" $context.status $context.responseLength $context.requestId
  MyLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Join
        - '-'
        - - !Ref MyAPI
          - access-logs
```