OpenTelemetry 客户端设计原则

本文档定义了通用原则,这些原则将帮助设计者创建易于使用、在所有支持的语言中统一,同时又允许足够灵活性的语言特定表达力的 OpenTelemetry 客户端。

OpenTelemetry 客户端应开箱即用提供全部功能,并通过可扩展性实现创新和实验。

请先阅读 概述,以了解 OpenTelemetry 的基本架构。

本文档不打算描述 OpenTelemetry 客户端 API 的细节或功能。有关 API 规范,请参阅 API 规范

致 OpenTelemetry 客户端作者: OpenTelemetry 规范、API 和 SDK 实现指南仍在开发中。如果您发现信息不完整或缺失、矛盾、风格不一致以及其他缺陷,请通过在此存储库中创建问题或在 Slack 发帖告知规范编写者。作为规范的实现者,您通常对如何改进规范有宝贵的见解。规范 SIG 和技术委员会成员非常重视您的意见,并欢迎您的反馈。

要求

  1. OpenTelemetry API 必须定义明确且与实现清晰分离。这使得最终用户可以仅使用 API 而不使用实现(参见第 2 点和第 3 点,了解其重要性)。

  2. 第三方库和框架在代码中添加仪器时,将仅依赖 OpenTelemetry 客户端的 API。第三方库和框架的开发人员不关心(也无法知道)最终应用程序中使用的是哪个 OpenTelemetry 实现。为了实现这种清晰的分离,OpenTelemetry API 和 SDK 库**必须**作为独立的项目提供。

  3. 最终应用程序的开发人员通常决定如何配置 OpenTelemetry SDK 和使用哪些扩展。他们还应自由选择不使用任何 OpenTelemetry 实现,即使应用程序和/或其库已进行仪器化。理由是,使用 OpenTelemetry 进行仪器化的第三方库和框架在不希望使用 OpenTelemetry 的应用程序中仍必须完全可用(这样可以避免框架开发人员为他们的框架提供“已仪器化”和“未仪器化”的版本)。

  4. SDK 必须清楚地划分为与线协议无关的部分,这些部分实现通用逻辑(例如,批量处理、通过进程信息丰富标签等),以及与协议相关的遥测导出器。遥测导出器必须包含最少的功能,从而使供应商能够轻松添加对他们特定协议的支持。

  5. SDK 实现应包含以下导出器:

    • 日志、指标、跟踪
      • OTLP (OpenTelemetry Protocol)。
      • 标准输出(或日志记录),用于调试和测试,以及作为各种日志代理工具的输入。
      • 内存(模拟)导出器,它将遥测数据累积在本地内存中,并允许对其进行检查(例如,单元测试有用)。
    • 指标
      • Prometheus。
    • 跟踪
      • Zipkin。

    注意:其中一些支持多种协议(例如,gRPC、Thrift 等)。导出器中要实现的具体协议列表待定。

    其他特定于供应商的导出器(实现供应商协议的导出器)不应包含在 OpenTelemetry 客户端中,而应放在其他地方(存储和维护供应商特定导出器的确切方法将在未来定义)。

OpenTelemetry 客户端通用设计

以下是 OpenTelemetry 客户端的通用设计(箭头表示调用)

OpenTelemetry client Design Diagram

预期用法

OpenTelemetry 客户端由 4 种类型的 组成:API 包、SDK 包、语义约定包和插件包(例如,Contrib)。API 和 SDK 根据信号类型(例如,一个用于 api-trace,一个用于 api-metric,一个用于 sdk-trace,一个用于 sdk-metric)分为多个包,这是实现细节,只要 API 项目与 SDK 项目保持分离即可。

想要使用 OpenTelemetry 进行仪器化的库、框架和应用程序仅依赖于 API 包。这些第三方库的开发人员将调用 API 来生成遥测数据。

使用 OpenTelemetry API 进行仪器化的第三方库的应用程序控制是否安装 SDK 和生成遥测数据。当未安装 SDK 时,API 调用应为 no-ops,产生最小开销。

为了实现遥测,应用程序必须依赖 OpenTelemetry SDK。应用程序还必须配置导出器和其他插件,以便能够正确生成遥测数据并将其传输到其选择的分析工具。插件的启用和配置细节因语言而异。

API 和最小实现

API 包是一个独立的依赖项,这意味着如果最终用户应用程序或第三方库仅依赖于它而不接入完整的 SDK 实现,那么应用程序将能够构建和运行而不会失败,尽管实际上不会有遥测数据被传递到遥测后端。

这种独立性是通过以下方式实现的:

API 依赖项包含 API 的最小实现。当应用程序中没有显式包含其他实现时,将不会收集遥测数据。在这种情况下,活动组件如下所示:

Minimal Operation Diagram

重要的是,从 API 的最小实现返回的值是有效的,并且不需要调用者执行额外的检查(例如,`createSpan()` 方法不应失败并应返回一个有效的非空 Span 对象)。调用者不必知道并担心最小实现正在生效的事实。这最大限度地减少了仪器化代码中的样板代码和错误处理。

同样重要的是,最小实现应尽可能少的性能开销,以便使用 OpenTelemetry 进行仪器化的第三方框架和库对不想使用 OpenTelemetry 的用户施加的开销可以忽略不计。

SDK 实现

SDK 实现是一个独立的(可选)依赖项。当它被接入时,它将替换 API 包中包含的最小实现(确切的替换机制取决于语言)。

SDK 实现将 API 调用转换为可导出遥测数据所需的核心功能。当启用 SDK 时,OpenTelemetry 组件如下所示:

Full Operation Diagram

SDK 定义了一个 Exporter 接口。负责将遥测数据发送到后端的特定于协议的导出器必须实现此接口。

SDK 还包括可选的辅助导出器,如果需要,可以使用它们来实现附加功能。

库设计者需要根据 此通用规范 定义特定于语言的 `Exporter` 接口。

协议导出器

预期遥测后端供应商实现 Exporter 接口。通过 `Export()` 函数接收的数据应以供应商特定方式进行序列化和发送到后端。

鼓励供应商尽量保持特定于协议的导出器简单,并使用 SDK 提供的辅助功能来实现所需的附加功能,如排队和重试。

应为最终用户提供灵活性,让他们能够就对他们应用程序最有意义的排队、重试、标记和批量处理功能做出许多决定。例如,如果应用程序的遥测数据必须传递到一个不保证可用性的远程后端,最终用户可以选择使用持久化的本地队列和 `Exporter` 在失败时重试发送。相反,对于将遥测数据发送到本地运行的 Agent 守护程序的应用程序,最终用户可能更喜欢更简单的导出配置,而无需重试或排队。

如果 SDK 的附加导出器作为独立库提供,则该库的名称应根据相应技术的命名约定,以“OpenTelemetry”和“Exporter”作为前缀。

例如

  • Python 和 Java:opentelemetry-exporter-{vendor_name}
  • Javascript:@opentelemetry/exporter-{vendor_name}

资源检测

鼓励云供应商提供从环境中检测资源信息的包。这些**必须**在 SDK 之外实现。有关更多详细信息,请参阅 资源 SDK

替代实现

最终用户应用程序可以决定依赖替代实现。

SDK 提供了一个可供许多实现使用的灵活性和可扩展性。在开发替代实现之前,请审查 OpenTelemetry 提供的可扩展性点。

替代实现的一个用例是自动化测试。可以在自动化测试期间接入模拟实现。例如,它可以将所有生成的遥测数据存储在内存中,并提供检查这些存储数据的能力。这将允许测试验证遥测是否正确生成。鼓励 OpenTelemetry 客户端作者提供此类模拟实现。

请注意,通过使用 SDK 和 Mock `Exporter` 也可以实现模拟,而无需替换整个 SDK。

选择的模拟方法将取决于测试目标以及在测试期间需要拦截遥测数据路径的确切点。

版本标签

API 和 SDK 包必须使用语义版本号。API 包的版本号和 SDK 包的版本号是解耦的,并且可以不同(并且它们都可以与它们实现的规范版本号不同)。API 和 SDK 包**必须**标记有其自己的版本号。

这种版本号的解耦允许 OpenTelemetry 客户端作者独立发布 API 和 SDK 包,而无需与规范协调和匹配版本号。

由于 API 和 SDK 包的版本号不耦合,因此每个 API 和 SDK 包的发布**必须**清楚地说明它们实现的规范版本号。此外,如果特定版本的 SDK 包仅与特定版本的 API 包兼容,则此兼容性信息也必须由 OpenTelemetry 客户端作者发布。OpenTelemetry 客户端作者**必须**在发布说明中包含此信息。例如,SDK 包的发布说明可能写着:“SDK 0.3.4,与 API 0.1.0 一起使用,实现了 OpenTelemetry 规范 0.1.0”。

TODO:使用 OpenTelemetry 进行仪器化的第三方库作者应如何指导其最终用户找到正确的 SDK 包?

性能和阻塞

有关 API 实现应满足的性能期望、满足这些期望的策略以及实现如何记录其在负载下的行为的指南,请参阅 性能和阻塞 规范。

并发和线程安全

有关 API 实现应提供的并发安全性以及如何记录这些安全性的指南,请参阅各个 API 规范。