OpenTelemetry 项目自从诞生以来,OpenTracing 的向后兼容性就是优先事项之一。
为了简化迁移过程,OpenTelemetry 支持在同一代码库中同时使用 OpenTelemetry 和
OpenTracing API。这样就可以使用 OpenTelemetry SDK 记录 OpenTracing 的插桩数据。
为实现这一点,每个 OpenTelemetry SDK 都提供了一个 OpenTracing Shim,
它充当 OpenTracing API 和 OpenTelemetry SDK 之间的桥梁。请注意,OpenTracing Shim 默认是禁用的。
语言版本支持 {#language-version-support}
在使用 OpenTracing Shim 之前,请检查你的编程语言和运行时组件版本,
并在必要时进行更新。下表列出了 OpenTracing 和 OpenTelemetry API 的最低语言版本要求:
| 语言 | OpenTracing API | OpenTelemetry API |
|---|---|---|
| Go | 1.13 | 1.16 |
| Java | 7 | 8 |
| Python | 2.7 | 3.6 |
| JavaScript | 6 | 8.5 |
| .NET | 1.3 | 1.4 |
| C++ | 11 | 11 |
请注意,OpenTelemetry API 和 SDK 通常比 OpenTracing 要求更高的语言版本。
迁移概述 {#migration-overview}
目前许多代码库都使用 OpenTracing 进行了插桩。这些代码库使用 OpenTracing API
来对应用代码进行插桩,并/或安装 OpenTracing 插件以对其使用的库和框架进行插桩。
迁移到 OpenTelemetry 的通用方法总结如下:
- 安装 OpenTelemetry SDK,并移除当前的 OpenTracing 实现,例如 Jaeger 客户端。
- 安装 OpenTelemetry 的插桩库,并移除对应的 OpenTracing 版本。
- 更新插桩盘、告警等以消费新的 OpenTelemetry 数据。
- 编写新应用代码时,全部使用 OpenTelemetry API 进行插桩。
- 逐步用 OpenTelemetry API 重新对应用进行插桩。并不强制移除已有的
OpenTracing API 调用,它们仍然可以正常工作。
如上所述,迁移一个大型应用可能需要显著的工作量,我们建议 OpenTracing
用户逐步迁移他们的应用代码。这样可以减轻迁移负担,避免可观测性中断。
以下步骤展示了一种谨慎的、渐进式的 OpenTelemetry 迁移路径。
第 1 步:安装 OpenTelemetry SDK {#step-1-install-the-opentelemetry-sdk}
在更改任何插桩之前,请确保可以切换到 OpenTelemetry SDK,而不会导致当前应用发送的遥测数据中断。
单独完成这一步(不引入任何新插桩)是推荐做法,因为这样更容易判断是否出现了插桩中断。
- 用 OpenTelemetry SDK 替换你当前使用的 OpenTracing Tracer 实现。例如,
如果你在使用 Jaeger,请移除 Jaeger 客户端并安装对应的 OpenTelemetry 客户端。 - 安装 OpenTracing Shim。该 shim 允许 OpenTelemetry SDK 消费 OpenTracing 的插桩数据。
- 配置 OpenTelemetry SDK,以使用与之前 OpenTracing 客户端相同的协议和格式导出数据。
例如,如果你使用的是以 Zipkin 格式导出数据的 OpenTracing 客户端,请将 OpenTelemetry 客户端配置为使用相同格式。 - 或者,将 OpenTelemetry SDK 配置为发出 OTLP 数据,并将其发送至 Collector,在 Collector 中管理以多种格式导出数据。
安装好 OpenTelemetry SDK 后,请确认你可以部署应用并继续接收基于 OpenTracing
的遥测数据。换句话说,确认你的插桩盘、告警和其他基于追踪的分析工具仍能正常工作。
第 2 步:逐步替换插桩 {#step-2-progressively-replace-instrumentation}
安装 OpenTelemetry SDK 后,所有新插桩现在都可以使用 OpenTelemetry API 编写。
除少数情况外,OpenTelemetry 与 OpenTracing 的插桩可以无缝协同工作
(见下文的兼容性限制)。
那现有的插桩怎么办?并不强制将现有应用代码迁移至 OpenTelemetry。不过,我们建议将使用的
OpenTracing 插桩库(用于插桩 Web 框架、HTTP 客户端、数据库客户端等)迁移至对应的
OpenTelemetry 库。这将获得更好的支持,因为许多 OpenTracing 库将停止维护,可能不再更新。
需要注意的是,切换至 OpenTelemetry 插桩库后,产出的数据将发生变化。OpenTelemetry
对软件插桩有更好的模型(即所谓的“语义约定”)。在许多情况下,OpenTelemetry 生成更好、更全面的追踪数据。
然而,“更好”也意味着“不同”。这就意味着基于旧 OpenTracing 插桩库构建的插桩盘、告警等,可能在替换后不再起作用。
对于现有的插桩,建议按照以下步骤操作:
- 将某一部分 OpenTracing 插桩替换为其 OpenTelemetry 等价物。
- 观察这对应用产出的遥测数据带来了哪些变化。
- 创建新的插桩盘、告警等以消费这些新数据。务必在将新的 OpenTelemetry
库部署到生产环境之前设置好这些插桩盘。 - 可选:在 Collector 中添加处理规则,将新的遥测数据转换为旧格式。
Collector 可配置为同时发出两种格式的遥测数据,形成数据重叠。
这可以让新的插桩盘填充数据,同时你仍可使用旧的插桩盘。
兼容性限制 {#limits-on-compatibility}
本节将描述除前述语言版本限制之外的兼容性限制。
语义约定 {#semantic-conventions}
如前所述,OpenTelemetry 提供了改进的软件插桩模型。这意味着,OpenTracing 设置的
“tags” 可能与 OpenTelemetry 设置的 “attributes” 不同。换句话说,替换现有插桩时,
OpenTelemetry 产生的数据可能与 OpenTracing 不一致。
再次强调:更改插桩时,请同步更新所有依赖旧数据的插桩盘、告警等内容。
Baggage
在 OpenTracing 中,Baggage 是与 Span 关联的 SpanContext 对象一起携带的。而在
OpenTelemetry 中,上下文和传播是更底层的概念:Span、Baggage、指标工具等都是通过上下文对象传递的。
由于这种设计上的变化,通过 OpenTracing API 设置的 Baggage 无法被 OpenTelemetry
的 Propagator 访问。因此,在使用 Baggage 时不建议混用 OpenTelemetry 和 OpenTracing API。
具体来说,当使用 OpenTracing API 设置 Baggage 时:
- 无法通过 OpenTelemetry API 访问;
- 无法通过 OpenTelemetry Propagator 进行注入。
如果你在使用 Baggage,建议所有与 Baggage 相关的 API 调用同时切换到 OpenTelemetry。
在部署这些变更前,请确认所有关键的 Baggage 项仍能正确传递。
JavaScript 中的上下文管理 {#context-management-in-javascript}
在 JavaScript 中,OpenTelemetry API 使用了通用的上下文管理器,比如 Node.js 的async_hooks 和浏览器中的 Zones.js。与需要手动将 Span 参数传递给每个方法相比,
这些上下文管理器使追踪更易于实现,侵入性更低。
而 OpenTracing API 出现得更早,并未广泛使用这些上下文管理器。OpenTracing
代码通过参数传递当前活跃 Span,这与 OpenTelemetry 中通过上下文存储 Span
的方式存在冲突。在同一个链路中混用这两种方式,可能会导致链路中断或 Span 不匹配,因此不推荐这样做。
我们建议你按完整的代码路径将 OpenTracing 迁移至 OpenTelemetry,避免在同一链路中混用两套 API。
规范与实现细节 {#specification-and-implementation-details}
关于各语言中 OpenTracing Shim 的工作原理,请参阅对应的语言文档。关于
OpenTracing Shim 的设计细节,请参阅 OpenTracing 兼容性文档。