
OpenTelemetry JavaScript SDK 不支持在运行时直接修改 TraceIdRatioBasedSampler 的采样比,但可通过自定义可变采样器(mutable sampler)实现动态调控,本文详解其设计与集成方法。
opentelemetry javascript sdk 不支持在运行时直接修改 `traceidratiobasedsampler` 的采样比,但可通过自定义可变采样器(mutable sampler)实现动态调控,本文详解其设计与集成方法。
在 OpenTelemetry JS 中,采样策略由 Sampler 接口定义,而官方提供的 TraceIdRatioBasedSampler 是不可变(immutable)的:其采样比(ratio)在实例化时固定,后续无法更改。TracerProvider(无论是 NodeTracerProvider 还是 BasicTracerProvider)在初始化后也不提供替换或更新 sampler 的 API —— 这意味着你无法通过 provider.updateSampler() 或类似方式热更新采样配置。
不过,OpenTelemetry 的设计高度可扩展:只要实现 Sampler 接口(即包含 shouldSample()、toString() 和 attributes 方法),即可注入自定义逻辑。要支持运行时动态调优,推荐构建一个状态可变的采样器类,例如:
import {
SamplingResult,
SamplingDecision,
TraceIdRatioBasedSampler,
Sampler,
Context,
SpanKind,
SpanAttributes
} from '@opentelemetry/sdk-trace-base';
export class MutableRatioSampler implements Sampler {
private _ratio: number = 1.0;
constructor(initialRatio: number = 1.0) {
this._ratio = Math.max(0, Math.min(1, initialRatio)); // clamp to [0, 1]
}
get ratio(): number {
return this._ratio;
}
set ratio(value: number) {
this._ratio = Math.max(0, Math.min(1, value));
}
shouldSample(
context: Context,
traceId: string,
spanName: string,
spanKind: SpanKind,
attributes: SpanAttributes,
links: readonly unknown[]
): SamplingResult {
// 复用 TraceIdRatioBasedSampler 的核心逻辑(基于 traceId 哈希)
const hash = this.hashTraceId(traceId);
const decision = hash >> 0;
}
}
使用该采样器时,在初始化 TracerProvider 时传入实例,并在业务逻辑中按需调整 ratio 属性:
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { MeterProvider } from '@opentelemetry/sdk-metrics';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
const sampler = new MutableRatioSampler(0.1); // 初始采样率 10%
const provider = new NodeTracerProvider({
sampler, // 注入可变采样器
});
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
// 后续可动态调整(例如响应配置中心变更、A/B 测试开关等)
setTimeout(() => {
console.log('Upgrading sampling ratio to 1.0 (100%)');
sampler.ratio = 1.0;
}, 5000);
// 注册 tracer provider
provider.register();
// 自动 instrumentations(可选)
registerInstrumentations({
instrumentations: [new HttpInstrumentation()],
tracerProvider: provider,
});
⚠️ 注意事项:
- 线程安全:MutableRatioSampler 的 ratio 属性为简单赋值,若在高并发场景下被多线程(如 Worker Threads)同时修改,需加锁或使用原子操作;Node.js 单线程环境下通常无需额外同步。
- 采样一致性:动态调整仅影响新创建的 Span,已开始的 Trace 不受影响,符合 OpenTelemetry 语义。
- 可观测性增强:建议在 shouldSample() 返回的 attributes 中注入当前采样率(如示例所示),便于在后端(如 Jaeger/Tempo)中关联分析采样行为。
- 替代方案限制:不推荐通过重建 TracerProvider 来“切换”采样器——这会导致已注册的 Tracer 实例失效、Span 上下文丢失,且破坏生命周期管理。
综上,虽然 OpenTelemetry JS 原生不支持运行时采样率热更新,但借助接口契约与组合模式,开发者可轻松构建符合自身运维需求的动态采样能力,兼顾灵活性与标准兼容性。











