为何针对特定Span Name的比例采样会影响所有Trace?
问题根源:OpenTelemetry采样器是Trace级别的决策,而非单个Span
你误解了OTel采样器的核心逻辑——Sampler的决策是针对整个Trace的,不是单个Span。一旦Trace的根Span被赋予采样决策,整个Trace里的所有子Span都会继承这个决策,不会单独为每个Span重新判断。
你的代码存在以下问题:
- 当
some.specific.span是Trace的根Span时,99%概率返回NOT_RECORD,这会导致整个Trace被完全丢弃,包括里面的其他Span; - 当这个Span不是根Span时,根Span的决策是
RECORD,那这个Span也会被记录,完全达不到你想要的“只采样1%该Span”的效果; - 另外,你返回的
RECORD决策,部分导出器可能不会发送这类Span(RECORD仅表示本地记录,RECORD_AND_SAMPLED才会标记为需要导出的采样Span)。
正确的实现方式:用Span Processor做单Span过滤采样
因为你的需求是针对单个特定Span做概率采样,而非整个Trace,所以应该用Span Processor在Span导出前做过滤,而非依赖Sampler。
修改后的代码示例:
// 自定义Span Processor,针对特定Span做概率采样 class ProbabilitySpanFilterProcessor implements SpanProcessor { private readonly targetSpanName = 'some.specific.span'; private readonly sampleProb = 0.01; private readonly delegate: SpanProcessor; constructor(delegate: SpanProcessor) { this.delegate = delegate; } onStart(span: Span, parentContext: Context): void { this.delegate.onStart(span, parentContext); } onEnd(span: Span): void { // 只针对目标Span做概率过滤 if (span.name === this.targetSpanName) { if (Math.random() >= this.sampleProb) { // 不满足采样概率,直接跳过导出 return; } // 标记采样率属性 span.setAttribute('SampleRate', 1 / this.sampleProb); } // 其他Span正常导出 this.delegate.onEnd(span); } forceFlush(): Promise<void> { return this.delegate.forceFlush(); } shutdown(): Promise<void> { return this.delegate.shutdown(); } } export function setupTelemetry() { const provider = new BasicTracerProvider(); // 用自定义处理器包装BatchSpanProcessor const batchProcessor = new BatchSpanProcessor(new OTLPTraceExporter()); provider.addSpanProcessor(new ProbabilitySpanFilterProcessor(batchProcessor)); provider.register(); }
若需基于Trace包含目标Span的采样(不推荐)
如果你的需求是“当Trace包含some.specific.span时,整个Trace以1%概率采样,否则全量采样”,这种场景需要在根Span决策时预判后续子Span,通常不太现实,因此更推荐上面的Span Processor方案。
内容的提问来源于stack exchange,提问作者beta
相关产品推荐
相关产品推荐

