使用Spring Sleuth实现Span ID条件传播 仅上报失败事务链路到Zipkin
Spring Sleuth+Zipkin实现条件化上报失败链路的方案
完全可以实现你需要的能力,核心思路是替换默认的全量/采样率上报逻辑,结合Saga分布式事务的失败标记做过滤,仅上报符合条件的链路数据,两种主流实现方案如下:
方案1:自定义SpanReporter实现上报过滤(适配Spring Sleuth 2.x、3.x全版本)
- 首先在Saga事务的全局失败回调逻辑里,给当前链路的根Span打自定义标记,比如添加tag
transaction.saga.failed = true,同时可以把异常类型、错误信息等也存入tag方便后续排查 - 重写默认的
ZipkinSpanReporterBean,替换Spring Sleuth自动注入的默认实现,仅当Span包含上述失败标记时才执行上报逻辑,其余Span直接丢弃
示例代码:
@Component @Primary public class ConditionZipkinSpanReporter extends ZipkinSpanReporter { public ConditionZipkinSpanReporter(Sender sender, BytesEncoder<Span> encoder) { super(sender, encoder); } @Override public void report(Span span) { // 仅上报Saga事务执行失败的链路 if (Boolean.parseBoolean(span.tags().getOrDefault("transaction.saga.failed", "false"))) { super.report(span); } } }
注意需要在启动类排除Sleuth自动装配的默认Reporter,避免冲突:
@SpringBootApplication(exclude = {ZipkinAutoConfiguration.class}),再自行注册Sender、Encoder等依赖Bean即可。
方案2:基于Brave采样策略实现(更轻量,适配Spring Sleuth 3.x+版本)
Spring Sleuth 3.x之后底层依赖Brave框架实现链路能力,你可以通过自定义采样规则+主动触发上报的方式实现需求,内存消耗更低:
- 自定义全局采样器,默认所有链路都标记为暂不上报
- Saga事务执行失败时,主动给当前链路打标记并触发全链路上报
示例代码:
// 注册自定义采样器,默认不采样普通链路 @Bean public Sampler customSampler() { return span -> false; } // Saga事务失败回调逻辑 @Autowired private Tracer tracer; public void handleSagaFailed(Throwable ex) { Span currentSpan = tracer.currentSpan(); if (currentSpan != null) { // 打失败标记 currentSpan.tag("transaction.saga.failed", "true") .tag("error", ex.getMessage()); // 主动上报当前链路的所有Span currentSpan.flush(); } }
大流量场景注意事项
- 确保Saga事务的失败标记能正确透传到链路根Span,避免跨服务调用时标记丢失导致漏报
- 可以配合本地队列做失败链路的批量聚合上报,避免短时间大量事务失败时压垮Zipkin服务端
- 如果使用Spring Cloud 2020+版本,Sleuth已迁移为Micrometer Tracing,对应调整为自定义
ObservationHandler做过滤即可,适配逻辑和上述方案一致
内容的提问来源于stack exchange,提问作者DanielSP
相关产品推荐
相关产品推荐

