

# 使用 Lambda 扩展增强 Lambda 函数
<a name="lambda-extensions"></a>

您可以使用 Lambda 扩展来增强您的 Lambda 函数。例如，使用 Lambda 扩展将函数与您首选的监控、可观察性、安全性和监管工具集成。您可以从 [AWS Lambda 合作伙伴](https://aws.amazon.com/lambda/partners/)提供的一系列工具中进行选择，也可以[创建自己的 Lambda 扩展](runtimes-extensions-api.md)。

Lambda 支持内部和外部扩展。外部扩展作为独立进程在执行环境中运行，并在完全处理函数调用后继续运行。由于扩展作为单独的进程运行，因此您可以使用不同于函数的语言来编写它们。所有 [Lambda 运行时](lambda-runtimes.md) 均支持扩展。

内部扩展作为运行时进程的一部分运行。您的函数通过使用包装脚本或进程内机制（如 `JAVA_TOOL_OPTIONS`）访问内部扩展。有关更多信息，请参阅[修改运行时环境](runtimes-modify.md)。

您可以使用 Lambda 控制台、AWS Command Line Interface (AWS CLI) 或基础设施即代码 (IaC) 服务和工具（如 CloudFormation、AWS Serverless Application Model (AWS SAM) 和 Terraform）向函数添加扩展。

您需要按扩展所占用的执行时间（以 1 毫秒为增量）付费。安装自己的扩展没有任何费用。有关扩展的定价的更多信息，请参阅 [AWS Lambda 定价](https://aws.amazon.com/lambda/pricing/) 有关合作伙伴扩展的定价信息，请参阅这些合作伙伴的网站。有关官方合作伙伴扩展列表，请参阅 [AWS Lambda 扩展合作伙伴](extensions-api-partners.md)。

**Topics**
+ [

## 执行环境
](#using-extensions-env)
+ [

## 对性能和资源的影响
](#using-extensions-reg)
+ [

## 权限
](#using-extensions-permissions)
+ [

# 配置 Lambda 扩展
](extensions-configuration.md)
+ [

# AWS Lambda 扩展合作伙伴
](extensions-api-partners.md)
+ [

# 使用 Lambda 扩展 API 创建扩展
](runtimes-extensions-api.md)
+ [

# 使用遥测 API 访问扩展的实时遥测数据
](telemetry-api.md)

## 执行环境
<a name="using-extensions-env"></a>

Lambda 在[执行环境](lambda-runtime-environment.md)中调用您的函数，该环境提供一个安全和隔离的运行时环境。执行环境管理运行函数所需的资源，并为函数的运行时和扩展提供生命周期支持。

执行环境的生命周期包括以下阶段：
+ `Init`：在此阶段，Lambda 会使用配置的资源创建或取消冻结执行环境、下载函数代码和所有层、初始化任何扩展、初始化运行时，然后运行函数的初始化代码（主处理程序外的代码）。`Init` 阶段发生在第一次调用期间，或者在函数调用之前（如果您已启用[预配置并发](provisioned-concurrency.md)）。

  `Init` 阶段分为三个子阶段：`Extension init`、`Runtime init` 和 `Function init`。这些子阶段可确保所有扩展和运行时在函数代码运行之前完成其设置任务。

  激活 [Lambda SnapStart](snapstart.md) 后，在您发布一个函数版本时会发生 `Init` 阶段。Lambda 保存初始化的执行环境的内存和磁盘状态的快照，永久保存加密快照并对其进行缓存以实现低延迟访问。如果您具有检查点前的[运行时钩子](snapstart-runtime-hooks.md)，则该代码将在 `Init` 阶段结束时运行。
+ `Restore`（仅限 SnapStart）：当您首次调用 [SnapStart](snapstart.md) 函数时，随着该函数的纵向扩展，Lambda 会从永久保存的快照中恢复新的执行环境，而不是从头开始初始化函数。如果您有还原后[运行时挂钩](snapstart-runtime-hooks.md)，则代码将在 `Restore` 阶段结束时运行。还原后运行时挂钩执行期间将产生费用。必须加载运行时，并且还原后运行时挂钩必须在超时限制（10 秒）内完成。否则，您将收到 SnapStartTimeoutException。`Restore` 阶段完成后，Lambda 将调用函数处理程序（[调用阶段](lambda-runtime-environment.md#runtimes-lifecycle-invoke)）。
+ `Invoke`：在此阶段，Lambda 调用函数处理程序。在函数运行完成后，Lambda 准备处理另一次函数调用。
+ `Shutdown`：如果 Lambda 函数在一段时间内没有收到任何调用，则触发此阶段。在 `Shutdown` 阶段，Lambda 会关闭运行时，提醒扩展让其完全停止，然后删除环境。Lambda 向每个扩展发送一个 `Shutdown` 事件，通知扩展环境即将关闭。

在 `Init` 阶段，Lambda 将包含扩展的层提取到执行环境中的 `/opt` 目录中。Lambda 在 `/opt/extensions/` 目录中查找扩展，将每个文件解释为启动扩展的可执行引导程序，然后并行启动所有扩展。

## 对性能和资源的影响
<a name="using-extensions-reg"></a>

函数的扩展的大小将计入部署包大小限制。对于 .zip 文件存档，函数和所有扩展解压后的总大小不得超过解压后的部署程序包大小限制，即 250 MB。

扩展可能会影响函数的性能，因为它们共享函数资源，如 CPU、内存和存储。例如，如果扩展执行计算密集型操作，那么您可能会发现函数的执行时间增加。

每个扩展都必须在 Lambda 调用函数之前完成其初始化。因此，占用大量初始化时间的扩展可能会增加函数调用的延迟。

要测量扩展在函数执行后所花的额外时间，可以使用`PostRuntimeExtensionsDuration` [函数指标](monitoring-metrics.md)。要衡量所使用的内存增加量，可以使用 `MaxMemoryUsed` 指标。要了解特定扩展的影响，您可以并行运行不同版本的函数。

**注意**  
`MaxMemoryUsed` 指标是 [Lambda Insights 收集的指标](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-metrics.html)之一，而不是 Lambda 原生指标。

## 权限
<a name="using-extensions-permissions"></a>

扩展可以访问与函数相同的资源。由于扩展是在与函数相同的环境中执行的，因此在函数和扩展之间共享权限。

对于 .zip 文件归档，您可以创建一个 CloudFormation 模板，以简化将相同扩展配置（包括 AWS Identity and Access Management (IAM) 权限）附加到多个函数的任务。

# 配置 Lambda 扩展
<a name="extensions-configuration"></a>

## 配置扩展（.zip 文件存档）
<a name="using-extensions-config"></a>

您可以将扩展作为 [Lambda 层](chapter-layers.md)添加到函数中。使用层可让您在整个组织或整个 Lambda 开发人员社区中共享扩展。您可以向层添加一个或多个扩展。您最多可以为一个函数注册 10 个扩展。

您可以使用与任何层相同的方法将扩展添加到函数中。有关更多信息，请参阅 [使用层管理 Lambda 依赖项](chapter-layers.md)。

**将扩展添加到您的函数（控制台）**

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

1. 选择函数。

1. 选择 **Code（代码）**（如果尚未选择）。

1. 在 **Layers（层）**下，选择 **Edit（编辑）**。

1. 对于**选择层**，选择**指定 ARN**。

1. 对于**指定 ARN**，输入扩展层的 Amazon Resource Name (ARN)。

1. 选择 **添加**。

## 在容器映像中使用扩展
<a name="invocation-extensions-images"></a>

您可以向[容器映像](images-create.md)添加扩展。ENTRYPOINT 容器映像设置指定函数的主进程。在 Dockerfile 中配置 ENTRYPOINT 设置，或者覆盖函数配置。

您可以在一个容器内运行多个进程。Lambda 管理主进程和任何其他进程的生命周期。Lambda 使用[扩展 API](runtimes-extensions-api.md) 管理扩展生命周期。

### 示例：添加外部扩展
<a name="extensions-images-ex1"></a>

外部扩展在 Lambda 函数之外的单独进程中运行。Lambda 为 `/opt/extensions/` 目录中的每个扩展启动一个进程。Lambda 使用扩展 API 管理扩展生命周期。函数运行完成后，Lambda 向每个外部扩展发送一个 `Shutdown` 事件。

**Example 向 Python 基本映像添加外部扩展**  

```
FROM public.ecr.aws/lambda/python:3.11

# Copy and install the app
COPY /app /app
WORKDIR /app
RUN pip install -r requirements.txt

# Add an extension from the local directory into /opt/extensions
ADD my-extension.zip /opt/extensions
CMD python ./my-function.py
```

## 后续步骤
<a name="using-extensions-next"></a>

要了解有关扩展的更多信息，我们建议使用以下资源：
+ 有关基本的工作示例，请参阅 AWS Lambda 计算博客上的[构建 AWS 扩展](https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/)。
+ 有关 AWS Lambda 合作伙伴提供的扩展的信息，请参阅 AWS Lambda 计算博客上的[AWS 扩展简介](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-extensions-in-preview/)。
+ 要查看可用的示例扩展和包装脚本，请参阅 AWS Lambda Sample GitHub 存储库上的 [AWS 扩展](https://github.com/aws-samples/aws-lambda-extensions)。

# AWS Lambda 扩展合作伙伴
<a name="extensions-api-partners"></a>

AWS Lambda 已与多个第三方实体结成合作伙伴，提供多种扩展以与您的 Lambda 函数集成。以下列表详细列出了可供您随时使用的第三方扩展。
+ [https://docs.appdynamics.com/display/PRO20X/Use+the+AppDynamics+AWS+Lambda+Extension+to+Instrument+Serverless+APM+at+Runtime](https://docs.appdynamics.com/display/PRO20X/Use+the+AppDynamics+AWS+Lambda+Extension+to+Instrument+Serverless+APM+at+Runtime) – 提供 Node.js 或 Python Lambda 函数的自动分析，从而提供有关函数性能的可见性和提示。
+ [https://axiom.co/docs/apps/lambda](https://axiom.co/docs/apps/lambda) – 提供用于监控 Lambda 函数性能和汇总系统级指标的控制面板。
+ [https://docs.datadoghq.com/serverless/datadog_lambda_library/extension/](https://docs.datadoghq.com/serverless/datadog_lambda_library/extension/) – 通过使用指标、跟踪和日志，为无服务器应用程序提供全面、实时的可见性。
+ [https://www.dynatrace.com/support/help/technology-support/cloud-platforms/amazon-web-services/integrations/deploy-oneagent-as-lambda-extension/](https://www.dynatrace.com/support/help/technology-support/cloud-platforms/amazon-web-services/integrations/deploy-oneagent-as-lambda-extension/) – 提供跟踪和指标的可见性，并利用 AI 在整个应用程序堆栈中进行自动错误检测和根本原因分析。
+ [https://www.elastic.co/guide/en/apm/agent/nodejs/current/lambda.html](https://www.elastic.co/guide/en/apm/agent/nodejs/current/lambda.html) – 提供应用程序性能监控（APM），以便使用相关的跟踪、指标和日志来识别和解决根本原因问题。
+ [https://docs.epsagon.com/docs/environment-monitoring/lambda/intro](https://docs.epsagon.com/docs/environment-monitoring/lambda/intro) – 侦听调用事件、存储跟踪，并将它们并行发送到 Lambda 函数执行。
+ [https://docs.fastly.com/signalsciences/install-guides/paas/aws-lambda/](https://docs.fastly.com/signalsciences/install-guides/paas/aws-lambda/)– 保护您的 Lambda 函数免受可疑活动的侵害，例如注入式攻击、通过凭证填充获取账户、恶意机器人和 API 滥用。
+ [https://learn.hashicorp.com/tutorials/vault/aws-lambda](https://learn.hashicorp.com/tutorials/vault/aws-lambda) – 管理秘密并使开发人员可以在函数代码中使用这些秘密，而无需通知函数文件库。
+ [https://docs.honeycomb.io/getting-data-in/integrations/aws/aws-lambda/](https://docs.honeycomb.io/getting-data-in/integrations/aws/aws-lambda/) – 用于调试应用程序堆栈的可观察性工具。
+ [https://docs.lumigo.io/docs/lambda-extensions](https://docs.lumigo.io/docs/lambda-extensions) – 分析 Lambda 函数调用情况并收集用于在无服务器和微服务环境中排除问题的指标。
+ [https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/get-started/monitoring-aws-lambda-serverless-monitoring](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/get-started/monitoring-aws-lambda-serverless-monitoring) – 与 Lambda 函数一起运行，自动收集、增强遥测数据，并将这些数据传输到 New Relic 的统一可观察性平台。
+ [https://docs.sedai.io/get-started/platform/optimization/aws/lambda](https://docs.sedai.io/get-started/platform/optimization/aws/lambda) – 由 AI/ML 提供支持的自主云管理平台，可为云运营团队提供持续优化，从而最大限度地节省云成本，提高大规模性能和可用性。
+ [https://docs.sentry.io/platforms/javascript/guides/aws-lambda/](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/) – 诊断、修复和优化 Lambda 函数的性能。
+ [https://www.site24x7.com/help/aws/lambda-execution-logs.html](https://www.site24x7.com/help/aws/lambda-execution-logs.html) – 实现对 Lambda 环境的实时可观察性
+ [https://github.com/signalfx/splunk-otel-lambda](https://github.com/signalfx/splunk-otel-lambda) – 收集高分辨率、低延迟的指标，以便高效且有效地监控 Lambda 函数。
+ [https://help.sumologic.com/03Send-Data/Collect-from-Other-Data-Sources/Collect_AWS_Lambda_Logs_using_an_Extension](https://help.sumologic.com/03Send-Data/Collect-from-Other-Data-Sources/Collect_AWS_Lambda_Logs_using_an_Extension) – 提供对无服务器应用程序的运行状况和性能的可见性。
+ [Salt Security](https://salt.security/press-releases/salt-security-becomes-the-first-and-only-api-security-vendor-to-join-aws-lambda-ready-program?) – 通过自动设置和对不同运行时的支持，简化 Lambda 函数的 API 状态治理和 API 安全。

## AWS 托管式扩展
<a name="aws-managed-extensions"></a>

AWS 提供了其自己的托管式扩展，包括：
+ [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-integration-lambda-extensions.html#appconfig-integration-lambda-extensions-enabling) - 使用功能标志和动态数据更新 Lambda 函数。您还可以使用此扩展来更新其他动态配置，例如运维节流和优化。
+ [Amazon CodeGuru Profiler](https://docs.aws.amazon.com/codeguru/latest/profiler-ug/python-lambda-layers.html) - 通过查明应用程序最宝贵的代码行并提供改进代码的建议，来提高应用程序性能并降低成本。
+ [CloudWatch Lambda Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights.html) - 通过自动化控制面板监控、故障排除和优化 Lambda 函数的性能。
+ [AWS Distro for OpenTelemetry（ADOT）](https://aws.amazon.com/otel) – 启用函数将跟踪数据发送到 AWS 监控服务（例如 AWS X-Ray），以及支持 OpenTelemetry 的目的地（例如 Honeycomb 和 Lightstep）。
+ [AWS 参数和密钥](with-secrets-manager.md) – 在 Lambda 函数中安全地从 AWS Systems Manager Parameter Store 检索参数并从 AWS Secrets Manager 检索密钥。

有关其他扩展示例和演示项目，请参阅 [AWS Lambda 扩展](https://github.com/aws-samples/aws-lambda-extensions)。

# 使用 Lambda 扩展 API 创建扩展
<a name="runtimes-extensions-api"></a>

Lambda 函数作者使用扩展将 Lambda 与他们首选的监控、可观察性、安全性和监管工具集成。函数作者可以使用来自 AWS、[AWS 合作伙伴](extensions-api-partners.md)和开源项目的扩展。有关使用扩展的更多信息，请参阅 AWS Lambda 计算博客上的 [AWS 扩展简介](https://aws.amazon.com/blogs/aws/getting-started-with-using-your-favorite-operational-tools-on-aws-lambda-extensions-are-now-generally-available/)。本节介绍如何使用 Lambda 扩展 API、Lambda 执行环境生命周期以及 Lambda 扩展 API 参考。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


作为扩展作者，您可以使用 Lambda 扩展 API 深入集成到 Lambda [执行环境](lambda-runtime-environment.md)中。您的扩展可以注册函数和执行环境生命周期事件。为响应这些事件，您可以启动新进程、运行逻辑、控制并参与 Lambda 生命周期的所有阶段：初始化、调用和关闭。此外，您可以使用[运行时日志 API](runtimes-logs-api.md) 接收日志流。

扩展作为独立进程在执行环境中运行，并可以在完全处理函数调用后继续运行。由于扩展作为进程运行，因此您可以使用不同于函数的语言来编写它们。我们建议您使用已编译的语言实现扩展。在这种情况下，扩展是一个独立的二进制文件，与支持的运行时兼容。所有 [Lambda 运行时](lambda-runtimes.md) 均支持扩展。如果使用非编译的语言，请确保在扩展中包含兼容的运行时。

Lambda 还支持*内部扩展*。内部扩展作为运行时进程的独立线程运行。运行时启动并停止内部扩展。与 Lambda 环境集成的另一种方法是使用特定于语言的[环境变量和包装脚本](runtimes-modify.md)。您可以使用这些来配置运行时环境并修改运行时进程的启动行为。

您可以通过两种方式将扩展添加到函数。对于部署为 [.zip 文件存档](configuration-function-zip.md)的函数，您可以将扩展部署为[层](chapter-layers.md)。对于定义为容器映像的函数，您可以将[扩展](extensions-configuration.md#invocation-extensions-images)添加到容器映像中。

**注意**  
有关示例扩展和包装脚本的信息，请参阅 AWS Lambda Sample GitHub 存储库上的 [AWS 扩展](https://github.com/aws-samples/aws-lambda-extensions)。

**Topics**
+ [

## Lambda 执行环境生命周期
](#runtimes-extensions-api-lifecycle)
+ [

## 扩展 API 参考
](#runtimes-extensions-registration-api)

## Lambda 执行环境生命周期
<a name="runtimes-extensions-api-lifecycle"></a>

执行环境的生命周期包括以下阶段：
+ `Init`：在此阶段，Lambda 会使用配置的资源创建或取消冻结执行环境、下载函数代码和所有层、初始化任何扩展、初始化运行时，然后运行函数的初始化代码（主处理程序外的代码）。`Init` 阶段发生在第一次调用期间，或者在函数调用之前（如果您已启用[预配置并发](provisioned-concurrency.md)）。

  `Init` 阶段分为三个子阶段：`Extension init`、`Runtime init` 和 `Function init`。这些子阶段可确保所有扩展和运行时在函数代码运行之前完成其设置任务。
+ `Invoke`：在此阶段，Lambda 调用函数处理程序。在函数运行完成后，Lambda 准备处理另一次函数调用。
+ `Shutdown`：如果 Lambda 函数在一段时间内没有收到任何调用，则触发此阶段。在 `Shutdown` 阶段，Lambda 会关闭运行时，提醒扩展让其完全停止，然后删除环境。Lambda 向每个扩展发送一个 `Shutdown` 事件，通知扩展环境即将关闭。

每个阶段都以一个从 Lambda 到运行时和所有已注册扩展的事件开始。运行时和每个扩展信号通过发送 `Next` API 请求来表示完成。Lambda 在每个进程结束并且没有挂起的事件时会冻结执行环境。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/Overview-Full-Sequence.png)


 

**Topics**
+ [

### Init 阶段
](#runtimes-extensions-api-reg)
+ [

### 调用阶段
](#runtimes-lifecycle-extensions-invoke)
+ [

### 关闭阶段
](#runtimes-lifecycle-extensions-shutdown)
+ [

### 权限和配置
](#runtimes-extensions-registration-api-e)
+ [

### 故障处理
](#runtimes-extensions-api-failure)
+ [

### 扩展故障排除
](#runtimes-extensions-api-trbl)

### Init 阶段
<a name="runtimes-extensions-api-reg"></a>

在 `Extension init` 阶段，每个扩展都需要在 Lambda 注册才能接收事件。Lambda 会使用扩展的完整文件名来验证扩展是否已完成引导启动序列。因此，每个 `Register` API 调用都必须包含 `Lambda-Extension-Name` 标头以及扩展的完整文件名。

您最多可以为一个函数注册 10 个扩展。此限制通过 `Register` API 调用强制执行。

在每个扩展注册后，Lambda 会启动 `Runtime init` 阶段。运行时进程调用 `functionInit`，启动 `Function init` 阶段。

`Init` 阶段在运行时之后结束，每个注册的扩展通过发送 `Next` API 请求指示完成。

**注意**  
扩展可以在 `Init` 阶段的任何时间点完成其初始化。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/Init-Phase.png)


### 调用阶段
<a name="runtimes-lifecycle-extensions-invoke"></a>

当调用 Lambda 函数来响应 `Next` API 请求时，Lambda 会向运行时和为 `Invoke` 事件注册的每个扩展发送一个 `Invoke` 事件。

**注意**  
**Lambda 托管实例：**Lambda 托管实例函数的扩展程序无法注册 `Invoke` 事件。由于 Lambda 托管实例支持在单个执行环境中进行并发调用，因此不支持 `Invoke` 事件。扩展程序只能注册 `Shutdown` 事件。如果您需要跟踪调用的开始和结束时间，请通过[遥测 API](telemetry-api.md) 使用 `platform.report` 平台事件。

在调用过程中，外部扩展与函数并行运行。在函数完成后，它们也会继续运行。这使您能够捕获诊断信息，或将日志、指标和跟踪发送到您选择的位置。

从运行时接收函数响应后，即使扩展仍在运行，Lambda 也会将响应返回给客户端。

`Invoke` 阶段在运行时之后结束，所有扩展都通过发送 `Next` API 请求来指示它们已完成。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/Invoke-Phase.png)


**事件负载**：发送到运行时（和 Lambda 函数）的事件包含整个请求、标头（如 `RequestId`）和负载。发送到每个扩展的事件包含描述事件内容的元数据。此生命周期事件包括事件的类型、函数超时的时间 (`deadlineMs`)、`requestId`、被调用函数的 Amazon 资源名称（ARN）和跟踪标头。

希望访问函数事件主体的扩展可以使用与扩展进行通信的运行时开发工具包。在调用函数时，函数开发人员使用运行时开发工具包将负载发送到扩展。

以下是一个示例负载：

```
{
    "eventType": "INVOKE",
    "deadlineMs": 676051,
    "requestId": "3da1f2dc-3222-475e-9205-e2e6c6318895",
    "invokedFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:ExtensionTest",
    "tracing": {
        "type": "X-Amzn-Trace-Id",
        "value": "Root=1-5f35ae12-0c0fec141ab77a00bc047aa2;Parent=2be948a625588e32;Sampled=1"
    }
 }
```

**持续时间限制**：函数的超时设置会限制整个 `Invoke` 阶段的持续时间。例如，如果将函数超时设置为 360 秒，则该函数和所有扩展都需要在 360 秒内完成。请注意，没有独立的调用后阶段。持续时间是运行时系统和所有扩展调用的时间总和，直到函数和所有扩展完成运行之后才计算。

**性能影响和扩展开销**：扩展可能会影响函数性能。作为扩展作者，您可以控制扩展对性能的影响。例如，如果扩展执行计算密集型操作，那么函数的持续时间会增加，这是因为扩展和函数代码共用相同的 CPU 资源。此外，如果扩展在函数调用完成后执行大量操作，则函数持续时间会增加，因为 `Invoke` 阶段会持续，直到所有扩展指示它们都已完成。

**注意**  
Lambda 以与函数的内存设置成正比的方式分配 CPU 处理能力。在较低的内存设置下，您可能会看到执行和初始化持续时间增加，这是因为函数和扩展进程正在争用相同的 CPU 资源。要缩短执行和初始化持续时间，请尝试增加内存设置。

为了帮助识别 `Invoke` 阶段上由扩展引起的性能影响，Lambda 会输出 `PostRuntimeExtensionsDuration` 指标。此指标衡量在运行时 `Next` API 请求与上次扩展 `Next` API 请求之间所花的累积时间。要衡量所使用的内存增加量，请使用 `MaxMemoryUsed` 指标。有关函数指标的更多信息，请参阅[将 CloudWatch 指标与 Lambda 结合使用](monitoring-metrics.md)。

函数开发人员可以并行运行不同版本的函数，以了解特定扩展的影响。我们建议扩展作者发布预期的资源消耗，以便函数开发人员更容易选择合适的扩展。

### 关闭阶段
<a name="runtimes-lifecycle-extensions-shutdown"></a>

若 Lambda 即将关闭运行时，它会向每个已注册的外部扩展发送一个 `Shutdown`。扩展可以使用此时间执行最终清理任务。`Shutdown` 事件是为了响应 `Next` API 请求而发送的。

**持续时间限制**：`Shutdown` 阶段的最长持续时间取决于已注册扩展的配置：
+ 0 毫秒 – 无已注册扩展的函数
+ 500 毫秒 – 带有注册的内部扩展的函数
+ 2000 毫秒 – 具有一个或多个注册的外部扩展的函数

如果运行时或扩展没有在限制范围内响应 `Shutdown` 事件，则 Lambda 会使用 `SIGKILL` 信号结束该进程。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/Shutdown-Phase.png)


**事件负载**：`Shutdown` 事件包含关闭原因和剩余时间（以毫秒为单位）。

 `shutdownReason` 包括以下值：
+ 降速 – 正常关机
+ 超时 – 持续时间限制超时
+ 失败 – 错误情况，例如 `out-of-memory` 事件

```
{ 
  "eventType": "SHUTDOWN", 
  "shutdownReason": "reason for shutdown", 
  "deadlineMs": "the time and date that the function times out in Unix time milliseconds" 
}
```

### 权限和配置
<a name="runtimes-extensions-registration-api-e"></a>

在与 Lambda 函数相同的执行环境中运行扩展。扩展还与函数共享资源，例如 CPU、内存和 `/tmp` 磁盘存储。此外，扩展会使用与函数相同的 AWS Identity and Access Management (IAM) 角色和安全上下文。

**文件系统和网络访问权限**：扩展名在与函数运行时相同的文件系统和网络名称命名空间中运行。这意味着扩展需要与关联的操作系统兼容。如果扩展需要任何其他出站网络流量规则，您必须将这些规则应用于函数配置。

**注意**  
因为函数代码目录是只读的，所以扩展无法修改函数代码。

**环境变量**：扩展可以访问函数的[环境变量](configuration-envvars.md)，但以下特定于运行时进程的变量除外：
+ `AWS_EXECUTION_ENV`
+ `AWS_LAMBDA_LOG_GROUP_NAME`
+ `AWS_LAMBDA_LOG_STREAM_NAME`
+ `AWS_XRAY_CONTEXT_MISSING`
+ `AWS_XRAY_DAEMON_ADDRESS`
+ `LAMBDA_RUNTIME_DIR`
+ `LAMBDA_TASK_ROOT`
+ `_AWS_XRAY_DAEMON_ADDRESS`
+ `_AWS_XRAY_DAEMON_PORT`
+ `_HANDLER`

**注意**  
**检测 Lambda 托管实例：**扩展程序可以检查 `AWS_LAMBDA_INITIALIZATION_TYPE` 环境变量，以确定它们是在 Lambda 托管实例上运行，还是在 Lambda（默认）函数上运行。这是扩展程序根据执行环境类型调整其行为的推荐方法。

### 故障处理
<a name="runtimes-extensions-api-failure"></a>

**初始化失败**：如果扩展失败，Lambda 会重新启动执行环境以强制执行一致的行为，并利于扩展快速失败。此外，对于某些客户来说，扩展必须满足日志记录、安全性、监管和遥测收集等关键任务需求。

**调用失败** （例如内存不足、函数超时）：由于扩展与运行时共享资源，因此内存耗尽会影响到它们。当运行时失败时，所有扩展和运行时本身都会参与 `Shutdown` 阶段。此外，运行时可以作为当前调用的一部分自动重新启动，也可以通过延迟的重新初始化机制重新启动。

如果在 `Invoke` 期间出现故障（例如函数超时或运行时错误），Lambda 服务会执行重置。重置的行为类似于 `Shutdown` 事件。首先，Lambda 会关闭运行时，然后向每个注册的外部扩展发送一个 `Shutdown` 事件。该事件包括关闭的原因。如果此环境用于新调用，则扩展和运行时将作为下一次调用的一部分重新初始化。

![\[执行环境示例：初始化、调用、调用时出错、调用、关闭\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/Overview-Invoke-with-Error.png)


有关上图的更详细说明，请参见 [在调用阶段失败](lambda-runtime-environment.md#runtimes-lifecycle-invoke-with-errors)。

**扩展日志**：Lambda 将扩展的日志输出发送到 CloudWatch Logs。Lambda 还会在 `Init` 期间为每个扩展生成一个其他的日志事件。日志事件记录成功时的名称和注册首选项（事件、配置）或失败时的失败原因。

### 扩展故障排除
<a name="runtimes-extensions-api-trbl"></a>
+ 如果 `Register` 请求失败，请确保 `Lambda-Extension-Name` API 调用中的 `Register` 标头包含扩展的完整文件名。
+ 如果 `Register` 请求对于内部扩展失败，请确保请求未注册 `Shutdown` 事件。

## 扩展 API 参考
<a name="runtimes-extensions-registration-api"></a>

扩展 API 版本 **2020-01-01** 的 OpenAPI 规范在此处提供：[extensions-api.zip](samples/extensions-api.zip)

您可以从 `AWS_LAMBDA_RUNTIME_API` 环境变量中检索 API 终端节点的值。要发送 `Register` 请求，请在每个 API 路径之前使用前缀 `2020-01-01/`。例如：

```
http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register 
```

**Topics**
+ [

### 注册
](#extensions-registration-api-a)
+ [

### 下一步
](#extensions-api-next)
+ [

### Init 错误
](#runtimes-extensions-init-error)
+ [

### 退出错误
](#runtimes-extensions-exit-error)

### 注册
<a name="extensions-registration-api-a"></a>

在 `Extension init` 期间，所有扩展都需要在 Lambda 注册才能接收事件。Lambda 会使用扩展的完整文件名来验证扩展是否已完成引导启动序列。因此，每个 `Register` API 调用都必须包含 `Lambda-Extension-Name` 标头以及扩展的完整文件名。

内部扩展由运行时进程启动和停止，因此不允许它们注册 `Shutdown` 事件。

**路径** – `/extension/register`

**方法** – **POST**

**Request headers**（请求标头）
+ `Lambda-Extension-Name` – 扩展名的完整文件名。必需：是。类型：字符串。
+ `Lambda-Extension-Accept-Feature` – 在注册期间使用此功能以指定可选的注册功能。必需：否 类型：以逗号分隔的字符串。可使用此设置指定的功能：
  + `accountId` – 如果指定，扩展注册响应将包含账户 ID，该 ID 与您为其注册扩展的 Lambda 函数相关联。

**请求正文参数**
+ `events` – 要注册的事件数组。必需：否 类型：字符串数组。有效字符串：`INVOKE`、`SHUTDOWN`。
**注意**  
**Lambda 托管实例：**Lambda 托管实例函数的扩展程序只能注册 `SHUTDOWN` 事件。尝试注册 `INVOKE` 事件将会导致错误。这是因为 Lambda 托管实例支持在单个执行环境中进行并发调用。

**响应标头**
+ `Lambda-Extension-Identifier` – 生成所有后续请求所需的唯一代理标识符（UUID 字符串）。

**响应代码**
+ 200 – 响应正文包含函数名称、函数版本和处理程序名称。
+ 400 – 错误请求
+ 403 – 禁止访问
+ 500 – 容器错误。不可恢复状态。扩展应立即退出。

**Example 示例请求正文**  

```
{
    'events': [ 'INVOKE', 'SHUTDOWN']
}
```

**Example 示例响应正文**  

```
{
    "functionName": "helloWorld",
    "functionVersion": "$LATEST",
    "handler": "lambda_function.lambda_handler"
}
```

**Example 具有可选 accountId 功能的响应正文示例**  

```
{
    "functionName": "helloWorld",
    "functionVersion": "$LATEST",
    "handler": "lambda_function.lambda_handler",
    "accountId": "123456789012"
}
```

### 下一步
<a name="extensions-api-next"></a>

扩展发送 `Next` API 请求以接收下一个事件，此事件可以是 `Invoke` 事件或 `Shutdown` 事件。响应正文包含负载，该负载是包含事件数据的 JSON 文档。

扩展发送 `Next` API 请求，以表示它已准备好接收新事件。这是一个阻止性调用。

不要对 GET 调用设置超时，因为扩展可能暂停一段时间，直到存在要返回的事件。

**路径** – `/extension/event/next`

**方法** – **GET**

**请求标头**
+ `Lambda-Extension-Identifier` – 扩展的唯一标识符（UUID 字符串）。必需：是。类型：UUID 字符串。

**响应标头**
+ `Lambda-Extension-Event-Identifier` – 事件的唯一标识符（UUID 字符串）。

**响应代码**
+ 200 – 响应包含有关下一个事件（`EventInvoke` 或 `EventShutdown`）的信息。
+ 403 – 禁止访问
+ 500 – 容器错误。不可恢复状态。扩展应立即退出。

### Init 错误
<a name="runtimes-extensions-init-error"></a>

扩展使用此方法向 Lambda 报告初始化错误。当扩展在注册后无法初始化时调用它。Lambda 接收到错误后，进一步的 API 调用不会成功。扩展应在收到 Lambda 的响应后退出。

**路径** – `/extension/init/error`

**方法** – **POST**

**Request headers（请求标头）**
+ `Lambda-Extension-Identifier` – 扩展名的唯一标识符。必需：是。类型：UUID 字符串。
+ `Lambda-Extension-Function-Error-Type` – 扩展遇到的错误类型。必需：是。此标头由字符串值组成。Lambda 接受任何字符串，但建议您使用 <category.reason> 格式。例如：
  + Extension.NoSuchHandler
  + Extension.APIKeyNotFound
  + Extension.ConfigInvalid
  + Extension.UnknownReason

**请求正文参数**
+ `ErrorRequest` – 有关错误的其他信息。必需：否 

此字段是具有以下结构的 JSON 对象：

```
{
      errorMessage: string (text description of the error),
      errorType: string,
      stackTrace: array of strings
}
```

请注意，Lambda 接受任何 `errorType` 值。

以下示例显示了 Lambda 函数错误消息，其中函数无法解析调用中提供的事件数据。

**Example 函数错误**  

```
{
      "errorMessage" : "Error parsing event data.",
      "errorType" : "InvalidEventDataException",
      "stackTrace": [ ]
}
```

**响应代码**
+ 202 – 已接受
+ 400 – 错误请求
+ 403 – 禁止访问
+ 500 – 容器错误。不可恢复状态。扩展应立即退出。

### 退出错误
<a name="runtimes-extensions-exit-error"></a>

扩展使用此方法在退出前向 Lambda 报告错误。当您遇到意外故障时调用它。Lambda 接收到错误后，进一步的 API 调用不会成功。扩展应在收到 Lambda 的响应后退出。

**路径** – `/extension/exit/error`

**方法** – **POST**

**Request headers（请求标头）**
+ `Lambda-Extension-Identifier` – 扩展名的唯一标识符。必需：是。类型：UUID 字符串。
+ `Lambda-Extension-Function-Error-Type` – 扩展遇到的错误类型。必需：是。此标头由字符串值组成。Lambda 接受任何字符串，但建议您使用 <category.reason> 格式。例如：
  + Extension.NoSuchHandler
  + Extension.APIKeyNotFound
  + Extension.ConfigInvalid
  + Extension.UnknownReason

**请求正文参数**
+ `ErrorRequest` – 有关错误的其他信息。必需：否

此字段是具有以下结构的 JSON 对象：

```
{
      errorMessage: string (text description of the error),
      errorType: string,
      stackTrace: array of strings
}
```

请注意，Lambda 接受任何 `errorType` 值。

以下示例显示了 Lambda 函数错误消息，其中函数无法解析调用中提供的事件数据。

**Example 函数错误**  

```
{
      "errorMessage" : "Error parsing event data.",
      "errorType" : "InvalidEventDataException",
      "stackTrace": [ ]
}
```

**响应代码**
+ 202 – 已接受
+ 400 – 错误请求
+ 403 – 禁止访问
+ 500 – 容器错误。不可恢复状态。扩展应立即退出。

 

# 使用遥测 API 访问扩展的实时遥测数据
<a name="telemetry-api"></a>

通过遥测 API，扩展可以直接从 Lambda 接收遥测数据。在函数初始化和调用期间，Lambda 会自动捕获遥测数据，其中包括日志、平台指标和平台跟踪。通过遥测 API，扩展可以近乎实时地直接从 Lambda 获取该遥测数据。

在 Lambda 执行环境中，您可以为 Lambda 扩展订阅遥测流。订阅后，Lambda 会自动将所有遥测数据流式发送到您的扩展。然后，您可以灵活处理、筛选这些数据，并将其分派到首选目标，例如 Amazon Simple Storage Service (Amazon S3) 存储桶或第三方可观测性工具提供商。

下图显示了扩展 API 和遥测 API 如何从执行环境中将扩展连接到 Lambda。此外，运行时 API 还将您的运行时系统和函数连接到 Lambda。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


**重要**  
Lambda 遥测 API 取代 Lambda Logs API。**尽管 Logs API 仍然功能完备，但我们建议您今后仅使用遥测 API。**您可以使用遥测 API 或 Logs API 为扩展订阅遥测流。使用其中一个 API 进行订阅后，任何使用其他 API 进行订阅的尝试都会返回错误。

**Lambda 托管实例架构版本要求**  
Lambda 托管实例仅支持遥测 API 的 `2025-01-29` 架构版本。订阅托管实例函数的遥测流时，**必须**在订阅请求中使用 `"schemaVersion": "2025-01-29"`。使用以前的架构版本会导致事件被 Lambda 拒绝。  
`2025-01-29` 架构版本向后兼容 Lambda 托管实例和 Lambda（默认）函数，并且可以与它们结合使用。我们建议将此版本用于所有的新扩展程序，以确保这两种部署模型之间的兼容性。

扩展可以使用遥测 API 订阅三种不同的遥测流：
+ **平台遥测** – 日志、指标和跟踪，描述与执行环境运行时生命周期、扩展生命周期和函数调用相关的事件和错误。
+ **函数日志** – Lambda 函数代码生成的自定义日志。
+ **扩展日志** – Lambda 扩展代码生成的自定义日志。

**注意**  
即使扩展订阅了遥测流，Lambda 也会将日志和指标发送到 CloudWatch，并将跟踪发送到 X-Ray（如果您已激活跟踪）。

**Topics**
+ [

## 使用遥测 API 创建扩展
](#telemetry-api-creating-extensions)
+ [

## 注册扩展
](#telemetry-api-registration)
+ [

## 创建遥测侦听器
](#telemetry-api-listener)
+ [

## 指定目标协议
](#telemetry-api-destination)
+ [

## 配置内存使用量和缓冲
](#telemetry-api-buffering)
+ [

## 向遥测 API 发送订阅请求
](#telemetry-api-subscription)
+ [

## 入站遥测 API 消息
](#telemetry-api-messages)
+ [

# Lambda 遥测 API 参考
](telemetry-api-reference.md)
+ [

# Lambda 遥测 API `Event` 架构参考
](telemetry-schema-reference.md)
+ [

# 将 Lambda 遥测 API `Event` 对象转换为 OpenTelemetry 跨度
](telemetry-otel-spans.md)
+ [

# 使用 Lambda 日志 API
](runtimes-logs-api.md)

## 使用遥测 API 创建扩展
<a name="telemetry-api-creating-extensions"></a>

Lambda 扩展在执行环境中作为独立进程运行。函数调用完成后，扩展可以继续运行。由于扩展作为单独的进程，因此您可以使用与函数代码不同的语言来编写这些扩展。我们建议使已编译的语言（如 Golang 或 Rust）来编写扩展。通过这种方式，扩展为独立的二进制文件，与任何支持的运行时兼容。

下图说明了创建使用遥测 API 接收和处理遥测数据的扩展的四步过程。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/telemetry-api-creation-steps.png)


以下是每个步骤的详细内容：

1. 使用 [使用 Lambda 扩展 API 创建扩展](runtimes-extensions-api.md) 注册扩展。这步骤为您提供了 `Lambda-Extension-Identifier`，您需要在以下步骤中使用。有关如何注册扩展的更多信息，请参阅 [注册扩展](#telemetry-api-registration)。

1. 创建遥测侦听器。这可以是基本的 HTTP 或 TCP 服务器。Lambda 使用遥测侦听器的 URI 向扩展发送遥测数据。有关更多信息，请参阅 [创建遥测侦听器](#telemetry-api-listener)。

1. 使用遥测 API 中的订阅 API，为您的扩展订阅所需的遥测流。在此步骤中，您需要遥测侦听器的 URI。有关更多信息，请参阅 [向遥测 API 发送订阅请求](#telemetry-api-subscription)。

1. 通过遥测侦听器从 Lambda 获取遥测数据。您可以对这些数据进行任何的自定义处理，例如将数据分派到 Amazon S3 或外部可观测性服务。

**注意**  
Lambda 函数的执行环境可以作为其[生命周期](runtimes-extensions-api.md#runtimes-extensions-api-lifecycle)的一部分多次启动和停止。通常，您的扩展代码在函数调用期间运行，在关闭阶段也最多运行 2 秒。我们建议在遥测数据到达侦听器时对其进行批处理。然后，使用 `Invoke` 和 `Shutdown` 生命周期事件将每个批次发送到所需目的地。

## 注册扩展
<a name="telemetry-api-registration"></a>

在订阅遥测数据之前，您必须注册 Lambda 扩展。注册发生在[扩展初始化阶段](runtimes-extensions-api.md#runtimes-extensions-api-reg)。以下示例显示了注册扩展的 HTTP 请求。

```
POST http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register
 Lambda-Extension-Name: lambda_extension_name
{
    'events': [ 'INVOKE', 'SHUTDOWN']
}
```

如果请求成功，订阅者将收到一条 HTTP 200 成功响应。响应标头包含 `Lambda-Extension-Identifier`。响应正文包含函数的其他属性。

```
HTTP/1.1 200 OK
Lambda-Extension-Identifier: a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
{
    "functionName": "lambda_function",
    "functionVersion": "$LATEST",
    "handler": "lambda_handler",
    "accountId": "123456789012"
}
```

有关更多信息，请参阅[扩展 API 参考](runtimes-extensions-api.md#runtimes-extensions-registration-api)。

## 创建遥测侦听器
<a name="telemetry-api-listener"></a>

Lambda 扩展必须有一个侦听器来处理来自遥测 API 的传入请求。以下代码显示了 Golang 中的示例遥测侦听器实施：

```
// Starts the server in a goroutine where the log events will be sent
func (s *TelemetryApiListener) Start() (string, error) {
	address := listenOnAddress()
	l.Info("[listener:Start] Starting on address", address)
	s.httpServer = &http.Server{Addr: address}
	http.HandleFunc("/", s.http_handler)
	go func() {
		err := s.httpServer.ListenAndServe()
		if err != http.ErrServerClosed {
			l.Error("[listener:goroutine] Unexpected stop on Http Server:", err)
			s.Shutdown()
		} else {
			l.Info("[listener:goroutine] Http Server closed:", err)
		}
	}()
	return fmt.Sprintf("http://%s/", address), nil
}

// http_handler handles the requests coming from the Telemetry API.
// Everytime Telemetry API sends log events, this function will read them from the response body
// and put into a synchronous queue to be dispatched later.
// Logging or printing besides the error cases below is not recommended if you have subscribed to
// receive extension logs. Otherwise, logging here will cause Telemetry API to send new logs for
// the printed lines which may create an infinite loop.
func (s *TelemetryApiListener) http_handler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		l.Error("[listener:http_handler] Error reading body:", err)
		return
	}

	// Parse and put the log messages into the queue
	var slice []interface{}
	_ = json.Unmarshal(body, &slice)

	for _, el := range slice {
		s.LogEventsQueue.Put(el)
	}

	l.Info("[listener:http_handler] logEvents received:", len(slice), " LogEventsQueue length:", s.LogEventsQueue.Len())
	slice = nil
}
```

## 指定目标协议
<a name="telemetry-api-destination"></a>

使用 Telemetry API 订阅接收遥测数据时，除了目标 URI 之外，您还可以指定目标协议：

```
{
    "destination": {
        "protocol": "HTTP",
        "URI": "http://sandbox.localdomain:8080"
    }
}
```

Lambda 接受两种接收遥测数据的协议：
+ **HTTP**（推荐）– Lambda 会将遥测数据作为 JSON 格式的记录数组传送到本地 HTTP 端点（`http://sandbox.localdomain:${PORT}/${PATH}`）。`$PATH` 参数是可选的。Lambda 仅支持 HTTP，不支持 HTTPS。Lambda 通过 POST 请求传送遥测数据。
+ **TCP** – Lambda 会将遥测数据以[换行符分隔的 JSON（NDJSON）格式](https://github.com/ndjson/ndjson-spec)传送到 TCP 端口。

**注意**  
我们强烈建议使用 HTTP 而不是 TCP。使用 TCP 时，Lambda 平台无法在其将遥测数据传送到应用层时进行确认。因此，如果扩展崩溃，遥测数据可能会丢失。HTTP 则无此限制。

订阅接收遥测数据前，建立本地 HTTP 侦听器或 TCP 端口。在安装期间，请注意以下事项：
+ Lambda 只会将遥测发送到执行环境内的目标。
+ 如果没有侦听器，或者 POST 请求遇到错误，Lambda 会（使用退避）重试发送遥测数据。如果遥测侦听器崩溃，侦听器会在 Lambda 重新启动执行环境后恢复接收遥测数据。
+ Lambda 会预留端口 9001。没有其他端口号限制或建议。

## 配置内存使用量和缓冲
<a name="telemetry-api-buffering"></a>

执行环境的内存使用量随着订阅者数量的增加而线性增加。订阅会消耗内存资源，因为每个订阅都会打开一个新的内存缓冲区来存储遥测数据。缓冲区内存使用量计入执行环境中的总内存消耗量。

通过遥测 API 订阅接收遥测数据时，您可以缓冲遥测数据并将其批量传送给订阅者。要优化内存使用量，您可以指定缓冲配置：

```
{
    "buffering": {
        "maxBytes": 256*1024,
        "maxItems": 1000,
        "timeoutMs": 100
    }
}
```


| 参数 | 说明 | 默认值和限制 | 
| --- | --- | --- | 
|  `maxBytes`  |  内存中缓冲的最大遥测量（以字节为单位）。  |  默认值：262144 最小值：262144 最大值：1048576。  | 
|  `maxItems`  |  内存中缓冲的最大事件数。  |  默认值：10000 最小值：1000 最大值：10000  | 
|  `timeoutMs`  |  缓冲批次的最长时间（以毫秒为单位）。  |  默认值：1000 最小值：25 最大值：30000  | 

设置缓冲时，请记住以下几点：
+ 如果任何输入流关闭，Lambda 会刷新日志。例如，如果运行时系统崩溃，就会发生这种情况。
+ 在订阅请求中，每个订阅用户都可以自定义其缓冲配置。
+ 在确定用于读取数据的缓冲区大小时，预计接收的有效负载大小为 `2 * maxBytes + metadataBytes`，其中 `maxBytes` 为缓冲设置的组成部分。要衡量需要考虑的 `metadataBytes` 数量，请查看以下元数据。Lambda 会将与此类似的元数据附加到每条记录：

  ```
  {
     "time": "2022-08-20T12:31:32.123Z",
     "type": "function",
     "record": "Hello World"
  }
  ```
+ 如果订阅用户处理传入遥测数据的速度不够快，或者如果您的函数代码生成非常高的日志卷，Lambda 可能会删除记录以保持内存利用率限制。发生这种情况时，Lambda 会发送 `platform.logsDropped` 事件。

## 向遥测 API 发送订阅请求
<a name="telemetry-api-subscription"></a>

Lambda 扩展可以通过向遥测 API 发送订阅请求来订阅接收遥测数据。订阅请求应包含有关您希望扩展订阅的事件类型的信息。此外，请求可以包含[传送目标信息](#telemetry-api-destination)和[缓冲配置](#telemetry-api-buffering)。

在发送订阅请求之前，您必须拥有扩展 ID（`Lambda-Extension-Identifier`）。[使用扩展 API 注册扩展](#telemetry-api-registration)时，您会从 API 响应中获得扩展 ID。

订阅发生在[扩展初始化阶段](runtimes-extensions-api.md#runtimes-extensions-api-reg)。以下示例显示了订阅所有三个遥测流的 HTTP 请求：平台遥测、函数日志和扩展日志。

```
PUT http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry HTTP/1.1
{
   "schemaVersion": "2025-01-29",
   "types": [
        "platform",
        "function",
        "extension"
   ],
   "buffering": {
        "maxItems": 1000,
        "maxBytes": 256*1024,
        "timeoutMs": 100
   },
   "destination": {
        "protocol": "HTTP",
        "URI": "http://sandbox.localdomain:8080"
   }
}
```

如果请求成功，订阅者将收到 HTTP 200 成功响应。

```
HTTP/1.1 200 OK
"OK"
```

## 入站遥测 API 消息
<a name="telemetry-api-messages"></a>

使用遥测 API 订阅后，扩展会自动开始通过 POST 请求接收来自 Lambda 的遥测数据。每个 POST 请求正文都包含一个 `Event` 对象数组。每个 `Event` 的架构如下：

```
{
   time: String,
   type: String,
   record: Object
}
```
+ `time` 属性定义 Lambda 平台何时生成事件。这与事件的实际发生时间不同。`time` 的字符串值是 ISO 8601 格式的时间戳。
+ `type` 属性定义事件类型。下表介绍了所有可能的值。
+ `record` 属性定义包含遥测数据的 JSON 对象。此 JSON 对象的架构取决于 `type`。

**通过并发调用对事件进行排序**  
对于 [Lambda 托管实例](lambda-managed-instances.md)，可以在同一个执行环境中并发执行多个函数调用。在这种情况下，无法在不同并发调用之间保证 `platform.start` 和 `platform.report` 事件的顺序。扩展程序必须能够处理同时运行的多个调用所产生的事件，并且不应假定事件具有顺序性。  
为了适当地将事件归因于特定调用，扩展程序应使用这些平台事件中存在的 `requestId` 字段。每次调用都有一个唯一的请求 ID，它在该调用的所有事件中始终保持一致，这使得扩展程序即使在事件未按顺序到达的情况下也能正确地关联它们。

下表汇总了所有类型的 `Event` 对象，并链接到每种事件类型的[遥测 API `Event` 架构参考](telemetry-schema-reference.md)。


| 类别 | Event type | 说明 | 事件记录架构 | 
| --- | --- | --- | --- | 
|  平台事件  |  `platform.initStart`  |  函数初始化已启动。  |  [`platform.initStart`](telemetry-schema-reference.md#platform-initStart) 架构  | 
|  平台事件  |  `platform.initRuntimeDone`  |  函数初始化已完成。  |  [`platform.initRuntimeDone`](telemetry-schema-reference.md#platform-initRuntimeDone) 架构  | 
|  平台事件  |  `platform.initReport`  |  函数初始化的报告。  |  [`platform.initReport`](telemetry-schema-reference.md#platform-initReport) 架构  | 
|  平台事件  |  `platform.start`  |  函数调用已启动。  |  [`platform.start`](telemetry-schema-reference.md#platform-start) 架构  | 
|  平台事件  |  `platform.runtimeDone`  |  运行时通过成功或失败的方式完成对事件的处理。  |  [`platform.runtimeDone`](telemetry-schema-reference.md#platform-runtimeDone) 架构  | 
|  平台事件  |  `platform.report`  |  函数调用的报告。  |  [`platform.report`](telemetry-schema-reference.md#platform-report) 架构  | 
|  平台事件  |  `platform.restoreStart`  |  运行时恢复已开始。  |  [`platform.restoreStart`](telemetry-schema-reference.md#platform-restoreStart) 架构  | 
|  平台事件  |  `platform.restoreRuntimeDone`  |  运行时恢复已完成。  |  [`platform.restoreRuntimeDone`](telemetry-schema-reference.md#platform-restoreRuntimeDone) 架构  | 
|  平台事件  |  `platform.restoreReport`  |  运行时恢复报告。  |  [`platform.restoreReport`](telemetry-schema-reference.md#platform-restoreReport) 架构  | 
|  平台事件  |  `platform.telemetrySubscription`  |  扩展订阅了遥测 API。  |  [`platform.telemetrySubscription`](telemetry-schema-reference.md#platform-telemetrySubscription) 架构  | 
|  平台事件  |  `platform.logsDropped`  |  Lambda 删除了日志条目。  |  [`platform.logsDropped`](telemetry-schema-reference.md#platform-logsDropped) 架构  | 
|  函数日志  |  `function`  |  来自函数代码的日志行。  |  [`function`](telemetry-schema-reference.md#telemetry-api-function) 架构  | 
|  扩展日志  |  `extension`  |  来自扩展代码的日志行。  |  [`extension`](telemetry-schema-reference.md#telemetry-api-extension) 架构  | 

# Lambda 遥测 API 参考
<a name="telemetry-api-reference"></a>

使用 Lambda 遥测 API 端点订阅遥测流的扩展。您可以从 `AWS_LAMBDA_RUNTIME_API` 环境变量中检索遥测 API 端点。若要发送 API 请求，请附加 API 版本（`2022-07-01/`）和 `telemetry/`。例如：

```
http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry/
```

有关订阅响应版本 `2025-01-29` 的 OpenAPI 规范（OAS）定义，请参阅以下内容：
+ **HTTP** – [telemetry-api-http-schema.zip](samples/events_http_schema_v2025_01_29.zip)
+ **TCP** – [telemetry-api-tcp-schema.zip](samples/events_tcp_schema_v2025_01_29.zip)

**Topics**
+ [

## 订阅
](#telemetry-subscribe-api)

## 订阅
<a name="telemetry-subscribe-api"></a>

若要订阅遥测流，Lambda 扩展可以发送订阅 API 请求。
+ **路径** – `/telemetry`
+ **方法** – `PUT`
+ **标头**：
  + `Content-Type`: `application/json`
+ **请求正文参数**
  + **schemaVersion**
    + 是否必需：是
    + 类型：字符串
    + 有效值：`"2025-01-29"`、`"2022-12-13"` 或 `"2022-07-01"`
    + **注意：**Lambda 托管实例需要 `"2025-01-29"`。此版本向后兼容 Lambda（默认）函数。
  + **目标** – 定义遥测事件目标和事件传输协议的配置设置。
    + 是否必需：是
    + 类型：对象

      ```
      {
          "protocol": "HTTP",
          "URI": "http://sandbox.localdomain:8080"
      }
      ```
    + **协议** – Lambda 用于发送遥测数据的协议。
      + 是否必需：是
      + 类型：字符串
      + 有效值：`"HTTP"`\$1`"TCP"`
    + **URI** – 要向其发送遥测数据的 URI。
      + 是否必需：是
      + 类型：字符串
    + 有关更多信息，请参阅 [指定目标协议](telemetry-api.md#telemetry-api-destination)。
  + **类型** – 您希望扩展订阅的遥测类型。
    + 是否必需：是
    + 类型：字符串数组
    + 有效值：`"platform"`\$1`"function"`\$1`"extension"`
  + **缓冲** – 事件缓冲的配置设置。
    + 必需：否
    + 类型：对象

      ```
      {
         "buffering": {
              "maxItems": 1000,
              "maxBytes": 256*1024,
              "timeoutMs": 100
         }
      }
      ```
    + **maxItems** – 在内存中缓冲的最大事件数。
      + 必需：否
      + 类型：整数
      + 默认值：1000
      + 最小值：1000
      + 最大值：10000
    + **maxBytes** – 在内存中缓冲的最大遥测量（以字节为单位）。
      + 必需：否
      + 类型：整数
      + 默认值：262144
      + 最小值：262144
      + 最大值：1048576。
    + **timeoutMs** – 缓冲批的最长时间（以毫秒为单位）。
      + 必需：否
      + 类型：整数
      + 默认值：1000
      + 最小值：25
      + 最大值：30000
    + 有关更多信息，请参阅 [配置内存使用量和缓冲](telemetry-api.md#telemetry-api-buffering)。

### 订阅 API 请求示例
<a name="telemetry-subscribe-api-example"></a>

```
PUT http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry HTTP/1.1
{
   "schemaVersion": "2025-01-29",
   "types": [
        "platform",
        "function",
        "extension"
   ],
   "buffering": {
        "maxItems": 1000,
        "maxBytes": 256*1024,
        "timeoutMs": 100
   },
   "destination": {
        "protocol": "HTTP",
        "URI": "http://sandbox.localdomain:8080"
   }
}
```

如果订阅请求成功，扩展将收到 HTTP 200 成功响应：

```
HTTP/1.1 200 OK
"OK"
```

如果订阅请求失败，扩展将收到错误响应。例如：

```
HTTP/1.1 400 OK
{
    "errorType": "ValidationError",
    "errorMessage": "URI port is not provided; types should not be empty"
}
```

以下是扩展可以收到的一些其他响应代码：
+ 200 – 已成功完成请求
+ 202 – 已接受请求。本地测试环境中的订阅请求响应
+ 400 – 错误请求
+ 500 – 服务错误

# Lambda 遥测 API `Event` 架构参考
<a name="telemetry-schema-reference"></a>

使用 Lambda 遥测 API 端点订阅遥测流的扩展。您可以从 `AWS_LAMBDA_RUNTIME_API` 环境变量中检索遥测 API 端点。若要发送 API 请求，请附加 API 版本（`2022-07-01/`）和 `telemetry/`。例如：

```
http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry/
```

有关订阅响应版本 `2025-01-29` 的 OpenAPI 规范（OAS）定义，请参阅以下内容：
+ **HTTP** – [telemetry-api-http-schema.zip](samples/events_http_schema_v2025_01_29.zip)
+ **TCP** – [telemetry-api-tcp-schema.zip](samples/events_tcp_schema_v2025_01_29.zip)

下表汇总了遥测 API 支持的所有 `Event` 对象类型。


| 类别 | Event type | 说明 | 事件记录架构 | 
| --- | --- | --- | --- | 
|  平台事件  |  `platform.initStart`  |  函数初始化已启动。  |  [`platform.initStart`](#platform-initStart) 架构  | 
|  平台事件  |  `platform.initRuntimeDone`  |  函数初始化已完成。  |  [`platform.initRuntimeDone`](#platform-initRuntimeDone) 架构  | 
|  平台事件  |  `platform.initReport`  |  函数初始化的报告。  |  [`platform.initReport`](#platform-initReport) 架构  | 
|  平台事件  |  `platform.start`  |  函数调用已启动。  |  [`platform.start`](#platform-start) 架构  | 
|  平台事件  |  `platform.runtimeDone`  |  运行时通过成功或失败的方式完成对事件的处理。  |  [`platform.runtimeDone`](#platform-runtimeDone) 架构  | 
|  平台事件  |  `platform.report`  |  函数调用的报告。  |  [`platform.report`](#platform-report) 架构  | 
|  平台事件  |  `platform.restoreStart`  |  运行时恢复已开始。  |  [`platform.restoreStart`](#platform-restoreStart) 架构  | 
|  平台事件  |  `platform.restoreRuntimeDone`  |  运行时恢复已完成。  |  [`platform.restoreRuntimeDone`](#platform-restoreRuntimeDone) 架构  | 
|  平台事件  |  `platform.restoreReport`  |  运行时恢复报告。  |  [`platform.restoreReport`](#platform-restoreReport) 架构  | 
|  平台事件  |  `platform.telemetrySubscription`  |  扩展订阅了遥测 API。  |  [`platform.telemetrySubscription`](#platform-telemetrySubscription) 架构  | 
|  平台事件  |  `platform.logsDropped`  |  Lambda 删除了日志条目。  |  [`platform.logsDropped`](#platform-logsDropped) 架构  | 
|  函数日志  |  `function`  |  来自函数代码的日志行。  |  [`function`](#telemetry-api-function) 架构  | 
|  扩展日志  |  `extension`  |  来自扩展代码的日志行。  |  [`extension`](#telemetry-api-extension) 架构  | 

**Contents**
+ [

## 遥测 API `Event` 对象类型
](#telemetry-api-events)
  + [

### `platform.initStart`
](#platform-initStart)
  + [

### `platform.initRuntimeDone`
](#platform-initRuntimeDone)
  + [

### `platform.initReport`
](#platform-initReport)
  + [

### `platform.start`
](#platform-start)
  + [

### `platform.runtimeDone`
](#platform-runtimeDone)
  + [

### `platform.report`
](#platform-report)
  + [

### `platform.restoreStart`
](#platform-restoreStart)
  + [

### `platform.restoreRuntimeDone`
](#platform-restoreRuntimeDone)
  + [

### `platform.restoreReport`
](#platform-restoreReport)
  + [

### `platform.extension`
](#platform-extension)
  + [

### `platform.telemetrySubscription`
](#platform-telemetrySubscription)
  + [

### `platform.logsDropped`
](#platform-logsDropped)
  + [

### `function`
](#telemetry-api-function)
  + [

### `extension`
](#telemetry-api-extension)
+ [

## 共享对象类型
](#telemetry-api-objects)
  + [

### `InitPhase`
](#InitPhase)
  + [

### `InitReportMetrics`
](#InitReportMetrics)
  + [

### `InitType`
](#InitType)
  + [

### `ReportMetrics`
](#ReportMetrics)
  + [

### `RestoreReportMetrics`
](#RestoreReportMetrics)
  + [

### `RuntimeDoneMetrics`
](#RuntimeDoneMetrics)
  + [

### `Span`
](#Span)
  + [

### `Status`
](#Status)
  + [

### `TraceContext`
](#TraceContext)
  + [

### `TracingType`
](#TracingType)

## 遥测 API `Event` 对象类型
<a name="telemetry-api-events"></a>

本节详细介绍 Lambda 遥测 API 支持的 `Event` 对象类型。在事件描述中，问号（`?`）表示该属性可能不存在于对象中。

### `platform.initStart`
<a name="platform-initStart"></a>

`platform.initStart` 事件表示函数初始化阶段已开始。`platform.initStart` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.initStart
- record: PlatformInitStart
```

`PlatformInitStart` 对象具有以下属性：
+ **functionName** – `String`
+ **functionVersion** – `String`
+ **initializationType** – ``InitType`` 对象
+ **instanceId?** – `String`
+ **instanceMaxMemory?** – `Integer`
+ **phase** – ``InitPhase`` 对象
+ **runtimeVersion?** – `String`
+ **runtimeVersionArn?** – `String`

以下是 `platform.initStart` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:00:15.064Z",
    "type": "platform.initStart",
    "record": {
        "initializationType": "on-demand",
        "phase": "init",
        "runtimeVersion": "nodejs-14.v3",
        "runtimeVersionArn": "arn",
        "functionName": "myFunction",
        "functionVersion": "$LATEST",
        "instanceId": "82561ce0-53dd-47d1-90e0-c8f5e063e62e",
        "instanceMaxMemory": 256
    }
}
```

### `platform.initRuntimeDone`
<a name="platform-initRuntimeDone"></a>

`platform.initRuntimeDone` 事件表示函数初始化阶段已完成。`platform.initRuntimeDone` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.initRuntimeDone
- record: PlatformInitRuntimeDone
```

`PlatformInitRuntimeDone` 对象具有以下属性：
+ **initializationType** – ``InitType`` 对象
+ **phase** – ``InitPhase`` 对象
+ **status** – ``Status`` 对象
+ **spans?** – ``Span`` 对象的列表。

以下是 `platform.initRuntimeDone` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:01:15.000Z",
    "type": "platform.initRuntimeDone",
    "record": {
        "initializationType": "on-demand"
        "status": "success",
        "spans": [
            {
                "name": "someTimeSpan",
                "start": "2022-06-02T12:02:33.913Z",
                "durationMs": 70.5
            }
        ]
    }
}
```

### `platform.initReport`
<a name="platform-initReport"></a>

`platform.initReport` 事件包含函数初始化阶段的总体报告。`platform.initReport` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.initReport
- record: PlatformInitReport
```

`PlatformInitReport` 对象具有以下属性：
+ **errorType?** – 字符串
+ **initializationType** – ``InitType`` 对象
+ **phase** – ``InitPhase`` 对象
+ **metrics** – ``InitReportMetrics`` 对象
+ **spans?** – ``Span`` 对象的列表。
+ **status** – ``Status`` 对象

以下是 `platform.initReport` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:01:15.000Z",
    "type": "platform.initReport",
    "record": {
        "initializationType": "on-demand",
        "status": "success",
        "phase": "init",
        "metrics": {
            "durationMs": 125.33
        },
        "spans": [
            {
                "name": "someTimeSpan",
                "start": "2022-06-02T12:02:33.913Z",
                "durationMs": 90.1
            }
        ]
    }
}
```

### `platform.start`
<a name="platform-start"></a>

`platform.start` 事件表示函数调用阶段已开始。`platform.start` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.start
- record: PlatformStart
```

`PlatformStart` 对象具有以下属性：
+ **requestId** – `String`
+ **version?** – `String`
+ **tracing?** – ``TraceContext``

以下是 `platform.start` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:00:15.064Z",
    "type": "platform.start",
    "record": {
        "requestId": "6d68ca91-49c9-448d-89b8-7ca3e6dc66aa",
        "version": "$LATEST",
        "tracing": {
            "spanId": "54565fb41ac79632",
            "type": "X-Amzn-Trace-Id",
            "value": "Root=1-62e900b2-710d76f009d6e7785905449a;Parent=0efbd19962d95b05;Sampled=1"
        }
    }
}
```

### `platform.runtimeDone`
<a name="platform-runtimeDone"></a>

`platform.runtimeDone` 事件表示函数调用阶段已完成。`platform.runtimeDone` `Event` 对象具有以下形状：

**Lambda 托管实例**  
Lambda 托管实例不支持 `platform.runtimeDone` 事件。在托管实例上运行的扩展程序将不会收到此事件，因为扩展程序无法在托管实例上订阅 `INVOKE` 事件。由于并发执行模型可以同时处理多个调用，因此扩展程序无法像传统上在 Lambda（默认）函数上那样对单个调用执行调用后处理。  
对于托管实例，通常包含在 `platform.runtimeDone` 中的 `responseLatency` 和 `responseDuration` 跨度在 `platform.report` 事件中可用。有关详细信息，请参阅 [`platform.report`](#platform-report)。

```
Event: Object
- time: String
- type: String = platform.runtimeDone
- record: PlatformRuntimeDone
```

`PlatformRuntimeDone` 对象具有以下属性：
+ **errorType?** – `String`
+ **metrics?** – ``RuntimeDoneMetrics`` 对象
+ **requestId** – `String`
+ **status** – ``Status`` 对象
+ **spans?** – ``Span`` 对象的列表。
+ **tracing?** – ``TraceContext`` 对象

以下是 `platform.runtimeDone` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:01:15.000Z",
    "type": "platform.runtimeDone",
    "record": {
        "requestId": "6d68ca91-49c9-448d-89b8-7ca3e6dc66aa",
        "status": "success",
        "tracing": {
            "spanId": "54565fb41ac79632",
            "type": "X-Amzn-Trace-Id",
            "value": "Root=1-62e900b2-710d76f009d6e7785905449a;Parent=0efbd19962d95b05;Sampled=1"
        },
        "spans": [
            {
                "name": "someTimeSpan",
                "start": "2022-08-02T12:01:23:521Z",
                "durationMs": 80.0
            }
        ],
        "metrics": {
            "durationMs": 140.0,
            "producedBytes": 16
        }
    }
}
```

### `platform.report`
<a name="platform-report"></a>

`platform.report` 事件包含函数调用阶段的总体报告。`platform.report` `Event` 对象具有以下形状：

**Lambda 托管实例**  
与 Lambda（默认）函数相比，Lambda 托管实例的 `platform.report` 事件具有不同的指标和跨度。对于托管实例：  
**跨度**：包含 `responseLatency` 和 `responseDuration`，而不是 `extensionOverhead`。`extensionOverhead` 跨度不可用，由于并发执行模式，扩展程序无法在托管实例上订阅 `INVOKE` 事件。
**指标**：仅包含 `durationMs`。不包含以下指标：`billedDurationMs`、`initDurationMs`、`maxMemoryUsedMB` 和 `memorySizeMB`。这些基于每次调用的指标在并发执行环境中并不适用。有关资源利用率指标，请使用 [监控 Lambda 托管实例](lambda-managed-instances-monitoring.md) 或 [Lambda Insights](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-insights.html)。

```
Event: Object
- time: String
- type: String = platform.report
- record: PlatformReport
```

`PlatformReport` 对象具有以下属性：
+ **metrics** – ``ReportMetrics`` 对象
+ **requestId** – `String`
+ **spans?** – ``Span`` 对象的列表。
+ **status** – ``Status`` 对象
+ **tracing?** – ``TraceContext`` 对象

以下是 `platform.report` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:01:15.000Z",
    "type": "platform.report",
    "record": {
        "metrics": {
            "billedDurationMs": 694,
            "durationMs": 693.92,
            "initDurationMs": 397.68,
            "maxMemoryUsedMB": 84,
            "memorySizeMB": 128
        },
        "requestId": "6d68ca91-49c9-448d-89b8-7ca3e6dc66aa",
    }
}
```

### `platform.restoreStart`
<a name="platform-restoreStart"></a>

`platform.restoreStart` 事件表示函数环境还原事件已启动。在环境还原事件中，Lambda 会从缓存的快照创建环境，而不是从头开始初始化该环境。有关更多信息，请参阅 [Lambda SnapStart](snapstart.md)。`platform.restoreStart` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.restoreStart
- record: PlatformRestoreStart
```

`PlatformRestoreStart` 对象具有以下属性：
+ **functionName** – `String`
+ **functionVersion** – `String`
+ **instanceId?** – `String`
+ **instanceMaxMemory?** – `String`
+ **runtimeVersion?** – `String`
+ **runtimeVersionArn?** – `String`

以下是 `platform.restoreStart` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:00:15.064Z",
    "type": "platform.restoreStart",
    "record": {
        "runtimeVersion": "nodejs-14.v3",
        "runtimeVersionArn": "arn",
        "functionName": "myFunction",
        "functionVersion": "$LATEST",
        "instanceId": "82561ce0-53dd-47d1-90e0-c8f5e063e62e",
        "instanceMaxMemory": 256
    }
}
```

### `platform.restoreRuntimeDone`
<a name="platform-restoreRuntimeDone"></a>

`platform.restoreRuntimeDone` 事件表示函数环境还原事件已完成。在环境还原事件中，Lambda 会从缓存的快照创建环境，而不是从头开始初始化该环境。有关更多信息，请参阅 [Lambda SnapStart](snapstart.md)。`platform.restoreRuntimeDone` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.restoreRuntimeDone
- record: PlatformRestoreRuntimeDone
```

`PlatformRestoreRuntimeDone` 对象具有以下属性：
+ **errorType?** – `String`
+ **spans?** – ``Span`` 对象的列表。
+ **status** – ``Status`` 对象

以下是 `platform.restoreRuntimeDone` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:00:15.064Z",
    "type": "platform.restoreRuntimeDone",
    "record": {
        "status": "success",
        "spans": [
            {
                "name": "someTimeSpan",
                "start": "2022-08-02T12:01:23:521Z",
                "durationMs": 80.0
            }
        ]
    }
}
```

### `platform.restoreReport`
<a name="platform-restoreReport"></a>

`platform.restoreReport` 事件包含函数还原事件的总体报告。`platform.restoreReport` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.restoreReport
- record: PlatformRestoreReport
```

`PlatformRestoreReport` 对象具有以下属性：
+ **errorType?** – 字符串
+ **metrics?** – ``RestoreReportMetrics`` 对象
+ **spans?** – ``Span`` 对象的列表。
+ **status** – ``Status`` 对象

以下是 `platform.restoreReport` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:00:15.064Z",
    "type": "platform.restoreReport",
    "record": {
        "status": "success",
        "metrics": {
            "durationMs": 15.19
        },
        "spans": [
            {
                "name": "someTimeSpan",
                "start": "2022-08-02T12:01:23:521Z",
                "durationMs": 30.0
            }
        ]
    }
}
```

### `platform.extension`
<a name="platform-extension"></a>

`extension` 事件包含来自扩展代码的日志。`extension` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = extension
- record: {}
```

`PlatformExtension` 对象具有以下属性：
+ **events** – `String` 列表
+ **name** – `String`
+ **state** – `String`

以下是 `platform.extension` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:02:15.000Z",
    "type": "platform.extension",
    "record": {
        "events": [ "INVOKE", "SHUTDOWN" ],
        "name": "my-telemetry-extension",
        "state": "Ready"
    }
}
```

### `platform.telemetrySubscription`
<a name="platform-telemetrySubscription"></a>

`platform.telemetrySubscription` 事件包含有关扩展订阅的信息。`platform.telemetrySubscription` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.telemetrySubscription
- record: PlatformTelemetrySubscription
```

`PlatformTelemetrySubscription` 对象具有以下属性：
+ **name** – `String`
+ **state** – `String`
+ **types** – `String` 列表

以下是 `platform.telemetrySubscription` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:02:35.000Z",
    "type": "platform.telemetrySubscription",
    "record": {
        "name": "my-telemetry-extension",
        "state": "Subscribed",
        "types": [ "platform", "function" ]
    }
}
```

### `platform.logsDropped`
<a name="platform-logsDropped"></a>

`platform.logsDropped` 事件包含有关已丢弃事件的信息。函数输出日志的速度过快，超过 Lambda 的处理能力时，Lambda 会发出 `platform.logsDropped` 事件。当 Lambda 无法按照函数生成日志的速度将日志发送给 CloudWatch 或订阅到遥测 API 的扩展时，它会丢弃日志以防止函数的执行速度变慢。`platform.logsDropped` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = platform.logsDropped
- record: PlatformLogsDropped
```

`PlatformLogsDropped` 对象具有以下属性：
+ **droppedBytes** – `Integer`
+ **droppedRecords** – `Integer`
+ **reason** – `String`

以下是 `platform.logsDropped` 类型的示例 `Event`：

```
{
    "time": "2022-10-12T00:02:35.000Z",
    "type": "platform.logsDropped",
    "record": {
        "droppedBytes": 12345,
        "droppedRecords": 123,
        "reason": "Some logs were dropped because the downstream consumer is slower than the logs production rate"
    }
}
```

### `function`
<a name="telemetry-api-function"></a>

`function` 事件包含来自函数代码的日志。`function` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = function
- record: {}
```

`record` 字段的格式取决于函数的日志格式为纯文本还是 JSON 格式。要了解有关日志格式配置选项的更多信息，请参阅 [配置 JSON 和纯文本日志格式](monitoring-cloudwatchlogs-logformat.md)

以下是日志格式为纯文本的 `function` 类型 `Event` 示例：

```
{
    "time": "2022-10-12T00:03:50.000Z",
    "type": "function",
    "record": "[INFO] Hello world, I am a function!"
}
```

以下是日志格式为 JSON 的 `function` 类型 `Event` 示例：

```
{
    "time": "2022-10-12T00:03:50.000Z",
    "type": "function",
    "record": {
        "timestamp": "2022-10-12T00:03:50.000Z",
        "level": "INFO",
        "requestId": "79b4f56e-95b1-4643-9700-2807f4e68189",
        "message": "Hello world, I am a function!"
    }
}
```

**注意**  
如果您使用的架构版本早于 `2022-12-13` 版本，则即使将函数的日志格式配置为 JSON，也会始终将 `"record"` 呈现为字符串。对于 Lambda 托管实例，您必须使用架构版本 `2025-01-29`。

### `extension`
<a name="telemetry-api-extension"></a>

`extension` 事件包含来自扩展代码的日志。`extension` `Event` 对象具有以下形状：

```
Event: Object
- time: String
- type: String = extension
- record: {}
```

`record` 字段的格式取决于函数的日志格式为纯文本还是 JSON 格式。要了解有关日志格式配置选项的更多信息，请参阅 [配置 JSON 和纯文本日志格式](monitoring-cloudwatchlogs-logformat.md)

以下是日志格式为纯文本的 `extension` 类型 `Event` 示例：

```
{
    "time": "2022-10-12T00:03:50.000Z",
    "type": "extension",
    "record": "[INFO] Hello world, I am an extension!"
}
```

以下是日志格式为 JSON 的 `extension` 类型 `Event` 示例：

```
{
    "time": "2022-10-12T00:03:50.000Z",
    "type": "extension",
    "record": {
       "timestamp": "2022-10-12T00:03:50.000Z",
       "level": "INFO",
       "requestId": "79b4f56e-95b1-4643-9700-2807f4e68189",
       "message": "Hello world, I am an extension!"
    }    
}
```

**注意**  
如果您使用的架构版本早于 `2022-12-13` 版本，则即使将函数的日志格式配置为 JSON，也会始终将 `"record"` 呈现为字符串。对于 Lambda 托管实例，您必须使用架构版本 `2025-01-29`。

## 共享对象类型
<a name="telemetry-api-objects"></a>

本节详细介绍 Lambda 遥测 API 支持的共享对象类型。

### `InitPhase`
<a name="InitPhase"></a>

描述初始化步骤发生时的阶段的字符串枚举。在大多数情况下，Lambda 在 `init` 阶段期间运行函数初始化代码。但是，在某些发生错误的情况下，Lambda 可能会在 `invoke` 阶段期间重新运行函数初始化代码。（此情况称为*抑制初始化*。）
+ **类型** – `String`
+ **有效值** – `init`\$1`invoke`\$1`snap-start`

### `InitReportMetrics`
<a name="InitReportMetrics"></a>

包含有关初始化阶段指标的对象。
+ **类型** – `Object`

`InitReportMetrics` 对象具有以下形状：

```
InitReportMetrics: Object
- durationMs: Double
```

以下是 `InitReportMetrics` 对象的示例：

```
{
    "durationMs": 247.88
}
```

### `InitType`
<a name="InitType"></a>

描述 Lambda 如何初始化环境的字符串枚举。
+ **类型** – `String`
+ **有效值** – `on-demand`\$1`provisioned-concurrency`

### `ReportMetrics`
<a name="ReportMetrics"></a>

包含有关已完成阶段指标的对象。
+ **类型** – `Object`

`ReportMetrics` 对象具有以下形状：

```
ReportMetrics: Object
- billedDurationMs: Integer
- durationMs: Double
- initDurationMs?: Double
- maxMemoryUsedMB: Integer
- memorySizeMB: Integer
- restoreDurationMs?: Double
```

以下是 `ReportMetrics` 对象的示例：

```
{
    "billedDurationMs": 694,
    "durationMs": 693.92,
    "initDurationMs": 397.68,
    "maxMemoryUsedMB": 84,
    "memorySizeMB": 128
}
```

### `RestoreReportMetrics`
<a name="RestoreReportMetrics"></a>

包含有关已完成还原阶段指标的对象。
+ **类型** – `Object`

`RestoreReportMetrics` 对象具有以下形状：

```
RestoreReportMetrics: Object
- durationMs: Double
```

以下是 `RestoreReportMetrics` 对象的示例：

```
{
    "durationMs": 15.19
}
```

### `RuntimeDoneMetrics`
<a name="RuntimeDoneMetrics"></a>

包含有关调用阶段指标的对象。
+ **类型** – `Object`

`RuntimeDoneMetrics` 对象具有以下形状：

```
RuntimeDoneMetrics: Object
- durationMs: Double
- producedBytes?: Integer
```

以下是 `RuntimeDoneMetrics` 对象的示例：

```
{
    "durationMs": 200.0,
    "producedBytes": 15
}
```

### `Span`
<a name="Span"></a>

包含有关跨度详细信息的对象。跨度表示某个跟踪中的一个工作或操作单位。有关跨度的更多信息，请参阅 OpenTelemetry Docs 网站 **Tracing API**（跟踪 API）页面上的 [Span](https://opentelemetry.io/docs/reference/specification/trace/api/#span)（跨度）。

Lambda 对 `platform.RuntimeDone` 事件支持以下跨度：
+ `responseLatency` 跨度描述了 Lambda 函数开始发送响应所需的时间。
+ `responseDuration` 跨度描述 Lambda 函数完成发送整个响应所需的时间。
+ `runtimeOverhead` 跨度描述了 Lambda 运行时系统发出信号表明其已准备好处理下一个函数调用所需的时间。这是返回函数响应后，运行时系统调用[下一个调用](runtimes-api.md#runtimes-api-next) API 以获取下一个事件所需的时间。

以下是 `responseLatency` 跨度对象的示例：

```
{
        "name": "responseLatency", 
        "start": "2022-08-02T12:01:23.521Z",
        "durationMs": 23.02
      }
```

### `Status`
<a name="Status"></a>

描述初始化或调用阶段状态的对象。如果状态为 `failure` 或 `error`，则 `Status` 对象还会包含一个 `errorType` 字段，用来描述错误。
+ **类型** – `Object`
+ **有效状态值** – `success`\$1`failure`\$1`error`\$1`timeout`

### `TraceContext`
<a name="TraceContext"></a>

描述跟踪属性的对象。
+ **类型** – `Object`

`TraceContext` 对象具有以下形状：

```
TraceContext: Object
- spanId?: String
- type: TracingType enum
- value: String
```

以下是 `TraceContext` 对象的示例：

```
{
    "spanId": "073a49012f3c312e",
    "type": "X-Amzn-Trace-Id",
    "value": "Root=1-62e900b2-710d76f009d6e7785905449a;Parent=0efbd19962d95b05;Sampled=1"
}
```

### `TracingType`
<a name="TracingType"></a>

描述 ``TraceContext`` 对象中跟踪类型的字符串枚举。
+ **类型** – `String`
+ **有效值** – `X-Amzn-Trace-Id`

# 将 Lambda 遥测 API `Event` 对象转换为 OpenTelemetry 跨度
<a name="telemetry-otel-spans"></a>

AWS Lambda 遥测 API 架构在语义上与 OpenTelemetry（OTel）兼容。这意味着您可以将 AWS Lambda 遥测 API `Event` 对象转换为 OpenTelemetry（OTel）跨度。转换时，不应将单个 `Event` 对象映射到单个 OTel 跨度。相反，您应该在单个 OTel 跨度中呈现与生命周期阶段相关的所有三个事件。例如，`start`、`runtimeDone` 和 `runtimeReport` 事件代表单个函数调用。将所有这三项事件作为单个 OTel 跨度呈现。

您可以使用跨度事件或子（嵌套）跨度来转换事件。此页面上的表格描述了两种方法的遥测 API 架构属性和 OTel 跨度属性之间的映射。有关 OTel 跨度的更多信息，请参阅 OpenTelemetry Docs 网站 **Tracing API**（跟踪 API）页面上的 [Span](https://opentelemetry.io/docs/reference/specification/trace/api/#span)（跨度）。

**Topics**
+ [

## 使用 Span 事件映射到 OTel 跨度
](#telemetry-otel-span-events)
+ [

## 使用子跨度映射到 OTel 跨度
](#telemetry-otel-child-spans)

## 使用 Span 事件映射到 OTel 跨度
<a name="telemetry-otel-span-events"></a>

在下表中，`e` 代表来自遥测源的事件。

**映射 \$1Start 事件**


| OpenTelemetry | Lambda 遥测 API 架构 | 
| --- | --- | 
|  `Span.Name`  |  扩展根据 `type` 字段生成此值。  | 
|  `Span.StartTime`  |  使用 `e.time`。  | 
|  `Span.EndTime`  |  不适用，因为事件尚未完成。  | 
|  `Span.Kind`  |  设置为 `Server`。  | 
|  `Span.Status`  |  设置为 `Unset`。  | 
|  `Span.TraceId`  |  解析 `e.tracing.value` 中找到的 AWS X-Ray 标头，然后使用 `TraceId` 值。  | 
|  `Span.ParentId`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Parent` 值。  | 
|  `Span.SpanId`  |  如果可用，请使用 `e.tracing.spanId`。否则，生成一个新的 `SpanId`。  | 
|  `Span.SpanContext.TraceState`  |  X-Ray 跟踪上下文不适用。  | 
|  `Span.SpanContext.TraceFlags`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Sampled` 值。  | 
|  `Span.Attributes`  |  扩展可以在此处添加任何自定义值。  | 

**映射 \$1RuntimeDone 事件**


| OpenTelemetry | Lambda 遥测 API 架构 | 
| --- | --- | 
|  `Span.Name`  |  扩展根据 `type` 字段生成此值。  | 
|  `Span.StartTime`  |  使用匹配 `*Start` 事件中的 `e.time`。 或者，请使用 `e.time - e.metrics.durationMs`。  | 
|  `Span.EndTime`  |  不适用，因为事件尚未完成。  | 
|  `Span.Kind`  |  设置为 `Server`。  | 
|  `Span.Status`  |  如果 `e.status` 不等于 `success`，则设置为 `Error`。 否则，设置为 `Ok`。  | 
|  `Span.Events[]`  |  使用 `e.spans[]`。  | 
|  `Span.Events[i].Name`  |  使用 `e.spans[i].name`。  | 
|  `Span.Events[i].Time`  |  使用 `e.spans[i].start`。  | 
|  `Span.TraceId`  |  解析 `e.tracing.value` 中找到的 AWS X-Ray 标头，然后使用 `TraceId` 值。  | 
|  `Span.ParentId`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Parent` 值。  | 
|  `Span.SpanId`  |  使用 `*Start` 事件中的相同 `SpanId`。如果不可用，则使用 `e.tracing.spanId` 或生成一个新的 `SpanId`。  | 
|  `Span.SpanContext.TraceState`  |  X-Ray 跟踪上下文不适用。  | 
|  `Span.SpanContext.TraceFlags`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Sampled` 值。  | 
|  `Span.Attributes`  |  扩展可以在此处添加任何自定义值。  | 

**映射 \$1Report 事件**


| OpenTelemetry | Lambda 遥测 API 架构 | 
| --- | --- | 
|  `Span.Name`  |  扩展根据 `type` 字段生成此值。  | 
|  `Span.StartTime`  |  使用匹配 `*Start` 事件中的 `e.time`。 或者，请使用 `e.time - e.metrics.durationMs`。  | 
|  `Span.EndTime`  |  使用 `e.time`。  | 
|  `Span.Kind`  |  设置为 `Server`。  | 
|  `Span.Status`  |  使用与 `*RuntimeDone` 事件相同的值。  | 
|  `Span.TraceId`  |  解析 `e.tracing.value` 中找到的 AWS X-Ray 标头，然后使用 `TraceId` 值。  | 
|  `Span.ParentId`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Parent` 值。  | 
|  `Span.SpanId`  |  使用 `*Start` 事件中的相同 `SpanId`。如果不可用，则使用 `e.tracing.spanId` 或生成一个新的 `SpanId`。  | 
|  `Span.SpanContext.TraceState`  |  X-Ray 跟踪上下文不适用。  | 
|  `Span.SpanContext.TraceFlags`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Sampled` 值。  | 
|  `Span.Attributes`  |  扩展可以在此处添加任何自定义值。  | 

## 使用子跨度映射到 OTel 跨度
<a name="telemetry-otel-child-spans"></a>

下表描述了如何将 Lambda 遥测 API 事件转换为带 `*RuntimeDone` 跨度子（嵌套）跨度的 OTel 跨度。对于 `*Start` 和 `*Report` 映射，请参阅 [使用 Span 事件映射到 OTel 跨度](#telemetry-otel-span-events) 中的表，因为它们与子跨度相同。在此表中，`e` 代表来自遥测源的事件。

**映射 \$1RuntimeDone 事件**


| OpenTelemetry | Lambda 遥测 API 架构 | 
| --- | --- | 
|  `Span.Name`  |  扩展根据 `type` 字段生成此值。  | 
|  `Span.StartTime`  |  使用匹配 `*Start` 事件中的 `e.time`。 或者，请使用 `e.time - e.metrics.durationMs`。  | 
|  `Span.EndTime`  |  不适用，因为事件尚未完成。  | 
|  `Span.Kind`  |  设置为 `Server`。  | 
|  `Span.Status`  |  如果 `e.status` 不等于 `success`，则设置为 `Error`。 否则，设置为 `Ok`。  | 
|  `Span.TraceId`  |  解析 `e.tracing.value` 中找到的 AWS X-Ray 标头，然后使用 `TraceId` 值。  | 
|  `Span.ParentId`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Parent` 值。  | 
|  `Span.SpanId`  |  使用 `*Start` 事件中的相同 `SpanId`。如果不可用，则使用 `e.tracing.spanId` 或生成一个新的 `SpanId`。  | 
|  `Span.SpanContext.TraceState`  |  X-Ray 跟踪上下文不适用。  | 
|  `Span.SpanContext.TraceFlags`  |  解析 `e.tracing.value` 中找到的 X-Ray 标头，然后使用 `Sampled` 值。  | 
|  `Span.Attributes`  |  扩展可以在此处添加任何自定义值。  | 
|  `ChildSpan[i].Name`  |  使用 `e.spans[i].name`。  | 
|  `ChildSpan[i].StartTime`  |  使用 `e.spans[i].start`。  | 
|  `ChildSpan[i].EndTime`  |  使用 `e.spans[i].start + e.spans[i].durations`。  | 
|  `ChildSpan[i].Kind`  |  与父 `Span.Kind` 一样。  | 
|  `ChildSpan[i].Status`  |  与父 `Span.Status` 一样。  | 
|  `ChildSpan[i].TraceId`  |  与父 `Span.TraceId` 一样。  | 
|  `ChildSpan[i].ParentId`  |  使用父 `Span.SpanId`。  | 
|  `ChildSpan[i].SpanId`  |  生成新的 `SpanId`。  | 
|  `ChildSpan[i].SpanContext.TraceState`  |  X-Ray 跟踪上下文不适用。  | 
|  `ChildSpan[i].SpanContext.TraceFlags`  |  与父 `Span.SpanContext.TraceFlags` 一样。  | 

# 使用 Lambda 日志 API
<a name="runtimes-logs-api"></a>

**重要**  
Lambda 遥测 API 取代 Lambda Logs API。**尽管 Logs API 仍然功能完备，但我们建议您今后仅使用遥测 API。**您可以使用遥测 API 或 Logs API 为扩展订阅遥测流。使用其中一个 API 进行订阅后，任何使用其他 API 进行订阅的尝试都会返回错误。

**Lambda 托管实例不支持日志 API**  
Lambda 托管实例不支持日志 API。如果您正在使用托管实例函数，请改用[遥测 API](telemetry-api.md)。遥测 API 为从您的 Lambda 函数中收集和处理遥测数据提供增强功能。

Lambda 会自动捕获运行时日志并将其流式传输到 Amazon CloudWatch。此日志流包含函数代码和扩展生成的日志，以及 Lambda 作为函数调用的一部分生成的日志。

[Lambda](runtimes-extensions-api.md) 扩展可以使用 Lambda Runtime Logs API 从 Lambda [执行环境](lambda-runtime-environment.md)中直接订阅日志流。Lambda 将日志流式传输到扩展，便于扩展处理、筛选日志并将其发送到首选目标。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/logs-api-concept-diagram.png)


Logs API 允许扩展订阅三种不同的日志流：
+ Lambda 函数生成并写入 `stdout` 或 `stderr` 的函数日志。
+ 扩展代码生成的扩展日志。
+ Lambda 平台日志，记录与调用和扩展相关的事件和错误。

**注意**  
Lambda 会将所有日志发送到 CloudWatch，即使扩展订阅了一个或多个日志流也是如此。

**Topics**
+ [

## 订阅接收日志
](#runtimes-logs-api-subscribing)
+ [

## 内存使用量
](#runtimes-logs-api-memory)
+ [

## 目标协议
](#runtimes-logs-api-dest)
+ [

## 缓冲配置
](#runtimes-logs-api-buffering)
+ [

## 示例订阅
](#runtimes-logs-api-subs-example)
+ [

## Logs API 的示例代码
](#runtimes-logs-api-samples)
+ [

## Logs API 参考
](#runtimes-logs-api-ref)
+ [

## 日志消息
](#runtimes-logs-api-msg)

## 订阅接收日志
<a name="runtimes-logs-api-subscribing"></a>

Lambda 扩展可以通过向 Logs API 发送订阅请求来订阅接收日志。

要订阅接收日志，则需要扩展标识符 (`Lambda-Extension-Identifier`)。首先，[注册扩展](runtimes-extensions-api.md#extensions-registration-api-a)以接收扩展标识符。然后，在[初始化](lambda-runtime-environment.md#runtimes-lifecycle-ib)期间订阅 Logs API。初始化阶段完成后，Lambda 不会处理订阅请求。

**注意**  
Logs API 订阅是幂等的。重复的订阅请求不会导致重复订阅。

## 内存使用量
<a name="runtimes-logs-api-memory"></a>

内存使用量随着订阅者数量的增加而线性增加。订阅会消耗内存资源，因为每个订阅都会打开一个新的内存缓冲区来存储日志。为了帮助优化内存使用量，您可以调整[缓冲配置](#runtimes-logs-api-buffering)。缓冲区内存使用量计入执行环境中的总内存消耗量。

## 目标协议
<a name="runtimes-logs-api-dest"></a>

您可以选择以下协议之一来接收日志：

1. **HTTP**（推荐）– Lambda 会将日志作为 JSON 格式的记录数组传送到本地 HTTP 端点 (`http://sandbox.localdomain:${PORT}/${PATH}`)。`$PATH` 参数是可选的。请注意，只支持 HTTP，不支持 HTTPS。您可以选择通过 PUT 或 POST 来接收日志。

1. **TCP** – Lambda 会将日志以[换行符分隔的 JSON (NDJSON) 格式](https://github.com/ndjson/ndjson-spec)传送到 TCP 端口。

我们建议使用 HTTP 而不是 TCP。使用 TCP 时，Lambda 平台无法在其将日志传送到应用层时进行确认。因此，如果扩展崩溃，日志可能会丢失。HTTP 则无此限制。

我们还建议在订阅接收日志之前设置本地 HTTP 侦听器或 TCP 端口。在安装期间，请注意以下事项：
+ Lambda 只会将日志发送到执行环境内的目标。
+ 如果没有侦听器，或者 POST 或 PUT 请求导致错误，Lambda 会尝试重试发送日志（退避尝试）。如果日志订阅者崩溃，它会在 Lambda 重新启动执行环境后继续接收日志。
+ Lambda 会预留端口 9001。没有其他端口号限制或建议。

## 缓冲配置
<a name="runtimes-logs-api-buffering"></a>

Lambda 可以缓冲日志并将其发送给订阅者。您可以通过指定以下可选字段在订阅请求中配置此行为。请注意，Lambda 对未指定的字段使用默认值。
+ **timeoutMs** – 缓冲批的最长时间（以毫秒为单位）。默认值：1,000。最低：25。最大值：30,000。
+ **maxBytes** – 在内存中缓冲的最大大小（以字节为单位）。默认值：262,144。最小值：262,144。最大值：1,048,576。
+ **maxItems** – 在内存中缓冲的最大事件数。默认值：10,000。最小值：1,000。最大值：10,000。

在缓冲配置期间，请注意以下几点：
+ 如果任何输入流关闭（例如，运行时崩溃），Lambda 会刷新日志。
+ 在订阅请求中，每个订阅者都可以指定不同的缓冲配置。
+ 考虑读取数据所需的缓冲区大小。预计最多可接收 `2*maxBytes+metadata` 的有效负载，其中，`maxBytes` 在订阅请求中配置。例如，Lambda 会将以下元数据字节添加到每条记录：

  ```
  {
  "time": "2020-08-20T12:31:32.123Z",
  "type": "function",
  "record": "Hello World"
  }
  ```
+ 如果订阅者处理传入日志的速度不够快，Lambda 可能会删除日志以保持内存利用率限制。为指示丢弃记录数，Lambda 会发送一个 `platform.logsDropped` 日志。有关更多信息，请参阅 [Lambda：并非所有我的函数的日志都会出现](troubleshooting-execution.md#troubleshooting-execution-missinglogs)。

## 示例订阅
<a name="runtimes-logs-api-subs-example"></a>

以下示例显示订阅平台和函数日志的请求。

```
PUT http://${AWS_LAMBDA_RUNTIME_API}/2020-08-15/logs HTTP/1.1
{ "schemaVersion": "2020-08-15",
  "types": [
      "platform",
      "function"
    ],
  "buffering": {
      "maxItems": 1000,
      "maxBytes": 262144,
      "timeoutMs": 100
    },
  "destination": {
    "protocol": "HTTP",
    "URI": "http://sandbox.localdomain:8080/lambda_logs"
  }
}
```

如果请求成功，订阅者将收到一条 HTTP 200 成功响应。

```
HTTP/1.1 200 OK
"OK"
```

## Logs API 的示例代码
<a name="runtimes-logs-api-samples"></a>

有关显示如何将日志发送到自定义目标的示例代码，请参阅 AWS Lambda 计算博客上的[使用 AWS 扩展将日志发送到自定义目标](https://aws.amazon.com/blogs/compute/using-aws-lambda-extensions-to-send-logs-to-custom-destinations/)。

有关显示如何开发基本 Lambda 扩展和订阅 Logs API 的 Python 和 Go 代码示例，请参阅AWS示例 GitHub 存储库上的 [AWS Lambda扩展](https://github.com/aws-samples/aws-lambda-extensions)。有关构建 Lambda 扩展的更多信息，请参阅 [使用 Lambda 扩展 API 创建扩展](runtimes-extensions-api.md)。

## Logs API 参考
<a name="runtimes-logs-api-ref"></a>

您可以从 `AWS_LAMBDA_RUNTIME_API` 环境变量中检索 Logs API 终端节点。要发送 API 请求，请在 API 路径前使用前缀 `2020-08-15/`。例如：

```
http://${AWS_LAMBDA_RUNTIME_API}/2020-08-15/logs
```

Logs API 版本 **2020-08-15** 的 OpenAPI 规范可从此处获得：[logs-api-request.zip](samples/logs-api-request.zip)

### Subscribe
<a name="runtimes-logs-api-ref-a"></a>

要订阅一个或多个在 Lambda 执行环境中可用的日志流，扩展会发送 Subscribe API 请求。

**路径** – `/logs`

**方法** – **PUT**

**主体参数**

`destination`请参阅 [目标协议](#runtimes-logs-api-dest)。必需：是。类型：字符串。

`buffering`请参阅 [缓冲配置](#runtimes-logs-api-buffering)。必需：否 类型：字符串。

`types` – 要接收的日志类型的数组。必需：是。类型：字符串数组。有效值："platform"、"function"、"extension"。

`schemaVersion` – 必需：否。默认值：“2020-08-15”。设置为“2021-03-18”以便扩展接收 [`platform.runtimeDone`](#runtimes-logs-api-ref-done) 消息。

****响应参数****

提供适用于 HTTP 和 TCP 协议的订阅响应版本 **2020-08-15** 的 OpenAPI 规范：
+ HTTP：[logs-api-http-response.zip](samples/logs-api-http-response.zip)
+ TCP：[logs-api-tcp-response.zip](samples/logs-api-tcp-response.zip)

****响应代码****
+ 200 – 已成功完成请求
+ 202 – 已接受请求。在本地测试期间响应订阅请求。
+ 4XX – 错误请求
+ 500 – 服务错误

如果请求成功，订阅者将收到一条 HTTP 200 成功响应。

```
HTTP/1.1 200 OK
"OK"
```

如果请求失败，订阅者将收到一条错误响应。例如：

```
HTTP/1.1 400 OK
{
    "errorType": "Logs.ValidationError",
    "errorMessage": URI port is not provided; types should not be empty"
}
```

## 日志消息
<a name="runtimes-logs-api-msg"></a>

Logs API 允许扩展订阅三种不同的日志流：
+ 函数 – Lambda 函数生成并写入 `stdout` 或 `stderr` 的日志。
+ 扩展 – 扩展代码生成的日志。
+ 平台 – 运行时平台生成的平台日志，用于记录与调用和扩展相关的事件和错误。

**Topics**
+ [

### 函数日志
](#runtimes-logs-api-msg-function)
+ [

### 扩展日志
](#runtimes-logs-api-msg-extension)
+ [

### 平台日志
](#runtimes-logs-api-msg-platform)

### 函数日志
<a name="runtimes-logs-api-msg-function"></a>

Lambda 函数和内部扩展会生成函数日志并将其写入 `stdout` 或 `stderr`。

以下示例显示了函数日志消息的格式。\$1 "time": "2020-08-20T12:31:32.123Z", "type": "function", "record": Stack trace:\$1n\$1my-function (line 10)\$1n" \$1 

### 扩展日志
<a name="runtimes-logs-api-msg-extension"></a>

扩展可以生成扩展日志。日志格式与函数日志的格式相同。

### 平台日志
<a name="runtimes-logs-api-msg-platform"></a>

Lambda 会为平台事件（例如 `platform.start`、`platform.end` 和 `platform.fault`）生成日志消息。

或者，您可以订阅 ** 2021-03-18 ** 版本的 Logs API 架构，其中包括 `platform.runtimeDone` 日志消息。

#### 示例平台日志消息
<a name="runtimes-logs-api-examples"></a>

以下示例显示了平台开始日志和平台结束日志。这些日志指定了 requestId 指定的调用的调用开始时间和调用结束时间。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.start",
    "record": {"requestId": "6f7f0961f83442118a7af6fe80b88d56"}   
}
{
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.end",
    "record": {"requestId": "6f7f0961f83442118a7af6fe80b88d56"}   
}
```

**platform.initRuntimeDone** 日志消息显示 `Runtime init` 子阶段的状态，该子阶段是[初始化生命周期阶段](lambda-runtime-environment.md#runtimes-lifecycle-ib)的一部分。`Runtime init` 成功后，运行时会发送 `/next` 运行时 API 请求（针对 `on-demand` 和 `provisioned-concurrency` 初始化类型）或 `restore/next`（针对 `snap-start` 初始化类型）。以下示例显示适用于 `snap-start` 初始化类型的成功 **platform.initRuntimeDone** 日志消息。

```
{
  "time":"2022-07-17T18:41:57.083Z",
  "type":"platform.initRuntimeDone",
  "record":{
      "initializationType":"snap-start",
      "status":"success"
  }
}
```

**platform.initReport** 日志消息显示该 `Init` 阶段的持续时间以及该阶段已计费的毫秒数。当初始化类型为 `provisioned-concurrency` 时，Lambda 会在调用期间发送此消息。当初始化类型为 `snap-start` 时，Lambda 会在还原快照后发送此消息。以下示例显示适用于 `snap-start` 初始化类型的 **platform.initReport** 日志消息。

```
{
  "time":"2022-07-17T18:41:57.083Z",
  "type":"platform.initReport",
  "record":{
      "initializationType":"snap-start",
      "metrics":{
          "durationMs":731.79,
          "billedDurationMs":732
          }
  }
}
```

平台报告日志包含有关 requestId 指定的调用的指标。仅当调用包括冷启动时，`initDurationMs` 字段才会包含在日志中。如果 AWS X-Ray 跟踪处于活动状态，日志会包含 X-Ray 元数据。以下示例显示了包括冷启动的调用的平台报告日志。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.report",
    "record": {"requestId": "6f7f0961f83442118a7af6fe80b88d56",
        "metrics": {"durationMs": 101.51,
            "billedDurationMs": 300,
            "memorySizeMB": 512,
            "maxMemoryUsedMB": 33,
            "initDurationMs": 116.67
        }
    }
}
```

平台故障日志捕获运行时或执行环境错误。以下示例显示了平台故障日志消息。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.fault",
    "record": "RequestId: d783b35e-a91d-4251-af17-035953428a2c Process exited before completing request"
}
```

**注意**  
AWS 目前正在实施对 Lambda 服务的更改。由于这些更改，您可能会看到 AWS 账户 中不同 Lambda 函数发出的系统日志消息和跟踪分段的结构和内容之间存在细微差异。  
受此更改影响的日志输出之一是平台故障日志 `"record"` 字段。以下示例显示了新旧格式的说明性 `"record"` 字段。新样式的故障日志包含更简洁的消息  
这些更改将在未来几周内实施，除中国和 GovCloud 区域外，所有 AWS 区域 的函数都将过渡到使用新格式的日志消息和跟踪分段。



**Example 平台故障日志记录（旧样式）**  

```
"record":"RequestId: ...\tError: Runtime exited with error: exit status 255\nRuntime.ExitError"
```

**Example 平台故障日志记录（新样式）**  

```
"record":"RequestId: ... Status: error\tErrorType: Runtime.ExitError"
```

在扩展利用扩展 API 注册时，Lambda 会生成平台扩展日志。以下示例显示了平台扩展消息。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.extension",
    "record": {"name": "Foo.bar",
        "state": "Ready",
        "events": ["INVOKE", "SHUTDOWN"]
     }
}
```

在扩展订阅日志 API 时，Lambda 会生成平台日志订阅日志。以下示例显示了日志订阅消息。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.logsSubscription",
    "record": {"name": "Foo.bar",
        "state": "Subscribed",
        "types": ["function", "platform"],
    }
}
```

当扩展无法处理其接收的日志数量时，Lambda 会生成平台日志丢弃日志。以下示例显示了 `platform.logsDropped` 日志消息。

```
{     
    "time": "2020-08-20T12:31:32.123Z",
    "type": "platform.logsDropped",
    "record": {"reason": "Consumer seems to have fallen behind as it has not acknowledged receipt of logs.",
        "droppedRecords": 123,
        "droppedBytes" 12345
    }
}
```

**platform.restoreStart** 日志消息显示 `Restore` 阶段的开始时间（仅限 `snap-start` 初始化类型）。示例：

```
{ 
  "time":"2022-07-17T18:43:44.782Z", 
  "type":"platform.restoreStart", 
  "record":{} 
}
```

**platform.restoreReport** 日志消息显示 `Restore` 阶段的持续时间以及该阶段已计费的毫秒数（仅限 `snap-start` 初始化类型）。示例：

```
{
  "time":"2022-07-17T18:43:45.936Z",
  "type":"platform.restoreReport",
  "record":{
      "metrics":{
          "durationMs":70.87,
          "billedDurationMs":13
      }
  }
}
```

#### 平台 `runtimeDone` 消息
<a name="runtimes-logs-api-ref-done"></a>

如果在订阅请求中将架构版本设置为“2021-03-18”，则在函数调用成功完成或出现错误后，Lambda 会发送一条 `platform.runtimeDone` 消息。扩展可以使用此消息来停止此函数调用的所有遥测收集。

架构版本 ** 2021-03-18 ** 中日志事件类型的 OpenAPI 规范可从此处获得：[schema-2021-03-18.zip](samples/schema-2021-03-18.zip)

在运行时发送 `Next` 或 `Error` 运行时 API 请求时，Lambda 会生成 `platform.runtimeDone` 日志消息。`platform.runtimeDone` 日志会通知 Logs API 的使用者函数调用已完成。扩展可以使用此信息来决定何时发送在调用期间收集的所有遥测数据。

##### 示例
<a name="runtimes-logs-api-examples"></a>

在函数调用完成时，Lambda 会在运行时发送 NEXT 请求后发送 `platform.runtimeDone` 消息。以下示例显示了每个状态值的消息：成功、失败和超时。

**Example 成功消息示例**  

```
{
    "time": "2021-02-04T20:00:05.123Z",
    "type": "platform.runtimeDone",
    "record": {
       "requestId":"6f7f0961f83442118a7af6fe80b88",
       "status": "success"
    }
}
```

**Example 失败消息示例**  

```
{
   "time": "2021-02-04T20:00:05.123Z",
   "type": "platform.runtimeDone",
   "record": {
      "requestId":"6f7f0961f83442118a7af6fe80b88",
      "status": "failure"
   }
}
```

**Example 超时消息示例**  

```
{
   "time": "2021-02-04T20:00:05.123Z",
   "type": "platform.runtimeDone",
   "record": {
      "requestId":"6f7f0961f83442118a7af6fe80b88",
      "status": "timeout"
  }
}
```

**Example platform.restoreRuntimeDone 消息示例（仅限 `snap-start` 初始化类型）**  
**platform.restoreRuntimeDone** 日志消息显示 `Restore` 阶段是否成功。当运行时发送 `restore/next` 运行时 API 请求时，Lambda 会发送此消息。存在三种可能的状态：成功、失败和超时。以下示例显示了成功的 **platform.restoreRuntimeDone** 日志消息。  

```
{
  "time":"2022-07-17T18:43:45.936Z",
  "type":"platform.restoreRuntimeDone",
  "record":{
      "status":"success"
  }
}
```