

# 将 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)
