编程 OTel JS SDK 2.x 迁移笔记:真正留神的是 NodeTracerProvider 那处"静默"变化

2026-09-06 00:04:27

OTel JS SDK 2.x 迁移笔记:真正留神的是 NodeTracerProvider 那处“静默”变化

@opentelemetry/opentelemetry-js 的 stable 包在 2025 年 2 月发布了 2.0.0,experimental 包随之进到 0.200.0。官方对“JS SDK 2.x”的界定是:仅指 opentelemetry-js 仓库内的 stable 包(1.x→2.0.0)与实验包(0.x→0.200.0);@opentelemetry/apisemantic-conventions 不在此列,它们的版本策略照旧。

先看升级门槛

  • Node:最低 ^18.19.0 || >=20.6.0。Node 14/16 被丢弃,原因是要覆盖 --importmodule.register() 两种加载路径。
  • TypeScript:最低 5.0.4。后续 minor 版本会直接丢弃超过 2 年旧的 TS。
  • 编译 target:ES2017 → ES2022。浏览器侧会丢掉不支持 ES2022 的老版本;Node 侧本身已隐含 ES2022。
  • @opentelemetry/api 仍支持 Node v8,semantic-conventions 仍支持 Node v14。

Resource:类变成了函数

@opentelemetry/resources 不再导出 Resource 类,构造函数和静态方法全部改为独立函数:

// 1.x
import { Resource } from '@opentelemetry/resources';
const res = new Resource(attributes);
const def = Resource.default();
const empty = Resource.empty();

// 2.x
import { resourceFromAttributes, defaultResource, emptyResource } from '@opentelemetry/resources';
const res = resourceFromAttributes(attributes);
const def = defaultResource();
const empty = emptyResource();

sync/async detector 合并,不再区分 *Sync 后缀:

1.x2.x
envDetectorSyncenvDetector
hostDetectorSynchostDetector
osDetectorSyncosDetector
processDetectorSyncprocessDetector
serviceInstanceIdDetectorSyncserviceInstanceIdDetector
detectResourcesSync()detectResources()

browserDetector / browserDetectorSync 从本包导出中删除,改用独立包 @opentelemetry/opentelemetry-browser-detector

类型层的变化:ResourceAttributes@opentelemetry/apiAttributes 取代,@opentelemetry/api 的 peerDependency 从 1.0.0 提到 1.3.0。

浏览器 window.OTEL_* 配置被移除

浏览器端不再从 window.OTEL_* 读配置,bootstrap 逻辑需要改为代码显式配置。

core.getEnv() 拆了

@opentelemetry/coregetEnv() 不再一次性 load+parse 全部 OTEL_* 变量,改成按需读取单个变量的函数族:

  • getStringFromEnv()
  • getNumberFromEnv()
  • getBooleanFromEnv()
  • getStringListFromEnv()
  • diagLogLevelFromString()

默认值语义有变化:原 getEnv() 返回带默认值,getEnvWithoutDefaults() 不带默认值;现在调用侧自己用 ?? defaultValue 兜底。

// 1.x
const { OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT } = getEnv();

// 2.x
const limit = getNumberFromEnv('OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? Infinity;

删除项:

  • DEFAULT_ENVIRONMENT / ENVIRONMENT / RAW_ENVIRONMENT / parseEnvironment
  • 各种 DEFAULT_*_LIMIT 常量:属性值长度默认改为字面量 Infinity,count 类默认改为 128

另外:IdGenerator / RandomIdGenerator 删除;AlwaysOnSampler / AlwaysOffSampler / ParentBasedSampler / TraceIdRatioSampler 移到 @opentelemetry/sdk-trace-baseisWrapped / ShimWrapped 移到 instrumentation 包。

这个改动的动机是:原来每新增一个 OTEL_* 变量都要更新 core 发版,按需单读把耦合拆掉了。

NodeTracerProvider 不再消费 env 创建 exporter/propagator

影响最大的是第 4 节,迁移时容易“不报错但数据不出门”。

BasicTracerProviderNodeTracerProvider 不再读 OTEL_TRACES_EXPORTER 创建 exporter,也不再读 OTEL_PROPAGATORS 创建 propagator。这套逻辑挪到了 @opentelemetry/sdk-nodeNodeSDK

后果很直接:裸用 NodeTracerProvider 且依赖环境变量配 exporter 的代码,升级后不会有任何报错,但 trace 不会被导出。

// 1.x:环境变量驱动的裸 provider
const provider = new NodeTracerProvider();
provider.register();

// 2.x:要交给 NodeSDK,或代码显式注入
import { NodeSDK } from '@opentelemetry/sdk-node';
const sdk = new NodeSDK();
sdk.start();

BasicTracerProvider 相关删除:

  • addSpanProcessor() 删除,改为构造参数传入
  • getActiveSpanProcessor()resource 改为私有
  • register() 删除,改用 NodeTracerProvider#register() 或手动 trace.setGlobalTracerProvider()
  • EXPORTER_FACTORY / PROPAGATOR_FACTORY / ForceFlushState 删除
  • Tracer class 误导出删除,改用 provider.getTracer(),类型层面用 @opentelemetry/apiTracer

Span:parentSpanId 改名,sampler 回退策略调整

Span / ReadableSpanparentSpanId 改为 parentSpanContext,对齐 spec:

// 1.x
span.parentSpanId

// 2.x
span.parentSpanContext?.spanId

ReadableSpan.instrumentationLibrary 改为 instrumentationScopenew Span() 不再可用,统一走 tracer.startSpan()

OTEL_TRACES_SAMPLER 配置非法值时的回退行为有变:之前回退 AlwaysOnSampler,现在回退 ParentBasedAlwaysOnSampler

sdk-metrics:View class 移除

@opentelemetry/sdk-metricsView class 和各个 *Aggregation class 被移除,改为传 ViewOptions 对象 + AggregationType 枚举。

attributeKeys 改为 attributesProcessors,搭配 createAllowListAttributesProcessor / createDenyListAttributesProcessor

// 1.x
new View({ meterName, attributeKeys: ['http.*'] })

// 2.x
// ViewOptions + AggregationType 枚举/attributesProcessors

迁移优先级判断

如果你的接入层基本只依赖 NodeSDK,主要工作量就是升 Node/TS 最低版本;Resource / getEnv() / parentSpanId / Metrics class 这些改动都是编译期可抓的,按编译错误逐个改即可。

真正需要留神的是第 4 节:NodeSDK 之外的裸 NodeTracerProvider 不再读 env,属于“不报错但数据不出门”的静默变化。手动拼过 Provider、自己读过 env、或者持久化过 span 对象的代码,要按上面几节逐一排查。

参考资料

  • 官方迁移文档:https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/upgrade-to-2.x.md
  • stable CHANGELOG:https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md
  • experimental CHANGELOG:https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/CHANGELOG.md

按 OTel 版本策略,1.x stable 在 2.0.0 发布后仍支持一年,不急于一次切完的可以先排期。

推荐文章

程序员茄子在线接单