从设计之初就原生支持 OTel – 构建可导出到任意可观测性堆栈的产品

Hacker News Top 工具

摘要

OpenTelemetry 官方博客介绍了如何从产品设计之初就实现 OTel 原生支持,让用户可以将日志、追踪和指标导出到任意可观测性后端,避免供应商锁定。文章概述了良好的遥测系统应具备的特性,包括符合语义约定、保留丰富上下文以及通过 OTLP 协议实现标准化导出。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/10/09 09:21

# 原生支持 OpenTelemetry 的设计——构建可导出至任意可观测性栈的产品 来源:https://opentelemetry.io/blog/2026/otel-native-by-design/ 贡献者:Dan Gomez Blanco(https://github.com/danielgblanco)(New Relic) 如果你正在构建自托管软件或 SaaS 产品,你的用户最终会希望将**日志、追踪和指标**导出到他们自己的可观测性栈中——无论是为了满足合规要求、控制成本,还是为了将所有可观测性数据集中管理。将用户锁定在你内置的仪表盘中,或者限制只能导出到特定厂商的后端,都会造成不必要的摩擦。相反,支持导出到任何兼容 OpenTelemetry(OTel)的后端,是一种厂商中立、面向未来的做法,能够让用户自由选择自己的可观测性栈。本文概述了如何设计你的产品,使用户能够在需要时将日志、追踪和指标导出到 OTel 后端。通过 OTLP 标准支持遥测导出,让用户能够在其选择的平台上拥有并分析自己的数据。 ## 四大可观测性信号 OpenTelemetry 定义了四种信号类型,全部通过标准的 OpenTelemetry 协议(OTLP)(https://opentelemetry.io/docs/specs/otlp/)传输: - **日志(Logs)**(https://opentelemetry.io/docs/concepts/signals/logs/):事件记录、请求/访问日志以及带有时间戳和元数据的应用日志。 - **追踪(Traces)**(https://opentelemetry.io/docs/concepts/signals/traces/):分布式追踪和 Span,让用户能够查看跨服务的请求流程,并将其与日志关联。 - **指标(Metrics)**(https://opentelemetry.io/docs/concepts/signals/metrics/):计数器、仪表盘和直方图(例如请求速率、延迟、错误率)。 - **性能剖析(Profiles)**(https://opentelemetry.io/docs/concepts/signals/profiles/):采样数据,展示应用程序在运行期间消耗资源的位置。 同样的导出方式适用于所有三种信号(日志、追踪和指标):让用户配置一个 OTLP 端点,并**推送**遥测数据到该端点。你可以根据产品生成的数据类型,支持其中一种、两种或全部三种信号。许多支持 OTel 导出的平台至少支持追踪和日志,而且现在越来越多的平台也开始支持指标。从一开始就为所有三种信号进行设计,可以避免日后需要返工。 ## 一个"好的"遥测系统是什么样的 一个可靠的导出方案对于你支持的每种信号都应具备以下几个明确特性: - **厂商中立:**用户可以指向任何兼容 OTel 的端点——无论是 Collector 实例(https://opentelemetry.io/docs/collector/),还是众多直接支持 OTLP 的后端之一(https://opentelemetry.io/ecosystem/vendors/)——而无需为每个后端构建自定义集成。 - **无需深度定制开发:**外部平台(或用户的工具)可以使用标准的 OTel SDK(https://opentelemetry.io/docs/languages/)和 OTLP 协议进行集成,而无需依赖专有 API。 - **保留丰富的上下文:**导出的数据应包含元数据、时间戳以及追踪/Span 关联信息(例如,日志记录关联到追踪 ID),使用户能够在自己的后端中进行调试和分析,而不会丢失上下文。 - **遵循语义约定(Semantic Conventions):**遵守语义约定(https://opentelemetry.io/docs/specs/semconv/)可确保遥测数据保持标准化,并能被任何兼容后端轻松解读。这同时降低了最终用户的认知负担,无论是第一方还是第三方系统,用户都不需要额外理解软件系统的内部工作方式。 如果你的设计在你发出的信号上遵循这些原则,那么你就与现代平台在可观测性导出方面的思路保持一致了。 ## 两种场景:你的产品运行在哪里? 添加 OTel 导出的方式取决于**谁拥有产生遥测数据的系统**。明确这一点有助于你选择正确的方案。 ### 自托管软件 你的产品是一个应用或系统(例如身份认证服务器、服务网格、数据库),由客户安装并运行在*他们自己的*环境中(他们的数据中心、他们的云、他们的 Kubernetes 集群)。在这种情况下,你**对产品进行插桩**(instrument)以集成 OpenTelemetry。当客户配置了端点(例如通过环境变量(https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/)或配置文件),你的应用程序会从他们正在运行的进程中导出遥测数据。由于 OpenTelemetry 提供了标准的配置方式(https://opentelemetry.io/docs/specs/otel/configuration/),你的用户可以期待与他们使用任何其他 OTel 插桩系统时相同的配置体验。导出发生在客户的环境中;他们控制二进制文件和导出目标。 *示例:Keycloak、Kuma。* ### 云平台 你的产品是一个平台,客户在上面部署*他们自己的*应用或使用你的托管服务(例如 PaaS、Serverless、API 网关)。工作负载运行在*你的*基础设施上。在这种情况下,你需要添加一个**平台功能**,例如"Telemetry Drains"或"Observability Destinations",让客户配置遥测数据的发送目标。你的平台从他们的工作负载(以及你自己的服务,如路由器)收集遥测数据,并将其转发到客户的 OTLP 端点。导出由你的基础设施完成,而不是由客户运行的应用程序二进制文件完成。 *示例:Heroku、Cloudflare。* 简而言之:**用户部署的软件**→ 专注于**内置插桩**和端点配置。**你运营的平台**→ 专注于**可配置的导出目标**,由你的基础设施负责转发数据。 ## 其他人是怎么做的 本文重点介绍了四个集成——Kuma、Keycloak、Cloudflare 和 Heroku——作为上述两种场景的代表性示例,但它们远非唯一已经通过 OTLP 原生导出遥测数据的产品。OpenTelemetry 集成页面(https://opentelemetry.io/ecosystem/integrations/)展示了提供原生插桩或一流插件的库和服务。以下是这四个平台如何处理**三种信号**(或其子集)以及你可以从中学到什么。 | 平台 | 日志 | 追踪 | 指标 | 部署方式 | 备注 | |------|------|------|------|----------|------| | Kuma | 是 | 是 | 是 | 用户自行部署的软件 | 每种信号有独立策略,全部基于 OTel | | Keycloak | 是† | 是 | 是 | 用户自行部署的软件 | †日志目前为预览状态;所有信号使用同一个端点 | | Cloudflare Workers | 是 | 是 | 否* | 平台 | *暂不支持指标导出 | | Heroku | 是 | 是 | 是 | 平台 | 用户通过 `--signals` 选择信号类型 | ### 自托管方案:Kuma 和 Keycloak 如果你的用户将软件部署到自己的环境中,最佳实践是预先为应用集成 OpenTelemetry 插桩,并暴露配置选项让用户指定 OTLP 端点。 #### Kuma 无论客户是在自己的 Kubernetes 集群还是虚拟机上运行 Kuma 的控制平面和数据平面,它都已预配置好可将日志、追踪和指标发送到 OTel 后端。用户通过网格策略配置导出,导出来自其 Kuma 部署: - **MeshAccessLog:**将访问日志路由到 OTel Collector(端点 + 属性,如网格名称、开始时间)。 - **MeshTrace:**处理分布式追踪,支持可配置的采样和标签。 - **MeshMetric:**暴露控制平面和数据平面的指标,支持与 OpenTelemetry 和 Prometheus 集成。 例如,将追踪发送到 OTel 后端的配置如下: ```yaml # MeshTrace policy backends: - type: OpenTelemetry openTelemetry: endpoint: otel-collector:4317 ``` 发送访问日志遵循相同的模式,只是使用不同的策略: ```yaml # MeshAccessLog policy backends: - type: OpenTelemetry openTelemetry: endpoint: otel-collector:4317 body: kvlistValue: values: - key: mesh value: stringValue: '%KUMA_MESH%' attributes: - key: start_time value: stringValue: '%START_TIME%' ``` 延伸阅读: - Kuma MeshAccessLog – OpenTelemetry(https://kuma.io/docs/2.13.x/policies/meshaccesslog/#opentelemetry) - Kuma MeshTrace(https://kuma.io/docs/latest/policies/meshtrace/)(OpenTelemetry 后端) - Kuma 可观测性(https://kuma.io/docs/2.13.x/explore/observability/) #### Keycloak Keycloak 是另一个提供出色遥测导出功能的自托管软件示例。用户无需额外的 sidecar 或平台功能,只需传入一个启动参数指向其 Collector 端点,Keycloak 进程本身即可处理导出。它使用单一遥测端点,但提供细粒度的参数来单独开关特定信号: - **追踪:**`tracing-enabled=true`(覆盖 HTTP 请求、数据库、LDAP、出站 HTTP/IdP)。 - **指标:**通过同一 OTel 集成暴露详细的指标。 - **日志:**目前处于预览状态,默认禁用(`--features=opentelemetry-logs --telemetry-logs-enabled=true`,使用 `--telemetry-logs-level` 进行级别过滤)。 定义端点、可选头部和首选协议(gRPC 或 HTTP)的配置如下: ```bash bin/kc.sh start --telemetry-endpoint=http://my-otel-endpoint:4317 --telemetry-protocol=grpc ``` 延伸阅读: - Keycloak 可观测性 / 遥测(https://www.keycloak.org/observability/telemetry) ### 平台方案:Cloudflare 和 Heroku 当你掌控基础设施时,一个直接的用户体验是在平台层面处理导出,从用户的工作负载中拉取数据并推送到他们指定的目标。 #### Cloudflare Workers 由于用户直接在 Cloudflare 的基础设施上运行代码,Cloudflare 通过**Observability Destinations**平台功能来处理导出。它为用户提供了一个简化的操作流程,用户可以在仪表盘中配置 OTLP 端点。配置完成后,Cloudflare 会自动将来自 Workers 的追踪和日志推送到该目标。虽然目前尚不支持指标,但追踪数据通过记录处理程序调用、绑定、出站 fetch 调用等信息,提供了深入的端到端可见性。用户还可以在 `wrangler.toml` 中配置采样率。 延伸阅读: - 从 Workers 导出 OpenTelemetry 数据(https://developers.cloudflare.com/workers/observability/exporting-opentelemetry-data/) - Cloudflare Workers 与追踪(https://developers.cloudflare.com/workers/observability/traces/) #### Heroku Heroku 采用了一种略有不同且高度可配置的方式——**Telemetry Drains**。用户通过指定端点、传输协议和头部来添加目标,然后明确选择*要导出哪些信号*。Heroku 平台随后从用户的应用程序(通过 OTel SDK)和第一方服务(如 Router)收集数据,并将其推送到目标。 ```bash heroku telemetry:add --app --signals traces,metrics,logs --transport http --headers '{"Authorization": "ingestion key"}' ``` 让用户细粒度地控制要导出哪些信号,是一种务实的设计模式,尤其适合需要管理数据量和摄取成本的团队。 延伸阅读: - Heroku 遥测(https://devcenter.heroku.com/articles/heroku-telemetry) - Heroku OpenTelemetry 信号与属性(https://devcenter.heroku.com/articles/heroku-opentelemetry-signals-and-attributes-reference) - 使用 Heroku Telemetry Drains(https://devcenter.heroku.com/articles/working-with-heroku-telemetry-drains) ## 设计你的导出模型 在所有三种核心遥测信号中,基础架构问题始终相同:你的平台是要求用户定期**轮询 API 获取数据**,还是**将遥测数据直接推送**到用户定义的端点? ### 传统方案:自定义轮询 API 平台传统上通过提供 API 来暴露遥测数据,用户需要定期轮询这些 API、处理分页,并将结果摄取到自己的后端中。如果你已经有一个成熟的、经过充分测试的日志或指标 API,这是一个合理的起点,因为扩展它通常比构建新的推送路径更容易。然而,这种方案存在实际的代价: - 你将大量运营责任转移给了用户。他们现在必须构建可扩展的轮询系统,能够管理轮询间隔、处理 API 响应分页、在失败时重试以及回填缺失数据。 - 用户可能会构建无法扩展、不符合你的标准的自定义解决方案,而且随着你的 API 架构随平台一起演进,他们在维护方面需要付出大量精力。 - 实现实时交付变得显著困难,而实时性往往是追踪和指标等延迟敏感信号的关键需求。 对于日志,基于拉取的实现通常如下所示(例如,CloudWatch Logs 风格(https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/8bee89f9928b4b1f81700f9ab0e5886d428bfae6/receiver/awscloudwatchreceiver/logs.go#L293)): ``` state: last_end_time every poll_interval: start_time = last_end_time end_time = now() next_token = null do: response = FilterLogEvents(log_groups, start_time, end_time, next_token) emit(response.events) next_token = response.nextToken while next_token != null ``` 在这里,你需要为指标或追踪 API 编写类似的状态跟踪逻辑。尽管自定义轮询模式会强制用户编写自定义代码来将你的 API 响应转换为标准格式,但在无法使用 Prometheus 等更标准化方案的情况下,它对于每种受支持的信号来说都是可行的。然而,对于新的设计,它不应成为默认选择。 ### 面向标准的方案:OTLP 对于面向开发者的实时遥测场景,OTLP 推送已经成为主流模式。你的服务(或你运行的 OpenTelemetry Collector)无需等待被请求,而是主动使用 OTLP(通过 HTTP 或 gRPC)将日志、追踪和指标直接导出到用户配置的端点。它使用一种厂商中立的行业标准协议来处理所有遥测数据,这意味着你不必为每种受支持的信号重复实现遥测交付逻辑。此外,OTLP 为结构化数据和元数据提供了原生支持,有助于自动保留关键上下文,例如将特定日志记录与其父追踪 ID 关联。从用户的角度来看,这几乎是即插即用的。任何兼容 OTel 的后端都可以近乎实时地摄取数据,而无需自定义轮询逻辑。 ### 构建导出体验 在产品中实现导出模型时,目标是通过最少的配置实现最大的灵活性。 #### 让用户配置 OTLP 端点

相似文章

@XAMTO_AI: OpenObserve 在圈子里炸了,基于 Rust 的可观测平台,专门收拾那些贵得离谱的日志工具。AGPL-3.0 协议,单文件部署,几分钟搞定。 存储成本暴降 140 倍:Parquet + S3 架构,占用小到夸张 全打包:日志、指…

X AI KOLs Timeline

OpenObserve 是一个基于 Rust 的开源可观测平台,支持日志、指标、链路追踪和 RUM,存储成本比 Elasticsearch 低 140 倍,单文件即可部署,是 Datadog 的开源替代方案。

你用什么进行可观测性?

Reddit r/LocalLLaMA

一位开发者讨论了AI代理缺乏合适的可观测性工具,对现有解决方案如Opik表示失望,并希望有一个支持OpenTelemetry的服务,用于分析代理会话和故障模式。