You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OTEL NodeJS SDK客户端采样:如何留存全量异常追踪数据

解决方案

针对你的需求,这里提供两种客户端层面的实现方案,无需启用全量尾部采样,就能确保所有含异常的追踪数据被留存到APM工具:

方案一:自定义感知异常的采样器(推荐)

这个方案会在Span创建阶段结合比例采样和异常动态修正,确保整个异常追踪链路被完整采样:

const { ParentBasedSampler, TraceIdRatioBasedSampler, SamplingDecision, SpanStatusCode, TraceFlags } = require('@opentelemetry/sdk-trace-base');

class ErrorPrioritySampler {
  constructor(sampleRatio) {
    this.ratioSampler = new TraceIdRatioBasedSampler(sampleRatio);
  }

  shouldSample(context) {
    // 继承父Span的采样决策
    const parentSpanContext = context.spanContext();
    if (parentSpanContext) {
      return {
        decision: (parentSpanContext.traceFlags & TraceFlags.SAMPLED) 
          ? SamplingDecision.RECORD_AND_SAMPLED 
          : SamplingDecision.NOT_RECORD
      };
    }

    // 根Span先按比例采样,可提前标记高风险请求(比如POST接口)强制采样
    const request = context.getValue('http.request'); // 基于HTTP instrumentation的示例
    if (request?.method === 'POST') {
      return { decision: SamplingDecision.RECORD_AND_SAMPLED };
    }

    return this.ratioSampler.shouldSample(context);
  }

  toString() {
    return `ErrorPrioritySampler{ratio=${this.ratioSampler.toString()}}`;
  }
}

// 替换原有采样配置
sampler: new ParentBasedSampler({
  root: new ErrorPrioritySampler(options.sampleRatio),
}),

// 添加Span处理器,异常发生后强制修正采样决策
const errorCorrectionProcessor = new SimpleSpanProcessor({
  onStart() {},
  onEnd(span) {
    if (span.status.code === SpanStatusCode.ERROR && !(span.spanContext().traceFlags & TraceFlags.SAMPLED)) {
      // 强制标记该Span及链路为采样状态
      span.updateTraceFlags(TraceFlags.SAMPLED);
      // 立即导出
      yourExporter.export([span], () => {});
    }
  }
});

// 注册处理器到TracerProvider
tracerProvider.addSpanProcessor(errorCorrectionProcessor);

方案二:直接强制导出异常Span

如果不想修改原有采样逻辑,可通过Span处理器单独捕获异常Span并导出,实现更轻量:

const { SimpleSpanProcessor, SpanStatusCode, TraceFlags } = require('@opentelemetry/sdk-trace-base');

const errorExportProcessor = new SimpleSpanProcessor({
  onStart() {},
  onEnd(span) {
    if (span.status.code === SpanStatusCode.ERROR) {
      // 确保Span被标记为采样
      if (!(span.spanContext().traceFlags & TraceFlags.SAMPLED)) {
        span.updateTraceFlags(TraceFlags.SAMPLED);
      }
      // 直接导出到APM工具
      yourExporter.export([span], (result) => {
        if (result.code !== 'SUCCESS') {
          console.error('异常Span导出失败:', result.error);
        }
      });
    }
  }
});

tracerProvider.addSpanProcessor(errorExportProcessor);

关键注意事项

  • 方案一能保证完整追踪链路被采样,适合需要排查端到端问题的场景;方案二更轻量,但可能只捕获单个异常Span
  • 必须确保代码中正确标记异常:使用span.setStatus({ code: SpanStatusCode.ERROR, message: error.stack || error.message })
  • 两种方案都不会显著增加吞吐量,因为异常请求占比通常远低于常规请求

内容的提问来源于stack exchange,提问作者Ján Bušfy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:38:21