

# 使用 Lambda 函数日志
<a name="monitoring-logs"></a>

为帮助您排除故障，AWS Lambda 会代表您自动监控 Lambda 函数。您可以借助 Lambda 控制台、CloudWatch 控制台、AWS Command Line Interface（AWS CLI）或 CloudWatch API 查看 Lambda 函数的日志。您还可以配置 Lambda 以将日志发送到 Amazon S3 和 Firehose。

只要函数的[执行角色](lambda-intro-execution-role.md)具有必要的权限，Lambda 就会捕获函数处理的所有请求的日志，并将其发送到 Amazon CloudWatch Logs（即默认目标）。您还可以使用 Lambda 控制台将 Amazon S3 或 Firehose 配置为日志记录目标。
+ **CloudWatch Logs** 是 Lambda 函数的默认日志记录目标。CloudWatch Logs 提供实时日志查看和分析功能，并支持根据您的日志数据创建指标和警报。
+ **Amazon S3** 对于长期存储来说经济实惠，并且可以使用 Athena 等服务来分析日志。延迟通常较高。
+ **Firehose** 提供将日志流式传输到各个目标的托管服务。如果您需要将日志发送到其他 AWS 服务（例如，OpenSearch Service 或 Redshift Data API）或第三方平台（如 Datadog、New Relic 或 Splunk），Firehose 会通过提供预构建的集成来简化该过程。您也可以流式传输到自定义 HTTP 端点，而无需设置其他基础设施。

## 选择要向其发送日志的服务目标
<a name="choosing-log-destination"></a>

选择服务作为函数日志的目标时，请考虑以下关键因素：
+ **成本管理因服务而异。**Amazon S3 通常为长期存储提供最经济的选择，而 CloudWatch Logs 允许您实时查看日志、处理日志和设置警报。Firehose 成本包括流媒体服务和与您配置流媒体相关的成本。
+ **分析功能因服务而异。**CloudWatch Logs 擅长实时监控，并与其他 CloudWatch 功能（例如 Logs Insights 和 Live Tail）原生集成。Amazon S3 可以很好地与 Athena 等分析工具配合使用，并且可以与各种服务集成，但可能需要额外的设置。Firehose 通过提供预构建的集成简化了到特定 AWS 服务（如 OpenSearch Service 和 Redshift Data API）和支持的第三方平台（如 Datadog 和 Splunk）的直接流式传输，从而可能减少配置工作。
+ **设置和易用性因服务而异。**CloudWatch Logs 是默认的日志目标 – 它无需额外配置即可立即运行，并通过 CloudWatch 控制台提供直接的日志查看和分析。如果需要将日志发送到 Amazon S3，则需要在 Lambda 控制台中进行一些初始设置并配置存储桶权限。如果需要将日志直接发送到 OpenSearch Service 等服务或第三方分析平台，则 Firehose 可以简化该流程。

## 配置日志目标
<a name="configuring-log-destinations"></a>

AWS Lambda 支持函数日志的多个目标。本指南说明可用的日志记录目标，并帮助您根据需要选择合适的选项。无论您选择哪个目标，Lambda 都会提供控制日志格式、筛选和传输的选项。

Lambda 支持 JSON 和纯文本格式的函数日志。JSON 结构化日志提供增强的可搜索性并支持自动分析，而纯文本日志则提供简单性并有可能降低存储成本。您可以通过配置系统日志和应用程序日志的日志级别来控制 Lambda 发送到所选目标的日志。筛选可以帮助您管理存储成本，并使您在调试期间更容易找到相关的日志条目。

有关每个目标的详细设置说明，请参阅以下各节：
+ [将 Lambda 函数日志发送到 CloudWatch Logs](monitoring-cloudwatchlogs.md)
+ [将 Lambda 函数日志发送到 Firehose](logging-with-firehose.md)
+ [将 Lambda 函数日志发送到 Amazon S3](logging-with-s3.md)

## 为 Lambda 函数配置高级日志记录控件
<a name="monitoring-cloudwatchlogs-advanced"></a>

为了让您可以更好地控制如何捕获、处理和使用函数日志，Lambda 提供了以下日志配置选项：
+ **日志格式** - 为函数日志选择纯文本或结构化的 JSON 格式。
+ **日志级别**：对于 JSON 结构化日志，选择 Lambda 发送到 CloudWatch 的日志的详细信息级别，例如 `FATAL`、`ERROR`、`WARN`、`INFO`、`DEBUG` 和 `TRACE`。
+ **日志组** - 选择您的函数发送日志的目标 CloudWatch 日志组。

要了解有关配置高级日志记录控件的更多信息，请参阅以下各节：
+ [配置 JSON 和纯文本日志格式](monitoring-cloudwatchlogs-logformat.md)
+ [日志级别筛选](monitoring-cloudwatchlogs-log-level.md)
+ [配置 CloudWatch 日志组](monitoring-cloudwatchlogs-loggroups.md)

# 配置 JSON 和纯文本日志格式
<a name="monitoring-cloudwatchlogs-logformat"></a>

将日志输出捕获为 JSON 键值对，可以更轻松地在调试函数时进行搜索和筛选。使用 JSON 格式的日志，您还可以在日志中添加标签和上下文信息。这可以帮助您对大量日志数据执行自动分析。除非您的开发工作流程依赖于使用纯文本格式 Lambda 日志的现有工具，否则我们建议您为日志格式选择 JSON。

**Lambda 托管实例**  
Lambda 托管实例仅支持 JSON 日志格式。当您创建托管实例函数时，Lambda 会自动将日志格式配置为 JSON，且您无法将其更改为纯文本格式。有关托管实例的更多信息，请参阅[Lambda 托管实例](lambda-managed-instances.md)。

对于所有 Lambda 托管的运行时系统，您可以选择将函数的系统日志以非结构化纯文本格式还是 JSON 格式发送到 CloudWatch Logs。系统日志是由 Lambda 生成的日志，有时也被称为平台事件日志。

对于[支持的运行时系统](#monitoring-cloudwatchlogs-logformat-supported)，当您使用支持的内置日志记录方法之一时，Lambda 还能以结构化的 JSON 格式输出函数的应用程序日志（您的函数代码生成的日志）。当您为这些运行时系统配置函数的日志格式时，您选择的配置将同时应用于系统日志和应用程序日志。

对于支持的运行时系统，如果您的函数使用支持的日志库或方法，则无需对 Lambda 的现有代码进行任何更改，即可在结构化的 JSON 中捕获日志。

**注意**  
使用 JSON 日志格式可以添加额外的元数据，并将日志消息编码为包含一系列键值对的 JSON 对象。因此，函数日志消息的大小可能会增加。

## 支持的运行时系统和日志记录方法
<a name="monitoring-cloudwatchlogs-logformat-supported"></a>

 Lambda 目前支持为以下运行时系统输出 JSON 结构化应用程序日志的选项。


| 语言 | 支持的版本 | 
| --- | --- | 
| Java | Amazon Linux 1 上除 Java 8 之外的所有 Java 运行时系统 | 
| .NET | .NET 8 及更高版本 | 
| Node.js | Node.js 16 及更高版本 | 
| Python | Python 3.8 及更高版本 | 
| Rust | 不适用 | 

为了让 Lambda 以结构化的 JSON 格式将函数的应用程序日志发送到 CloudWatch，您的函数必须使用以下内置日志记录工具来输出日志：
+ **Java**：`LambdaLogger` 记录器或 Log4j2。有关更多信息，请参阅 [Java Lambda 函数日志记录和监控](java-logging.md)。
+ **.NET**：上下文对象上的 `ILambdaLogger` 实例。有关更多信息，请参阅 [C\$1 Lambda 函数日志记录和监控](csharp-logging.md)。
+ **Node.js**：控制台方法 `console.trace`、`console.debug`、`console.log`、`console.info`、`console.error` 和 `console.warn`。有关更多信息，请参阅 [Node.js Lambda 函数日志记录和监控](nodejs-logging.md)。
+ **Python**：标准 Python `logging` 库。有关更多信息，请参阅 [Python Lambda 函数日志记录和监控](python-logging.md)。
+ **Rust**：`tracing` crate。有关更多信息，请参阅 [Rust Lambda 函数日志记录和监控](rust-logging.md)。

对于其他托管 Lambda 运行时系统，Lambda 本身目前仅支持以结构化的 JSON 格式捕获系统日志。但是，您仍然可以在任何运行时系统中使用输出 JSON 格式日志输出的日志记录工具（例如 Powertools for AWS Lambda），以结构化的 JSON 格式捕获应用程序日志。

## 默认日志格式
<a name="monitoring-cloudwatchlogs-format-default"></a>

目前，所有 Lambda 运行时系统的默认日志格式均为纯文本。对于 Lambda 托管实例，日志格式始终为 JSON，且无法更改。

如果您已经在使用像 Powertools for AWS Lambda 这样的日志库来生成 JSON 结构化格式的函数日志，则在选择 JSON 日志格式后无需更改代码。Lambda 不会对任何已采用 JSON 编码的日志进行双重编码，因此仍将像以前一样捕获函数的应用程序日志。

## 系统日志的 JSON 格式
<a name="monitoring-cloudwatchlogs-JSON-system"></a>

当您将函数的日志格式配置为 JSON 时，每个系统日志项（平台事件）都将被捕获为一个 JSON 对象，并且包含带有以下键的键值对：
+ `"time"` - 生成日志消息的时间
+ `"type"` - 正在记录的事件类型
+ `"record"` - 日志输出的内容

`"record"` 值的格式因所记录的事件类型而异。有关更多信息，请参阅 [遥测 API `Event` 对象类型](telemetry-schema-reference.md#telemetry-api-events)。有关分配给系统日志事件的日志级别的更多信息，请参阅 [系统日志级别的事件映射](monitoring-cloudwatchlogs-log-level.md#monitoring-cloudwatchlogs-log-level-mapping)。

为了进行比较，以下两个示例以纯文本和结构化的 JSON 格式显示了相同的日志输出。请注意，在大多数情况下，系统日志事件以 JSON 格式输出时所含的信息要多于以纯文本格式输出时所含的信息。

**Example 纯文本：**  

```
2024-03-13 18:56:24.046000 fbe8c1   INIT_START  Runtime Version: python:3.12.v18  Runtime Version ARN: arn:aws:lambda:eu-west-1::runtime:edb5a058bfa782cb9cedc6d534ac8b8c193bc28e9a9879d9f5ebaaf619cd0fc0
```

**Example 结构化的 JSON：**  

```
{
  "time": "2024-03-13T18:56:24.046Z",
  "type": "platform.initStart",
  "record": {
    "initializationType": "on-demand",
    "phase": "init",
    "runtimeVersion": "python:3.12.v18",
    "runtimeVersionArn": "arn:aws:lambda:eu-west-1::runtime:edb5a058bfa782cb9cedc6d534ac8b8c193bc28e9a9879d9f5ebaaf619cd0fc0"
  }
}
```

**注意**  
[使用遥测 API 访问扩展的实时遥测数据](telemetry-api.md) 始终以 JSON 格式发出平台事件，例如 `START` 和 `REPORT`。配置 Lambda 发送到 CloudWatch 的系统日志的格式不会影响 Lambda 遥测 API 的行为。

## 应用程序日志的 JSON 格式
<a name="monitoring-cloudwatchlogs-JSON-application"></a>

当您将函数的日志格式配置为 JSON 时，使用支持的日志记录库和方法编写的应用程序日志输出将被捕获为 JSON 对象，其中包含带有以下键的键值对。
+ `"timestamp"` - 生成日志消息的时间
+ `"level"` - 分配给消息的日志级别
+ `"message"` - 日志消息的内容
+ `"requestId"`（Python、.NET 和 Node.js）或 `"AWSrequestId"`（Java）：函数调用的唯一请求 ID

根据函数使用的运行时系统和日志记录方法，此 JSON 对象还可能包含其他密钥对。例如，在 Node.js 中，如果函数通过 `console` 方法使用多个参数记录错误对象，则 JSON 对象将包含带有键 `errorMessage`、`errorType`、和 `stackTrace` 的额外键值对。要了解有关不同 Lambda 运行时系统中的 JSON 格式日志的更多信息，请参阅 [Python Lambda 函数日志记录和监控](python-logging.md)、[Node.js Lambda 函数日志记录和监控](nodejs-logging.md) 和 [Java Lambda 函数日志记录和监控](java-logging.md)。

**注意**  
对于系统日志和应用程序日志，Lambda 用于时间戳值的键不同。对于系统日志，Lambda 使用密钥 `"time"` 来与遥测 API 保持一致。对于应用程序日志，Lambda 遵循支持的运行时系统并使用 `"timestamp"` 的惯例。

为了进行比较，以下两个示例以纯文本和结构化的 JSON 格式显示了相同的日志输出。

**Example 纯文本：**  

```
2024-10-27T19:17:45.586Z 79b4f56e-95b1-4643-9700-2807f4e68189 INFO some log message
```

**Example 结构化的 JSON：**  

```
{
    "timestamp":"2024-10-27T19:17:45.586Z",
    "level":"INFO",
    "message":"some log message",
    "requestId":"79b4f56e-95b1-4643-9700-2807f4e68189"
}
```

## 设置函数的日志格式
<a name="monitoring-cloudwatchlogs-set-format"></a>

要配置函数的日志格式，您可以使用 Lambda 控制台或 AWS Command Line Interface（AWS CLI）。您还可以使用 [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html) 和 [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html) Lambda API 命令、AWS Serverless Application Model（AWS SAM）[AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) 资源以及 CloudFormation [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html) 资源来配置函数的日志格式。

更改函数的日志格式不会影响 CloudWatch Logs 中存储的现有日志。只有新的日志才会使用更新的格式。

如果您将函数的日志格式更改为 JSON 且未设置日志级别，则 Lambda 会自动将函数的应用程序日志级别和系统日志级别设置为 INFO。这意味着 Lambda 仅向 CloudWatch Logs 发送 INFO 及以下级别的日志输出。要了解有关应用程序和系统日志级别筛选的更多信息，请参阅 [日志级别筛选](monitoring-cloudwatchlogs-log-level.md) 

**注意**  
对于 Python 运行时系统，当函数的日志格式设置为纯文本时，默认的日志级别设置为 WARN。这意味着 Lambda 仅向 CloudWatch Logs 发送 WARN 及以下级别的日志输出。将函数的日志格式更改为 JSON 可更改此默认行为。要了解有关 Python 中的日志记录的更多信息，请参阅 [Python Lambda 函数日志记录和监控](python-logging.md)。

对于发出嵌入式指标格式（EMF）日志的 Node.js 函数，将函数的日志格式更改为 JSON 可能会导致 CloudWatch 无法识别您的指标。

**重要**  
如果您的函数使用 Powertools for AWS Lambda（TypeScript）或开源的 EMF 客户端库来发出 EMF 日志，请将 [Powertools](https://github.com/aws-powertools/powertools-lambda-typescript) 和 [EMF](https://www.npmjs.com/package/aws-embedded-metrics) 库更新到最新版本，以确保 CloudWatch 能够继续正确解析您的日志。如果您切换到 JSON 日志格式，我们还建议您进行测试以确保与函数的嵌入式指标兼容。有关发出 EMF 日志的 node.js 函数的更多建议，请参阅 [使用带有结构化的 JSON 日志的嵌入式指标格式（EMF）客户端库](nodejs-logging.md#nodejs-logging-advanced-emf)。

**配置函数的日志格式（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数

1. 在函数配置页面上，选择**监控和操作工具**。

1. 在**日志记录配置**窗格中，选择**编辑**。

1. 在**日志内容**下，为**日志格式**选择**文本**或 **JSON**。

1. 选择**保存**。

**要更改现有函数的日志格式（AWS CLI）**
+ 要更改现有函数的日志格式，请使用 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) 命令。将 `LoggingConfig` 中的 `LogFormat` 选项设置为 `JSON` 或 `Text`。

  ```
  aws lambda update-function-configuration \
    --function-name myFunction \
    --logging-config LogFormat=JSON
  ```

**要在创建函数时设置日志格式（AWS CLI）**
+ 要在创建新函数时配置日志格式，请使用 [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令中的 `--logging-config` 选项。将 `LogFormat` 设置为 `JSON` 或 `Text`。以下示例命令创建 Node.js 函数，该函数以结构化 JSON 格式输出日志。

  如果您在创建函数时未指定日志格式，Lambda 将使用您选择的运行时系统版本的默认日志格式。有关默认日志记录格式的信息，请参阅 [默认日志格式](#monitoring-cloudwatchlogs-format-default)。

  ```
  aws lambda create-function \ 
    --function-name myFunction \ 
    --runtime nodejs24.x \
    --handler index.handler \
    --zip-file fileb://function.zip \
    --role arn:aws:iam::123456789012:role/LambdaRole \
    --logging-config LogFormat=JSON
  ```

# 日志级别筛选
<a name="monitoring-cloudwatchlogs-log-level"></a>

Lambda 可以筛选函数的日志，以便仅将不超过特定详细信息级别的日志发送到 CloudWatch Logs。您可以分别为函数的系统日志（Lambda 生成的日志）和应用程序日志（您的函数代码生成的日志）单独配置日志级别筛选。

对于 [支持的运行时系统和日志记录方法](monitoring-cloudwatchlogs-logformat.md#monitoring-cloudwatchlogs-logformat-supported)，要筛选函数的应用程序日志，无需对 Lambda 的函数代码进行任何更改。

对于所有其他运行时系统和日志记录方法，您的函数代码必须将日志事件作为 JSON 格式的对象输出到 `stdout` 或 `stderr`，并在其中包含键 `"level"` 的键值对。例如，Lambda 将以下到 `stdout` 的输出解释为调试级别的日志。

```
print('{"level": "debug", "msg": "my debug log", "timestamp": "2024-11-02T16:51:31.587199Z"}')
```

如果 `"level"` 值字段无效或缺失，Lambda 将为日志输出分配 INFO 级别。要让 Lambda 使用时间戳字段，您必须以有效的 [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) 时间戳格式指定时间。如果您未提供有效的时间戳，Lambda 将为日志分配 INFO 级别并为您添加时间戳。

命名时间戳键时，请遵循所用运行时系统的惯例。Lambda 支持托管运行时系统使用的大多数常用命名惯例。

**注意**  
要使用日志级别筛选，必须将您的函数配置为使用 JSON 日志格式。目前，所有 Lambda 托管运行时系统的默认日志格式均为纯文本。要了解如何将函数的日志格式配置为 JSON，请参阅 [设置函数的日志格式](monitoring-cloudwatchlogs-logformat.md#monitoring-cloudwatchlogs-set-format)。

对于应用程序日志（由函数代码生成的日志），您可以从以下日志级别中进行选择。


| 日志级别 | 标准使用情况 | 
| --- | --- | 
| TRACE（最详细） | 用于跟踪代码执行路径的最精细信息 | 
| 调试 | 系统调试的详细信息 | 
| INFO | 记录函数正常运行情况的消息 | 
| 警告 | 有关潜在错误的消息，如果不加以解决，这些错误可能会导致意外行为 | 
| ERROR | 有关会阻碍代码按预期执行的问题的消息 | 
| FATAL（最简略） | 有关导致应用程序停止运行的严重错误的消息 | 

当您选择日志级别后，Lambda 会将该级别及更低级别的日志发送到 CloudWatch Logs。例如，如果您将函数的应用程序日志级别设置为 WARN，则 Lambda 不会发送 INFO 和 DEBUG 级别的日志输出。日志筛选的默认应用程序日志级别为 INFO。

当 Lambda 筛选函数的应用程序日志时，将为没有级别的日志消息分配日志级别 INFO。

对于系统日志（由 Lambda 服务生成的日志），您可以在以下日志级别之间进行选择。


| 日志级别 | 用法 | 
| --- | --- | 
| DEBUG（最详细） | 系统调试的详细信息 | 
| INFO | 记录函数正常运行情况的消息 | 
| WARN（最简略） | 有关潜在错误的消息，如果不加以解决，这些错误可能会导致意外行为 | 

当您选择日志级别后，Lambda 会发送该级别及更低级别的日志。例如，如果您将函数的系统日志级别设置为 INFO，则 Lambda 不会发送 DEBUG 级别的日志输出。

默认情况下，Lambda 会将系统日志级别设置为 INFO。使用此设置，Lambda 会自动向 CloudWatch 发送 `"start"` 和 `"report"` 日志消息。要接收不同详细程度的系统日志，请将日志级别更改为 DEBUG 或 WARN。要查看 Lambda 将不同系统日志事件映射到的日志级别列表，请参阅 [系统日志级别的事件映射](#monitoring-cloudwatchlogs-log-level-mapping)。

## 配置日志级别筛选
<a name="monitoring-cloudwatchlogs-log-level-setting"></a>

要为您的函数配置应用程序和系统日志级别的筛选，您可以使用 Lambda 控制台或 AWS Command Line Interface（AWS CLI）。您还可以使用 [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html) 和 [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html) Lambda API 命令、AWS Serverless Application Model（AWS SAM）[AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) 资源以及 CloudFormation [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html) 资源来配置函数的日志级别。

请注意，如果在代码中设置函数的日志级别，则此设置将优先于您配置的任何其他日志级别设置。例如，如果您通过 Python `logging` `setLevel()` 方法将函数的日志级别设置为 INFO，则此设置将优先于您通过 Lambda 控制台配置的 WARN 设置。

**配置现有函数的应用程序或系统日志级别（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数。

1. 在函数配置页面上，选择**监控和操作工具**。

1. 在**日志记录配置**窗格中，选择**编辑**。

1. 在**日志内容**下，确保为**日志格式**选择 **JSON**。

1. 使用单选按钮，为您的函数选择所需的**应用程序日志级别**和**系统日志级别**。

1. 选择**保存**。

**配置现有函数的应用程序或系统日志级别（AWS CLI）**
+ 要更改现有函数的应用程序或系统日志级别，请使用 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) 命令。使用 `--logging-config` 将 `SystemLogLevel` 设为 `DEBUG`、`INFO` 或 `WARN`。将 `ApplicationLogLevel` 设置为 `DEBUG`、`INFO`、`WARN`、`ERROR` 或 `FATAL` 之一。

  ```
  aws lambda update-function-configuration \
    --function-name myFunction \
    --logging-config LogFormat=JSON,ApplicationLogLevel=ERROR,SystemLogLevel=WARN
  ```

**在创建函数时配置日志级别筛选**
+ 要在创建新函数时配置日志级别筛选，请在 [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令中使用 `--logging-config` 来设置 `SystemLogLevel` 和 `ApplicationLogLevel` 键。将 `SystemLogLevel` 设置为 `DEBUG`、`INFO` 或 `WARN` 之一。将 `ApplicationLogLevel` 设置为 `DEBUG`、`INFO`、`WARN`、`ERROR` 或 `FATAL` 之一。

  ```
  aws lambda create-function \
    --function-name myFunction \
    --runtime nodejs24.x \
    --handler index.handler \
    --zip-file fileb://function.zip \
    --role arn:aws:iam::123456789012:role/LambdaRole \ 
    --logging-config LogFormat=JSON,ApplicationLogLevel=ERROR,SystemLogLevel=WARN
  ```

## 系统日志级别的事件映射
<a name="monitoring-cloudwatchlogs-log-level-mapping"></a>

对于 Lambda 生成的系统级日志事件，下表定义了分配给每个事件的日志级别。要了解有关表中所列事件的更多信息，请参阅 [Lambda 遥测 API `Event` 架构参考](telemetry-schema-reference.md)


| 事件名称 | 条件 | 分配的日志级别 | 
| --- | --- | --- | 
| initStart | 已设置 runtimeVersion | INFO | 
| initStart | 未设置 runtimeVersion | 调试 | 
| initRuntimeDone | status=success | 调试 | 
| initRuntimeDone | status\$1=success | 警告 | 
| initReport | initializationType\$1=on-demand | INFO | 
| initReport | initializationType=on-demand | 调试 | 
| initReport | status\$1=success | 警告 | 
| restoreStart | 已设置 runtimeVersion | INFO | 
| restoreStart | 未设置 runtimeVersion | 调试 | 
| restoreRuntimeDone | status=success | 调试 | 
| restoreRuntimeDone | status\$1=success | 警告 | 
| restoreReport | status=success | INFO | 
| restoreReport | status\$1=success | 警告 | 
| 开启 | - | INFO | 
| runtimeDone | status=success | 调试 | 
| runtimeDone | status\$1=success | 警告 | 
| 报告 | status=success | INFO | 
| 报告 | status\$1=success | 警告 | 
| extension | state=success | INFO | 
| extension | state\$1=success | 警告 | 
| logSubscription | - | INFO | 
| telemetrySubscription | - | INFO | 
| logsDropped | - | 警告 | 

**注意**  
[使用遥测 API 访问扩展的实时遥测数据](telemetry-api.md) 始终会发出一整套平台事件。配置 Lambda 发送到 CloudWatch 的系统日志的级别不会影响 Lambda 遥测 API 的行为。

## 使用自定义运行时系统进行应用程序日志级别筛选
<a name="monitoring-cloudwatchlogs-log-level-custom"></a>

当您为函数配置应用程序日志级别筛选时，Lambda 会在后台使用 `AWS_LAMBDA_LOG_LEVEL` 环境变量在运行时系统中设置应用程序日志级别。Lambda 还会使用 `AWS_LAMBDA_LOG_FORMAT` 环境变量设置函数的日志格式。您可以使用这些变量将 Lambda 高级日志记录控件集成到[自定义运行时系统](runtimes-custom.md)中。

要使用自定义运行时系统通过 Lambda 控制台、AWS CLI 和 Lambda API 为函数配置日志记录设置，请配置您的自定义运行时系统以检查这些环境变量的值。然后，您可以根据所选的日志格式和日志级别配置运行时系统的记录器。

# 将 Lambda 函数日志发送到 CloudWatch Logs
<a name="monitoring-cloudwatchlogs"></a>

默认情况下，Lambda 会自动捕获所有函数调用的日志并将其发送到 CloudWatch Logs，前提是您的函数的执行角色具有必要的权限。默认情况下，这些日志存储在名为 /aws/lambda/*<function-name>* 的日志组中。为了增强调试能力，您可以在代码中插入自定义日志记录语句，Lambda 将这些语句与 CloudWatch Logs 无缝集成。如果需要，您可以将函数配置为使用 Lambda 控制台、AWS CLI 或 Lambda API 将日志发送到不同的组。请参阅[配置 CloudWatch 日志组](monitoring-cloudwatchlogs-loggroups.md)，了解更多信息。

您可以借助 Lambda 控制台、CloudWatch 控制台、AWS Command Line Interface (AWS CLI) 或 CloudWatch API 查看 Lambda 函数的日志。有关更多信息，请参阅[查看 Lambda 函数的 CloudWatch 日志](monitoring-cloudwatchlogs-view.md)。

**注意**  
函数调用后，日志可能需要 5 到 10 分钟才能显示。

## 所需的 IAM 权限
<a name="monitoring-cloudwatchlogs-prereqs"></a>

[执行角色](lambda-intro-execution-role.md)必须具备以下权限，才能将日志上传 CloudWatch Logs：
+ `logs:CreateLogGroup`
+ `logs:CreateLogStream`
+ `logs:PutLogEvents`

要了解更多信息，请参阅《Amazon CloudWatch User Guide》中的 [Using identity-based policies (IAM policies) for CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-identity-based-access-control-cwl.html)。**

您可以使用 Lambda 提供的 `AWSLambdaBasicExecutionRole` AWS 托管式策略添加这些 CloudWatch Logs 权限。要将此策略添加到您的角色，请运行以下命令：

```
aws iam attach-role-policy --role-name your-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
```

有关更多信息，请参阅 [在执行角色中使用 AWS 托管策略](permissions-managed-policies.md)。

## 定价
<a name="monitoring-cloudwatchlogs-pricing"></a>

使用 Lambda 日志没有额外的费用；不过，会收取标准 CloudWatch Logs 费用。有关更多信息，请参阅 [CloudWatch 定价](https://aws.amazon.com/cloudwatch/pricing/)。

# 配置 CloudWatch 日志组
<a name="monitoring-cloudwatchlogs-loggroups"></a>

默认情况下，CloudWatch 会在首次调用您的函数时为其自动创建一个名为 `/aws/lambda/<function name>` 的日志组。要将您的函数配置为向现有日志组发送日志，或者为函数创建新的日志组，可以使用 Lambda 控制台或 AWS CLI。您还可以使用 [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html) 和 [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html) Lambda API 命令以及 AWS Serverless Application Model（AWS SAM）[AWS::Serverless::Function]() 资源配置自定义日志组。

您可以配置多个 Lambda 函数向同一 CloudWatch 日志组发送日志。例如，您可以使用单个日志组来存储构成特定应用程序的所有 Lambda 函数的日志。当您为 Lambda 函数使用自定义日志组时，Lambda 创建的日志流包括函数名称和函数版本。这可以确保即使将同一个日志组用于多个函数，也能保留日志消息与函数之间的映射。

自定义日志组的日志流命名格式遵循以下惯例：

```
YYYY/MM/DD/<function_name>[<function_version>][<execution_environment_GUID>]
```

请注意，配置自定义日志组时，您为日志组选择的名称必须遵守 [CloudWatch Logs 命名规则](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html)。此外，自定义日志组名称不得以字符串 `aws/` 开头。如果以 `aws/` 为开头创建自定义日志组，则 Lambda 将无法创建该日志组。这将导致函数的日志不会发送到 CloudWatch。

**更改函数的日志组（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数。

1. 在函数配置页面上，选择**监控和操作工具**。

1. 在**日志记录配置**窗格中，选择**编辑**。

1. 在**日志记录组**窗格中，为 **CloudWatch 日志组**选择**自定义**。

1. 在**自定义日志组**下，输入您希望函数发送日志的目标 CloudWatch 日志组的名称。如果您输入现有日志组的名称，则函数将使用该组。如果不存在具有所输入名称的日志组，则 Lambda 将使用该名称为您的函数创建一个新的日志组。

**更改函数的日志组（AWS CLI）**
+ 要更改现有函数的日志组，请使用 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) 命令。

  ```
  aws lambda update-function-configuration \
    --function-name myFunction \
    --logging-config LogGroup=myLogGroup
  ```

**在创建函数时指定自定义日志组（AWS CLI）**
+ 要在使用 AWS CLI 创建新 Lambda 函数时指定自定义日志组，请使用 `--logging-config` 选项。以下示例命令可创建 Node.js Lambda 函数，用于将日志发送到名为 `myLogGroup` 的日志组。

  ```
  aws lambda create-function \
    --function-name myFunction \
    --runtime nodejs24.x \
    --handler index.handler \
    --zip-file fileb://function.zip \
    --role arn:aws:iam::123456789012:role/LambdaRole \
    --logging-config LogGroup=myLogGroup
  ```

## 执行角色权限
<a name="monitoring-cloudwatchlogs-configure-permissions"></a>

您的函数必须拥有 [logs:PutLogEvents](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html) 权限，才能向 CloudWatch Logs 发送日志。当您使用 Lambda 控制台配置函数的日志组时，Lambda 将在以下条件下将此权限添加到角色：
+ 服务目标设置为 CloudWatch Logs
+ 函数的执行角色没有将日志上传到 CloudWatch Logs（默认目标）的权限

**注意**  
Lambda 不会为 Amazon S3 或 Firehose 日志目标添加任何 Put 权限。

当 Lambda 添加此权限时，它会向该函数授予向任何 CloudWatch Logs 日志组发送日志的权限。

要防止 Lambda 自动更新函数的执行角色并改为手动对其进行编辑，请展开**权限**并取消选中**添加所需权限**。

当您使用 AWS CLI 配置函数的日志组时，Lambda 不会自动添加 `logs:PutLogEvents` 权限。如果函数的执行角色还没有该权限，请添加。此权限包含在 [AWSLambdaBasicExecutionRole](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole$jsonEditor) 托管策略中。

## Lambda 托管实例的 CloudWatch 日志记录
<a name="monitoring-cloudwatchlogs-lmi"></a>

使用 [Lambda 托管实例](lambda-managed-instances.md)时，在将日志发送至 CloudWatch Logs 时还需注意以下事项：

### VPC 联网要求
<a name="monitoring-cloudwatchlogs-lmi-networking"></a>

Lambda 托管实例在您的 VPC 内的客户自有 EC2 实例上运行。要将日志发送到 CloudWatch Logs 并将跟踪发送到 X-Ray，您必须确保这些 AWS API 可以从您的 VPC 路由。您有多种选择：
+ **AWS PrivateLink（推荐）**：使用 [AWS PrivateLink](https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html) 为 CloudWatch Logs 和 X-Ray 服务创建 VPC 端点。这使得您的实例能够以私有方式访问这些服务，而无需使用互联网网关或 NAT 网关。有关更多信息，请参阅[将 CloudWatch Logs 与接口 VPC 端点结合使用](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch-logs-and-interface-VPC.html)。
+ **NAT 网关**：配置 NAT 网关以允许从您的私有子网中进行出站互联网访问。
+ **互联网网关**：对于公有子网，请确保您的 VPC 已配置互联网网关。

如果 CloudWatch Logs 或 X-Ray API 无法从您的 VPC 进行路由，则您的函数日志和跟踪将无法传输。

### 并发调用和日志归因
<a name="monitoring-cloudwatchlogs-lmi-concurrent"></a>

Lambda 托管实例执行环境可以同时处理多个调用。当多个调用同时运行时，它们的日志条目会交错出现在同一个日志流中。为了有效地筛选和分析来自并发调用的日志，您应当确保每个日志条目都包含 AWS 请求 ID。

我们推荐采用以下方法之一：
+ **使用默认的 Lambda 运行时记录器（推荐）**：Lambda 托管运行时提供的默认日志记录库会自动在每个日志条目中包含请求 ID。
+ **实施结构化 JSON 日志记录**：如果您正在构建[自定义运行时](runtimes-custom.md)或需要自定义日志记录，请实施在每个条目中包含请求 ID 的 JSON 格式日志。Lambda 托管实例仅支持 JSON 日志格式。在 JSON 日志中包含 `requestId` 字段以启用按调用进行筛选：

  ```
  {
    "timestamp": "2025-01-15T10:30:00.000Z",
    "level": "INFO",
    "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "message": "Processing request"
  }
  ```

借助请求 ID 归因，您可以使用 CloudWatch Logs Insights 查询筛选特定调用的 CloudWatch Logs 日志条目。例如：

```
fields @timestamp, @message
| filter requestId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
| sort @timestamp asc
```

有关 Lambda 托管实例日志记录要求的更多信息，请参阅 [了解 Lambda 托管实例执行环境](lambda-managed-instances-execution-environment.md)。

# 查看 Lambda 函数的 CloudWatch 日志
<a name="monitoring-cloudwatchlogs-view"></a>

您可以使用 Lambda 控制台、CloudWatch 控制台或 AWS Command Line Interface（AWS CLI）查看 Lambda 函数的 Amazon CloudWatch Logs。按照以下各节中的说明访问函数的日志。

## 使用 CloudWatch Logs Live Tail 流式处理函数日志
<a name="monitoring-live-tail"></a>

Amazon CloudWatch Logs Live Tail 通过直接在 Lambda 控制台中显示新日志事件的流式列表，来帮助您快速对函数进行问题排查。您可以通过 Lambda 函数实时地查看和筛选提取的日志，帮助您快速检测并解决问题。

**注意**  
Live Tail 会话按会话使用时间每分钟产生费用。有关定价的更多信息，请参阅 [Amazon CloudWatch 定价](https://aws.amazon.com/cloudwatch/pricing/)。

### 比较 Live Tail 和 --log-type Tail
<a name="live-tail-logtype"></a>

CloudWatch Logs Live Tail 和 Lambda API 中的 [LogType: Tail](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#lambda-Invoke-request-LogType) 选项（AWS CLI 中的 `--log-type Tail`）之间有多项差异：
+ `--log-type Tail` 仅返回调用日志的前 4 KB。Live Tail 不具备此限制，并且每秒最多可以接收 500 个日志事件。
+ `--log-type Tail` 捕获并发送带有响应的日志，这可能会影响函数的响应延迟。Live Tail 不会影响函数响应延迟。
+ `--log-type Tail` 仅支持同步调用。Live Tail 适用于同步和异步调用。

**注意**  
[Lambda 托管实例](lambda-managed-instances.md)不支持 `--log-type Tail` 选项。使用 CloudWatch Logs Live Tail 或直接查询 CloudWatch Logs 来查看托管实例函数的日志。

### 权限
<a name="live-tail-permissions"></a>

启动和停止 CloudWatch Logs Live Tail 会话需要以下权限：
+ `logs:DescribeLogGroups`
+ `logs:StartLiveTail`
+ `logs:StopLiveTail`

### 在 Lambda 控制台中启动 Live Tail 会话
<a name="live-tail-console"></a>

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择此函数的名称。

1. 选择**测试**选项卡。

1. 在**测试事件**窗格中，选择 **CloudWatch Logs Live Tail**。

1. 对于**选择日志组**，默认情况下会选择该函数的日志组。一次最多可选择 5 个日志组。

1. （可选）要仅显示包含某些单词或其他字符串的日志事件，请在**添加筛选模式**框中输入词或字符串。筛选字段不区分大小写。您可以在此字段中包含多个术语和模式运算符，包含正则表达式（regex）。有关更多信息，请参阅《Amazon CloudWatch Logs User Guide》**中的 [Filter pattern syntax](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)。

1. 选择**启动**。匹配的日志事件开始出现在窗口中。

1. 要停止 Live Tail 会话，请选择**停止**。
**注意**  
Live Tail 会话会在处于非活动状态 15 分钟后或 Lambda 控制台会话超时后自动停止。

## 使用控制台访问函数日志
<a name="monitoring-cloudwatchlogs-console"></a>

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择一个函数。

1. 选择**监控**选项卡。

1. 选择**查看 CloudWatch 日志**打开 CloudWatch 控制台。

1. 向下滚动，选择要查看的函数调用的**日志流**。  
![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/log-stream.png)

Lambda 函数的每个实例都具有一个专用的日志流。如果函数纵向扩展，每个并发实例都具有自己的日志流。每次创建新的执行环境来响应调用时，都会生成新的日志流。日志流的命名约定是：

```
YYYY/MM/DD[Function version][Execution environment GUID]
```

单一执行环境在生命周期内写入同一个日志流。日志流包含来自该执行环境的消息，以及您的 Lambda 函数代码的任何输出。每条消息都带有时间戳，包括您的自定义日志。即使您的函数不记录代码的任何输出，每次调用也会生成三个最小的日志语句（START、END 和 REPORT）：

![\[监控可观测性图 3\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-3.png)


这些日志显示：
+  **RequestId** – 这是每个请求生成的唯一 ID。如果 Lambda 函数重试请求，则此 ID 不会更改，且会显示在每次后续重试的日志中。
+  **开始/结束** – 这些为单一调用添加了书签，因此它们之间的每个日志行都属于同一调用。
+  **持续时间** – 处理程序函数的总调用时间，不包括 `INIT` 代码。
+  **计费持续时间** – 为计费目的应用舍入逻辑。
+  **内存大小** – 分配给函数的内存量。
+  **最大已用内存**：调用期间使用的最大内存量。
+  **初始化持续时间** – 在主处理程序之外运行 `INIT` 代码部分所花费的时间。

## 使用 AWS CLI 访问日志
<a name="monitoring-cloudwatchlogs-cli"></a>

AWS CLI 是一种开源工具，让您能够在命令行 Shell 中使用命令与 AWS 服务进行交互。要完成本节中的步骤，您必须拥有 [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

您可以通过 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)，使用 `--log-type` 命令选项检索调用的日志。响应包含一个 `LogResult` 字段，其中包含多达 4KB 来自调用的 base64 编码日志。

**Example 检索日志 ID**  
以下示例说明如何从 `LogResult` 字段中检索名为 `my-function` 的函数的*日志 ID*。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
您应看到以下输出：  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example 解码日志**  
在同一命令提示符下，使用 `base64` 实用程序解码日志。以下示例说明如何为 `my-function` 检索 base64 编码的日志。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  
您应看到以下输出：  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64` 实用程序在 Linux、macOS 和 [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 上可用。macOS 用户可能需要使用 `base64 -D`。



**Example get-logs.sh 脚本**  
在同一命令提示符下，使用以下脚本下载最后五个日志事件。此脚本使用 `sed` 从输出文件中删除引号，并休眠 15 秒以等待日志可用。输出包括来自 Lambda 的响应，以及来自 `get-log-events` 命令的输出。  
复制以下代码示例的内容并将其作为 `get-logs.sh` 保存在 Lambda 项目目录中。  
如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS 和 Linux（仅限）**  
在同一命令提示符下，macOS 和 Linux 用户可能需要运行以下命令以确保脚本可执行。  

```
chmod -R 755 get-logs.sh
```

**Example 检索最后五个日志事件**  
在同一命令提示符下，运行以下脚本以获取最后五个日志事件。  

```
./get-logs.sh
```
您应看到以下输出：  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## 解析日志和结构化日志
<a name="querying-logs"></a>

借助 CloudWatch Logs Insights，您可以使用专用[查询语法](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html)搜索和分析日志数据。它对多个日志组执行查询，并使用 [glob](https://en.wikipedia.org/wiki/Glob_(programming)) 和[正则表达式](https://en.wikipedia.org/wiki/Regular_expression)模式匹配提供功能强大的筛选功能。

您可以通过在 Lambda 函数中实施结构化日志记录来利用这些功能。结构化日志将您的日志组织成预定义的格式，便于查询。使用日志级别是生成便于筛选的日志的重要第一步，这些文件将信息性消息与警告或错误区分开来。例如，请考虑以下 Node.js 代码：

```
exports.handler = async (event) => {
    console.log("console.log - Application is fine")
    console.info("console.info - This is the same as console.log")
    console.warn("console.warn - Application provides a warning")
    console.error("console.error - An error occurred")
}
```

生成的 CloudWatch 日志文件包含一个单独的字段，用于指定日志级别：

![\[监控可观测性图 10\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-10.png)


然后，CloudWatch Logs Insights 查询可以按日志级别进行筛选。例如，要仅查询错误，可以使用以下查询：

```
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
```

### JSON 结构化日志记录
<a name="querying-logs-json"></a>

JSON 通常用于为应用程序日志提供结构。在以下示例中，日志已转换为 JSON 以输出三个不同的值：

![\[监控可观测性图 11\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-11.png)


CloudWatch Logs Insights 功能可自动发现 JSON 输出中的值并将消息解析为字段，而无需自定义 glob 或正则表达式。通过使用 JSON 结构的日志，以下查询查找上传的文件大于 1MB、上传时间超过 1 秒且调用不是冷启动的调用：

```
fields @message
| filter @message like /INFO/
| filter uploadedBytes > 1000000
| filter uploadTimeMS > 1000
| filter invocation != 1
```

此查询可能生成以下结果：

![\[监控可观测性图 12\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-12.png)


在 JSON 中发现的字段会自动填充到右侧的*已发现字段*菜单中。Lambda 服务发出的标准字段以“@”为前缀，您可以用相同的方式查询这些字段。Lambda 日志始终包含字段 @timestamp、@logStream、@message、@requestId、@duration、@billedDuration、@type、@maxMemoryUsed 和 @memorySize。如果为某个函数启用了 X-Ray，日志还会包含 @xrayTraceId 和 @xraySegmentId。

当 Amazon S3、Amazon SQS 或 Amazon EventBridge 之类的 AWS 事件源调用您的函数时，整个事件将作为 JSON 对象输入提供给该函数。通过在函数的第一行记录此事件，您随后就可以使用 CloudWatch Logs Insights 查询任何嵌套字段。

### 实用的 Insights 查询
<a name="useful-logs-queries"></a>

下表显示了可用于监控 Lambda 函数的 Insights 查询示例。


| 说明 |  查询语法示例 | 
| --- | --- | 
|  最后 100 个错误  |  

```
 fields Timestamp, LogLevel, Message
 \| filter LogLevel == "ERR"
 \| sort @timestamp desc
 \| limit 100
```  | 
|  计费最高的前 100 次调用  |  

```
filter @type = "REPORT"
\| fields @requestId, @billedDuration
\| sort by @billedDuration desc
\| limit 100
```  | 
|  冷启动占总调用次数的百分比  |  

```
filter @type = "REPORT"
\| stats sum(strcontains(@message, "Init Duration"))/count(*) * 100 as
  coldStartPct, avg(@duration)
  by bin(5m)
```  | 
|  Lambda 持续时间的百分位数报告  |  

```
filter @type = "REPORT"
\| stats
    avg(@billedDuration) as Average,
    percentile(@billedDuration, 99) as NinetyNinth,
    percentile(@billedDuration, 95) as NinetyFifth,
    percentile(@billedDuration, 90) as Ninetieth
    by bin(30m)
```  | 
|  Lambda 内存使用量的百分位数报告  |  

```
filter @type="REPORT"
\| stats avg(@maxMemoryUsed/1024/1024) as mean_MemoryUsed,
    min(@maxMemoryUsed/1024/1024) as min_MemoryUsed,
    max(@maxMemoryUsed/1024/1024) as max_MemoryUsed,
    percentile(@maxMemoryUsed/1024/1024, 95) as Percentile95
```  | 
|  使用 100% 分配内存的调用  |  

```
filter @type = "REPORT" and @maxMemoryUsed=@memorySize
\| stats
    count_distinct(@requestId)
    by bin(30m)
```  | 
|  各次调用的平均内存使用量  |  

```
avgMemoryUsedPERC,
    avg(@billedDuration) as avgDurationMS
    by bin(5m)
```  | 
|  内存统计数据的可视化  |  

```
filter @type = "REPORT"
\| stats
    max(@maxMemoryUsed / 1024 / 1024) as maxMemMB,
    avg(@maxMemoryUsed / 1024 / 1024) as avgMemMB,
    min(@maxMemoryUsed / 1024 / 1024) as minMemMB,
    (avg(@maxMemoryUsed / 1024 / 1024) / max(@memorySize / 1024 / 1024)) * 100 as avgMemUsedPct,
    avg(@billedDuration) as avgDurationMS
    by bin(30m)
```  | 
|  Lambda 退出时的调用  |  

```
filter @message like /Process exited/
\| stats count() by bin(30m)
```  | 
|  超时的调用  |  

```
filter @message like /Task timed out/
\| stats count() by bin(30m)
```  | 
|  延迟报告  |  

```
filter @type = "REPORT"
\| stats avg(@duration), max(@duration), min(@duration)
  by bin(5m)
```  | 
|  内存过度预调配  |  

```
filter @type = "REPORT"
\| stats max(@memorySize / 1024 / 1024) as provisonedMemMB,
        min(@maxMemoryUsed / 1024 / 1024) as smallestMemReqMB,
        avg(@maxMemoryUsed / 1024 / 1024) as avgMemUsedMB,
        max(@maxMemoryUsed / 1024 / 1024) as maxMemUsedMB,
        provisonedMemMB - maxMemUsedMB as overProvisionedMB
```  | 

## 日志可视化和控制面板
<a name="monitoring-logs-visualization"></a>

对于任何 CloudWatch Logs Insights 查询，您可以将结果导出为 markdown 或 CSV 格式。在某些情况下，如果至少有一个聚合函数，则[根据查询创建可视化](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_Insights-Visualizing-Log-Data.html)可能会更有用。`stats` 函数允许您定义聚合和分组。

以前的 *logInsightsJSON* 示例根据上传大小和上传时间进行了筛选，且排除了首次调用。这产生了一个数据表。为了监控生产系统，可视化最小、最大和平均文件大小以查找异常值可能更有用。为此，请使用带有所需聚合的 stats 函数，然后按时间值（例如每分钟）进行分组：

例如，请考虑以下查询。这与 [JSON 结构化日志记录](#querying-logs-json) 部分中的示例查询相同，但具有其他聚合函数：

```
fields @message
| filter @message like /INFO/
| filter uploadedBytes > 1000000
| filter uploadTimeMS > 1000
| filter invocation != 1
| stats min(uploadedBytes), avg(uploadedBytes), max(uploadedBytes) by bin (1m)
```

我们之所以加入这些聚合，是因为通过可视化最小、最大和平均文件大小来查找异常值可能会更有用。您可以在**可视化**选项卡中查看结果：

![\[监控可观测性图 14\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-14.png)


构建完可视化后，您可以选择将图表添加到 CloudWatch 控制面板。要执行此操作，请选择可视化上方的**添加到控制面板**。这会将查询添加为小组件，并允许您选择自动刷新间隔，从而更轻松地持续监控结果：

![\[监控可观测性图 15\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-15.png)


# 将 Lambda 函数日志发送到 Firehose
<a name="logging-with-firehose"></a>

Lambda 控制台现在提供了向 Firehose 发送函数日志的选项。这可以将您的日志实时流式传输到 Firehose 支持的各种目标，包括第三方分析工具和自定义端点。

**注意**  
您可以使用 Lambda 控制台、AWS CLI、AWS CloudFormation 和所有 AWS SDK 将 Lambda 函数日志配置为发送到 Firehose。

## 定价
<a name="logging-firehose-pricing"></a>

有关定价详细信息，请参阅 [Amazon CloudWatch 定价](https://aws.amazon.com/cloudwatch/pricing/#Vended_Logs)。

## Firehose 日志目标所需的权限
<a name="logging-firehose-permissions"></a>

使用 Lambda 控制台将 Firehose 配置为函数的日志目标时，您需要：

1. 将 CloudWatch Logs 与 Lambda 结合使用[所需的 IAM 权限](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-prereqs)。

1. [使用 Firehose 设置订阅筛选条件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#FirehoseExample)。此筛选条件定义将哪些日志事件传送到 Firehose 流。

## 将 Lambda 函数日志发送到 Firehose
<a name="logging-firehose-setup"></a>

在 Lambda 控制台中，您可以在创建新函数后将函数日志直接发送到 Firehose。为此，请完成以下步骤：

1. 登录 AWS 管理控制台，然后打开 Lambda 控制台。

1. 选择您的函数名称。

1. 选择**配置**选项卡。

1. 选择**监控和操作工具**选项卡。

1. 在“日志记录配置”部分中，选择**编辑**。

1. 在“日志内容”部分，选择一种日志格式。

1. 在“日志目标”部分中，完成以下步骤：

   1. 选择目标服务。

   1. 选择**创建新的日志组**或使用**现有日志组**。
**注意**  
如果为 Firehose 目标选择现有日志组，则请确保您选择的日志组是 `Delivery` 日志组类型。

   1. 选择一个 Firehose 流。

   1. 将出现 CloudWatch `Delivery` 日志组。

1. 选择**保存**。

**注意**  
如果控制台中提供的 IAM 角色没有所需的权限，则目标设置将失败。要解决此问题，请参阅“Firehose 日志目标所需的权限”以提供所需的权限。

## 跨账户日志记录
<a name="cross-account-logging-firehose"></a>

您可以将 Lambda 为使用不同 AWS 账户向 Firehose 传输流发送日志。这需要设置目标，并在两个账户中配置适当的权限。

有关设置跨账户日志记录的详细说明，包括所需的 IAM 角色和策略，请参阅 CloudWatch Logs 文档中的 [Setting up a new cross-account subscription](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CrossAccountSubscriptions.html)。

# 将 Lambda 函数日志发送到 Amazon S3
<a name="logging-with-s3"></a>

您可以使用 Lambda 控制台配置 Lambda 函数，以将日志直接发送到 Amazon S3。此功能为长期日志存储提供了经济高效的解决方案，并使用 Athena 等服务实现了强大的分析选项。

**注意**  
您可以使用 Lambda 控制台、AWS CLI、AWS CloudFormation 和所有 AWS SDK 将 Lambda 函数日志配置为发送到 Amazon S3。

## 定价
<a name="logging-s3-pricing"></a>

有关定价详细信息，请参阅 [Amazon CloudWatch 定价](https://aws.amazon.com/cloudwatch/pricing/#Vended_Logs)。

## Amazon S3 日志目标所需的权限
<a name="logging-s3-permissions"></a>

使用 Lambda 控制台将 Amazon S3 配置为函数的日志目标时，您需要：

1. 将 CloudWatch Logs 与 Lambda 结合使用[所需的 IAM 权限](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-prereqs)。

1. [设置 CloudWatch Logs 订阅筛选条件以将 Lambda 函数日志发送到 Amazon S3](#using-cwl-subscription-filter-lambda-s3)。此筛选条件定义将哪些日志事件传送到 Amazon S3 存储桶。

## 设置 CloudWatch Logs 订阅筛选条件以将 Lambda 函数日志发送到 Amazon S3
<a name="using-cwl-subscription-filter-lambda-s3"></a>

要将日志从 CloudWatch Logs 发送到 Amazon S3，您需要创建一个订阅筛选条件。此筛选条件定义将哪些日志事件传送到 Amazon S3 存储桶。您的 Amazon S3 存储桶必须与您的日志组位于同一区域。

### 为 Amazon S3 创建订阅筛选条件
<a name="create-subscription-filter-s3"></a>

1. 创建 Amazon Simple Storage Service (Amazon S3) 存储桶 我们建议您使用专为 CloudWatch Logs 创建的存储桶。但是，如果要使用现有存储桶，请跳至第 2 步。

   运行以下命令，将占位符区域替换为您想使用的区域：

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-bucket2 --create-bucket-configuration LocationConstraint=region
   ```
**注意**  
`amzn-s3-demo-bucket2` 是示例 Amazon S3 存储桶名称。它是*预留的*。要使此过程生效，您必须将其替换为唯一的 Amazon S3 存储桶名称。

   下面是示例输出：

   ```
   {
       "Location": "/amzn-s3-demo-bucket2"
   }
   ```

1. 创建 IAM 角色，该角色将授予 CloudWatch Logs 将数据放入 Amazon S3 存储桶的权限。此策略包括 aws:SourceArn 全局条件上下文密钥，有助于避免出现混淆代理安全问题。有关更多信息，请参阅 [Confused deputy prevention](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Subscriptions-confused-deputy.html)。

   1. 使用文本编辑器在文件 `~/TrustPolicyForCWL.json` 中创建一个信任策略，具体如下所示：

      ```
      {
          "Statement": {
              "Effect": "Allow",
              "Principal": { "Service": "logs.amazonaws.com" },
              "Condition": { 
                  "StringLike": {
                      "aws:SourceArn": "arn:aws:logs:region:123456789012:*"
                  } 
               },
              "Action": "sts:AssumeRole"
          } 
      }
      ```

   1. 使用 create-role 命令创建 IAM 角色，并指定信任策略文件。请记下返回的 Role.Arn 值，因为后面的步骤中将会用到它：

      ```
      aws iam create-role \
       --role-name CWLtoS3Role \
       --assume-role-policy-document file://~/TrustPolicyForCWL.json
      {
          "Role": {
              "AssumeRolePolicyDocument": {
                  "Statement": {
                      "Action": "sts:AssumeRole",
                      "Effect": "Allow",
                      "Principal": {
                          "Service": "logs.amazonaws.com"
                      },
                      "Condition": { 
                          "StringLike": {
                              "aws:SourceArn": "arn:aws:logs:region:123456789012:*"
                          } 
                      }
                  }
              },
              "RoleId": "AAOIIAH450GAB4HC5F431",
              "CreateDate": "2015-05-29T13:46:29.431Z",
              "RoleName": "CWLtoS3Role",
              "Path": "/",
              "Arn": "arn:aws:iam::123456789012:role/CWLtoS3Role"
          }
      }
      ```

1. 创建权限策略以定义可对您的账户执行的 CloudWatch Logs 操作。首先，使用文本编辑器在文件 `~/PermissionsForCWL.json` 中创建权限策略：

   ```
   {
     "Statement": [
       {
         "Effect": "Allow",
         "Action": ["s3:PutObject"],
         "Resource": ["arn:aws:s3:::amzn-s3-demo-bucket2/*"]
       }
     ]
   }
   ```

   使用以下 `put-role-policy` 命令，将权限策略与角色关联：

   ```
   aws iam put-role-policy --role-name CWLtoS3Role --policy-name Permissions-Policy-For-S3 --policy-document file://~/PermissionsForCWL.json
   ```

1. 创建 `Delivery` 日志组或使用现有的 `Delivery` 日志组。

   ```
   aws logs create-log-group --log-group-name my-logs --log-group-class DELIVERY --region REGION_NAME
   ```

1. `PutSubscriptionFilter` 用于设置目标

   ```
   aws logs put-subscription-filter
   --log-group-name my-logs
   --filter-name my-lambda-delivery
   --filter-pattern ""
   --destination-arn arn:aws:s3:::amzn-s3-demo-bucket2
   --role-arn arn:aws:iam::123456789012:role/CWLtoS3Role
   --region REGION_NAME
   ```

## 将 Lambda 函数日志发送到 Amazon S3
<a name="logging-s3-setup"></a>

在 Lambda 控制台中，您可以在创建新函数后将函数日志直接发送到 Amazon S3。为此，请完成以下步骤：

1. 登录 AWS 管理控制台，然后打开 Lambda 控制台。

1. 选择您的函数名称。

1. 选择**配置**选项卡。

1. 选择**监控和操作工具**选项卡。

1. 在“日志记录配置”部分中，选择**编辑**。

1. 在“日志内容”部分，选择一种日志格式。

1. 在“日志目标”部分中，完成以下步骤：

   1. 选择目标服务。

   1. 选择**创建新的日志组**或使用**现有日志组**。
**注意**  
如果为 Amazon S3 目标选择现有日志组，请确保您选择的日志组是 `Delivery` 日志组类型。

   1. 选择 Amazon S3 存储桶作为函数日志的目标。

   1. 将出现 CloudWatch `Delivery` 日志组。

1. 选择**保存**。

**注意**  
如果控制台中提供的 IAM 角色没有所需的权限，则目标设置将失败。要解决此问题，请参阅 [Amazon S3 日志目标所需的权限](#logging-s3-permissions)。

## 跨账户日志记录
<a name="cross-account-logging-s3"></a>

您可以将 Lambda 为使用不同 AWS 账户向 Amazon S3 存储桶发送日志。这需要设置目标，并在两个账户中配置适当的权限。

有关设置跨账户日志记录的详细说明，包括所需的 IAM 角色和策略，请参阅 CloudWatch Logs 文档中的 [Setting up a new cross-account subscription](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CrossAccountSubscriptions.html)。