使用 OpenTelemetry Collector 扩展层观察 Lambda
从现代应用程序中获取遥测数据非常简单(或者至少应该如此)。您设置一个收集器,该收集器要么从您的应用程序接收数据,要么要求它提供各种计数器的最新状态。这大约每分钟发生一次,如果延迟一秒或提前一秒,没有人真的会注意到。但是,如果应用程序的运行时间很短呢?如果等待数据收集的每一秒都要收费呢?那么您很可能在考虑函数即服务 (FaaS) 环境,其中最知名的是 AWS Lambda。
在此执行模型中,函数被直接调用,然后环境被冻结。您只需为实际执行时间付费,不再需要服务器来等待传入请求。这也是“无服务器”一词的由来。让函数保持运行直到可以收集指标并不是一个真正的选择,即使您愿意为此付费,不同的调用也将具有完全独立的上下文,并且不一定会了解同时发生的所有其他执行。您现在可能会说:“我将在执行结束时推送所有数据,这里没有问题!”,但这并不能解决问题。您仍然需要为发送数据所需的时间付费,并且有很多调用会累加。
但还有另一种方法!Lambda 扩展层允许您在代码旁边运行任何进程,共享执行运行时并提供附加服务。通过 opentelemetry-lambda 扩展层,您将获得一个本地端点来发送数据,同时它会跟踪 Lambda 的生命周期并确保您的遥测数据被发送到存储层。
它是如何工作的?
当您的函数首次被调用时,扩展层会启动一个 OpenTelemetry Collector 实例。Collector 的构建是一个精简版本,仅提供 Lambda 上下文中必需的组件。它会向 Lambda Extensions API 和 Telemetry API 注册。通过这样做,它会在您的函数被执行、发出日志行或执行上下文即将关闭时收到通知。
这里是奇迹发生的地方
到目前为止,这似乎只是无用的额外工作。您仍然需要等待 Collector 导出数据,对吗?这就是特殊的 decouple 处理器发挥作用的地方。它在与 Lambda 生命周期交互的同时,分离了接收和导出组件。这使得 Lambda 可以提前返回,即使并非所有数据都已发送。在下一次调用时(或在关闭时),Collector 会继续导出数据,而您的函数则执行其任务。
展示有无 Collector 时执行时间差异的图表
我该如何使用它?
截至 2024 年 11 月,opentelemetry-lambda 项目已发布 Collector 扩展层的版本。它可以通过托管在 S3 存储桶或任意 HTTP 服务器上的配置文件进行配置。也可以将配置文件与您的 Lambda 代码捆绑在一起。在这两种情况下,您都需要考虑权衡。远程配置文件会增加冷启动时间,因为需要发出额外的请求;而捆绑配置文件则在尝试控制多个 Lambda 的配置时会增加管理开销。
最简单的入门方法是使用嵌入式配置。为此,请在您的函数中添加一个名为 collector.yaml 的文件。这是一个常规的 Collector 配置文件。要利用特定于 Lambda 的扩展,需要对其进行配置。例如,下一个示例配置从 Telemetry API 接收跟踪和日志,并将它们发送到另一个端点。
receivers:
telemetryapi:
exporters:
otlphttp/external:
endpoint: 'external-collector:4318'
processors:
batch:
decouple:
service:
pipelines:
traces:
receivers: [telemetryapi]
processors: [batch, decouple]
exporters: [otlphttp/external]
logs:
receivers: [telemetryapi]
processors: [batch, decouple]
exporters: [otlphttp/external]
如果省略 decouple 处理器,则默认配置。在此示例中,它被明确添加以说明整个管道。有关更多信息,请参阅 自动配置。
之后,将 OPENTELEMETRY_COLLECTOR_CONFIG_URI 环境变量设置为 /var/task/collector.yaml。函数重新部署后,您将看到函数日志出现!您可以在下面的视频中看到这个过程。
您的 Lambda 生成的每一行日志都将发送到指定的 external-collector 端点。您根本不需要修改代码!从那里,遥测数据像往常一样流向您的后端。由于在 Lambda 未激活时遥测数据的传输可能会被冻结,因此日志可能会延迟到达。它们将在下次执行期间或关闭间隔期间到达。
如果您想进一步了解您的应用程序,还可以查看 特定语言的自动插装层。