如何将Java Spanner的OpenTelemetry链路关联到Micrometer/Brave父链路
跨Brave与OpenTelemetry的追踪上下文传播方案
核心思路:自动同步上下文
你可以通过自定义Spring Bean或利用官方桥接库,实现Brave与OpenTelemetry上下文的自动同步,无需在每个调用点手动复制traceId/spanId,就能让Spanner的Otel链路关联到Brave的父链路。
方案一:自定义切面实现上下文同步
创建Spring切面,在目标方法执行前将Brave当前Span的信息同步到OpenTelemetry上下文,覆盖Spanner客户端调用的上下文环境:
import brave.Tracer; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class BraveOtelContextSyncAspect { private final Tracer braveTracer; public BraveOtelContextSyncAspect(Tracer braveTracer) { this.braveTracer = braveTracer; } // 匹配所有Service层方法,可根据实际调整切点表达式 @Around("execution(* com.yourpackage..*(..)) && within(@org.springframework.stereotype.Service *)") public Object syncContext(ProceedingJoinPoint joinPoint) throws Throwable { brave.Span braveSpan = braveTracer.currentSpan(); if (braveSpan == null) { return joinPoint.proceed(); } // 提取Brave Span核心信息 String traceId = braveSpan.context().traceIdString(); String spanId = braveSpan.context().spanIdString(); boolean sampled = braveSpan.context().sampled() != null && braveSpan.context().sampled(); // 构建OpenTelemetry Span上下文 SpanContext otelSpanContext = SpanContext.create( traceId, spanId, sampled ? TraceFlags.getSampled() : TraceFlags.getDefault(), TraceState.getDefault() ); // 将Otel上下文设为当前上下文并执行方法 Context otelContext = Context.current().with(Span.wrap(otelSpanContext)); try (Scope ignored = otelContext.makeCurrent()) { return joinPoint.proceed(); } } }
这个切面会自动在Service方法执行前完成上下文同步,Spanner客户端调用时就能获取到正确的父链路信息。
方案二:利用OpenTelemetry Brave桥接库
OpenTelemetry官方提供了Brave桥接库,可直接实现两者上下文的双向同步,配置更简洁:
- 添加桥接依赖(根据你的Spring Boot版本调整版本号):
<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-bridge-brave</artifactId> <version>1.32.0</version> </dependency>
- 配置桥接Bean:
import brave.Tracer; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.brave.ShadowBrave; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BraveOtelBridgeConfig { @Bean public ShadowBrave shadowBrave(Tracer braveTracer, OpenTelemetry openTelemetry) { return ShadowBrave.builder(braveTracer) .setOpenTelemetry(openTelemetry) .build(); } }
桥接库会自动同步Brave与OpenTelemetry的Span上下文,Spanner的Otel链路会自动关联到Brave的父Span,无需手动复制信息。
注意事项
- 确保Brave的
TracerBean已被Spring正确注入(Spring Boot集成Brave时会自动配置)。 - 若存在异步方法调用,需额外配置Spring异步任务执行器,确保上下文能传递到异步线程中。
- 保持Brave与OpenTelemetry的采样状态一致,避免采样标记不一致导致链路断裂。
内容的提问来源于stack exchange,提问作者kpater87
相关产品推荐
相关产品推荐

