OpenTelemetry 客户端的版本控制和稳定性

状态: 稳定

本文档定义了 OpenTelemetry 客户端提供的稳定性保证,以及满足这些保证的规则和流程。

在本文档中,“OpenTelemetry”和“语言实现”这两个术语都专门指代 OpenTelemetry 客户端。在本文档中,这些术语不包括规范或 Collector。

每种语言实现必须采用这些版本控制和稳定性要求,并生成一份特定语言的文档,详细说明如何满足这些要求。此文档必须放置在每个仓库的根目录,并命名为 VERSIONINGVERSIONING.md

设计目标

版本控制和稳定性程序旨在实现以下目标。

确保应用程序所有者及时更新 SDK 的最新版本。我们希望所有用户都能更新到最新版本的 OpenTelemetry SDK。我们不想创建任何形式的硬性支持中断,使用户滞留在旧版本上。升级到最新次版本 OpenTelemetry SDK 时,必须始终能够避免编译或运行时错误。

绝不创建依赖于不同 OpenTelemetry 版本的软件包之间的依赖冲突。避免破坏所有稳定的公共 API。向后兼容性是严格要求。仪表化 API 绝不能产生版本冲突。否则,OpenTelemetry API 将无法嵌入到广泛共享的库中,例如 Web 框架。针对旧版本 API 编写的代码必须与所有新版本 API 兼容。API 的传递依赖不能产生版本冲突。OpenTelemetry API 不能依赖于某个特定软件包,如果任何库或应用程序可能需要不同、不兼容的该软件包版本。导入 OpenTelemetry API 的库不应因 OpenTelemetry 某个依赖项的版本冲突而与其他库不兼容。理论上,API 可以被弃用并最终移除,但这是一个以年为单位衡量的过程,我们没有计划这样做。

允许在同一 OpenTelemetry 组件版本中存在多个级别的软件包稳定性。为维护者提供清晰的流程,以开发处于“开发中”状态的新信号,同时保留稳定的信号。同一版本中的不同软件包可能具有不同的稳定性级别。这意味着,一个希望今天发布稳定跟踪的实现必须确保正在开发的指标被排除在外,以免指标 API 的重大更改破坏跟踪 API 软件包的稳定性。

信号生命周期

每个信号的开发遵循一个生命周期:开发、稳定、已弃用、已移除。

下图展示了 API 组件生命周期的示例。

API Lifecycle

开发中

信号以OTEP 0232定义的开发中状态开始。在信号开发期间,可能会发生重大更改和性能问题。不应期望组件功能齐全。在某些情况下,开发中的信号可能会被丢弃并完全移除。不应与开发中的信号建立长期依赖关系。

OpenTelemetry 客户端的设计必须能够允许创建处于开发中的信号,而不会破坏现有信号的稳定性保证。

OpenTelemetry 客户端的设计不得破坏现有用户,当信号从开发中过渡到稳定状态时。这将惩罚发布候选版本的使用者,并阻碍采用。

表示稳定性的术语(如“开发中”)不得用作目录或导入名称的一部分。软件包版本号可以包含后缀,例如 -alpha、-beta、-rc 或 -development,以区分不同状态的软件包。

请注意,“开发中”状态以前在此存储库中称为“实验性”。任何使用“实验性”的地方都应视为与“开发中”相同。

稳定

一旦处于开发中的信号经过严格测试,它就可以过渡到稳定状态。现在可以与此信号建立长期依赖关系。

所有信号组件可以同时变为稳定,也可以逐个组件过渡到稳定。API 必须在其他组件稳定之前稳定。

一旦信号组件被标记为稳定,以下规则必须适用,直到该信号存在结束。

API 稳定性

除非主版本号增加,否则不得对 API 软件包进行向后不兼容的更改。所有现有的 API 调用都必须能够与同一主版本的所有未来次版本进行编译和运行。

发布二进制工件的语言应为 API 软件包提供ABI 兼容性

SDK 稳定性

SDK 软件包的公共部分必须保持向后兼容。公共功能分为两类:插件接口构造函数。插件接口是 SDK 提供的扩展点,旨在由最终用户实现以自定义 SDK 行为。插件接口的示例包括 SpanProcessor、Exporter 和 Sampler。构造函数的示例包括配置对象、环境变量和 SDK 构建器。

发布二进制工件的语言应为 SDK 软件包提供ABI 兼容性

扩展 API/SDK 抽象

如果特定语言允许以向后兼容的方式进行,则可以在不增加主版本号的情况下扩展现有的 API/SDK 调用。

要向现有 API/SDK 调用添加新参数,根据语言的不同,有几种可能的方法。

  • 向现有方法添加新的可选参数。对于将 ABI 稳定性作为我们保证一部分的语言来说,这可能不是正确的方法,因为它很可能破坏 ABI。

  • 添加一个方法重载,允许传递不同的参数集,包括新参数。这可能是允许方法重载的语言的首选方法。

同样,如果特定语言允许以向后兼容的方式(例如,通过提供默认实现)进行,则可以扩展现有的 SDK 插件接口以添加新方法,而不增加主版本号。向后兼容意味着,实现插件接口的最终用户代码必须能够与新版本 SDK 一起使用,而无需更改最终用户的代码。对于经常通过二进制工件共享代码的语言(例如 Java),向后兼容意味着实现插件接口的最终用户代码必须能够与新的次版本或补丁版本一起使用,而无需重新编译最终用户的代码。

如果对于某种语言来说,向接口添加方法这种向后兼容的添加方式不可行,那么该语言的维护者仍应使用向后兼容的解决方案来实现添加,而不增加主版本号。例如,一种可能的解决方案是添加一个新接口而不是扩展现有接口,并在每个地方都接受新接口以及旧接口。

此外,可以通过向现有稳定 API 添加新方法来扩展稳定信号的 API/SDK。

  • 添加处于开发中成熟度的 API/SDK 新方法是可能的,并且对于不使用新方法的用户来说不是破坏性更改。
  • 处于开发中的新方法应该需要选择加入,以便用户意识到使用开发中 API 的风险。应该明确记录新添加的方法处于开发中,并且可能发生重大更改。
  • 移除(或弃用)一个处于开发中成熟度但未达到稳定级别的现有方法,对于从未使用过该方法的用户的来说不是破坏性更改。

可能还有其他方法可以以非破坏性方式扩展现有的 API/SDK。语言维护者应选择适合其语言的惯用方式。

Contrib 稳定性

插件、仪表化和其他 contrib 软件包应保持最新并与 API、SDK 和语义约定 的最新版本兼容。如果 API、SDK 或语义约定 的发布包含与 contrib 软件包相关的更改,则应及时更新并发布该软件包。(有关仪表化稳定性的限制,请参阅遥测稳定性。)目标是确保用户能够更新到 OpenTelemetry 的最新版本,而不会被他们依赖的插件所阻碍。

contrib 软件包的公共部分(构造函数、配置、接口)应保持向后兼容。

发布二进制工件的语言应为 contrib 软件包提供ABI 兼容性

例外:当必需的下游依赖项破坏稳定性时,Contrib 软件包可能会破坏稳定性。例如,数据库集成可能会因必需的数据库客户端破坏稳定性而破坏稳定性。但是,强烈建议保持旧的 contrib 软件包的稳定性。新的、不兼容的集成版本应作为单独的 contrib 软件包发布,而不是破坏现有的 contrib 软件包。

语义约定稳定性

警告

对依赖于模式转换以实现遥测稳定性存在暂停。

语义约定定义了 OpenTelemetry 仪表化将提供的信号与消费该仪表化的分析工具(例如,仪表板、警报、查询等)之间的契约。

OpenTelemetry 仪表化产生的遥测数据的更改应避免破坏仪表板和警报等分析工具。为了实现这一点,同时允许遥测和语义约定 的演进,OpenTelemetry 依赖于遥测模式的概念。

语义约定将重大更改定义为那些会破坏针对其产生的遥测数据编写的工具的通用使用的更改。也就是说,工具(警报、仪表板等)交互的遥测部分在应用模式转换后,预计将对该工具保持稳定。这些还假设没有用户干预默认配置,例如 Samplers、Views 等。

语义约定定义了 OTLP 数据模型中的字段集

  • Resource
    • 属性键。(属性键值对的键部分)
    • 实体引用
      • 实体类型
      • 标识符(继承资源中的属性键保证)
  • InstrumentationScope
  • Trace
    • 有关Span的以下数据
      • Span 名称
      • Span 类型
      • 提供给 Span 的属性键
        • 由于采样原因,这些属性是否必须在 Span 开始时提供。
      • 在已知值列表中定义的提供给 Span 的属性值。
    • 有关Span Events的以下数据
      • Event 名称
      • 为 Event 提供的属性键
      • 在已知值列表中定义的为 Event 提供的属性值。
  • 指标
    • 关于指标(在构建Instrument时传递)的以下部分
      • 指标名称(默认为 Instrument 名称)。
      • 指标数据类型(Gauge、Sum、Histogram、ExponentialHistogram)
        • 对于 CounterUpDownCounter Instruments,可以在异步和同步 Instruments 之间进行更改,因为这会保留指标类型。
      • 指标的单位(默认为 Instrument 单位)。
    • 任何 *DataPoint 上的属性键。
      • 这些在记录测量值时在 API 中提供,包括同步和异步 Instruments。
      • 这些存在于 NumberDataPointHistogramDataPointExponentialHistogramDataPointSummaryDataPoint 上。
    • 任何 *DataPoint 上的属性值,这些值在已知值列表中定义。
  • 日志记录
    • 在 LogRecord 上提供的属性键
    • 在 LogRecord 上提供的属性值,这些值在已知值列表中定义。
    • Event 名称

以上未列出的内容不期望通过语义约定保持稳定,并且允许(或期望)更改。以下是一些示例。

  • 属性的值
    • 现有已知值列表中的值是一个例外。但是,可以向此类列表添加新值。消费者应该期望未知值。
  • 附加到 Span 的链接
  • 指标记录的测量值类型(浮点数或整数)不受强制执行,允许更改。
  • 指标 Instrument 的描述。
  • Instrument 正在记录的值。

受稳定性保证覆盖的遥测字段列表可以扩展。

此规范中的语义约定更改是允许的,前提是这些更改可以通过模式文件进行描述。当前可以描述并允许的更改如下:

  • 重命名 Span、Metric、Log 和 Resource 属性。
  • 重命名指标。
  • 重命名 Span Events。

所有此类更改必须在 OpenTelemetry 模式文件格式中进行描述,并在此存储库中发布。有关详细信息,请参阅 OpenTelemetry 模式的发布方式

有关仪表化如何使用模式来更改其产生的仪表化的详细信息,请参阅遥测稳定性文档。

例外:某些资源属性嵌入在规范的各种位置,例如,service.* 属性是 SDK 所必需的,并且具有相应的常规 SDK 配置中定义的环境变量。这些资源属性永远不能更改。它们被视为本规范的硬编码部分。

除了上面描述的三种类型的更改外,还有一些类型始终允许。这些更改不需要(也不会)由模式文件描述。以下是此类更改的列表。

  • 为现有的 Resource、Span、Span Event 或 Log Record 添加新属性。
  • 向现有指标添加新属性,但这些属性不会“破坏”现有的时间序列,从而导致警报阈值中断/需要更改。
  • 为新的资源、Span、Span Event、Metric 或 Log Record 类型添加语义约定。

目前禁止对语义约定进行任何其他更改。未来版本的此规范可能会引入其他类型的更改。这仅在 OpenTelemetry 引入能够描述此类更改的新模式文件格式时才允许。

遥测稳定性

有关仪表化产生的遥测稳定性的信息,请参阅遥测稳定性文档。

已弃用

信号最终可能会被替换。发生这种情况时,它们会被标记为已弃用。

信号在被标记为已弃用之前,其替换必须是稳定的。已弃用的代码必须遵守与稳定代码相同的支持保证。

已移除

通过从发布中移除信号来结束支持。发生这种情况时,发布必须进行主版本号升级。

关于替换信号的说明

请注意,我们目前没有计划创建 OpenTelemetry v1.0 之后的某个主版本。

为清晰起见,仍然可以在不实际迁移到 v2.0 并破坏支持的情况下,创建现有信号的向后不兼容的新版本。

例如,假设我们开发了一个新的、更好的跟踪 API - 称之为 AwesomeTrace。我们永远不会将当前的跟踪 API 变异为 AwesomeTrace。相反,AwesomeTrace 将作为一个全新的信号添加,它与当前的跟踪信号共存并互操作。这将使添加 AwesomeTrace 成为次版本号升级,而不是 v2.0。v2.0 将标志着当前跟踪支持的结束,而不是 AwesomeTrace 的添加。而且,如果我们能避免的话,我们永远不想结束支持。

这实际上并非理论性示例。OpenTelemetry 已经支持两个跟踪 API:OpenTelemetry 和 OpenTracing。我们发明了一个新的跟踪 API,但继续支持旧的 API。

版本号

OpenTelemetry 客户端必须遵循语义版本 2.0.0,并附有以下说明。

OpenTelemetry 客户端有四个组件:API、SDK、语义约定和 Contrib。

就版本控制而言,组件内的所有代码都必须视为单个软件包的一部分,并使用相同的版本号进行版本控制,但 Contrib 除外,它可能是一个单独版本控制的软件包集合。

  • 所有稳定的 API 软件包必须跨所有信号一起进行版本控制。稳定的信号不得有单独的版本号。有一个版本号适用于包含在该版本号标记的 API 版本中的所有信号。
  • 所有信号的 SDK 软件包必须跨所有信号一起进行版本控制。信号不得有单独的版本号。有一个版本号适用于包含在该版本号标记的 SDK 版本中的所有信号。
  • 语义约定是一个具有单个版本号的单一软件包。
  • 每个 contrib 软件包可以有自己的版本号。
  • API、SDK、语义约定和 Contrib 组件具有独立版本号。例如,opentelemetry-python-api 的最新版本可能是 v1.2.3,而 opentelemetry-python-sdk 的最新版本是 v2.3.1。
  • 不同的语言实现具有独立版本号。例如,opentelemetry-python-api 为 v1.2.8,而 opentelemetry-java-api 为 v1.3.2 是可以的。
  • 语言实现的版本号与其实现的规范的版本号是独立的。例如,v1.8.2 的 opentelemetry-python-api 实现 v1.1.1 规范是没问题的。

例外:在某些语言中,包管理器可能对不稳定的包具有高于 0.X 的版本号反应不佳。在这种情况下,处于开发中的信号可以独立于稳定信号进行版本控制,以保留 0.X 版本号。当信号稳定时,版本必须升级以匹配发布中的其他稳定信号。

主版本号升级

当稳定的接口出现重大更改或已弃用的信号被移除时,必须进行主版本号升级。主版本号升级不应出现在不会导致某种形式的支持下降的更改上。

次版本号升级

OpenTelemetry 客户端的大多数更改都会导致次版本号升级。

  • 向任何组件添加新的向后兼容功能。
  • 对内部 SDK 组件进行破坏性更改。
  • 对开发中的信号进行破坏性更改。
  • 添加处于开发中的新信号。
  • 处于开发中的信号变为稳定。
  • 稳定的信号被弃用。

补丁版本号升级

补丁版本不会进行任何需要重新编译或可能破坏应用程序代码的更改。以下是补丁修复的示例。

  • 未要求次版本号升级的 Bug 修复。
  • 安全修复。
  • 文档。

目前,OpenTelemetry 项目不打算向先前次版本的 SDK 反向移植 Bug 和安全修复。安全和 Bug 修复只能应用于最新的次版本。我们致力于使用户能够轻松更新到最新版本的 OpenTelemetry SDK。

语言版本支持

每种语言实现都应定义移除支持的语言/运行时版本如何影响其版本控制。通常,它应该遵循给定生态系统中的约定。

长期支持

long term support

API 支持

API 的主版本号自下一个主 API 版本发布之日起,必须至少支持三年。API 支持定义如下。

  • 必须维护 API 稳定性,如上定义。

  • 在 LTS 期间,将继续维护支持最新次版本最后一个主版本 API 的 SDK 版本。必须将 Bug 和安全修复反向移植。不建议进行其他功能开发。

  • API 版本化时可用的 Contrib 软件包必须在 LTS 期间继续维护。将反向移植 Bug 和安全修复。不建议进行其他功能开发。

SDK 支持

SDK 稳定性,如上定义,将在下一个主 SDK 版本发布后至少维护一年

Contrib 支持

Contrib 稳定性,如上定义,将在下一个主 Contrib 软件包版本发布后至少维护一年

OpenTelemetry GA

“OpenTelemetry GA”一词指的是 OpenTracing 和 OpenCensus 将完全弃用的时间点。宣布 GA 的最低要求如下。

  • 至少必须在四种语言中发布稳定版本的跟踪和指标。
  • 必须为这些语言实现 CI/CD、性能和集成测试。