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

如何将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桥接库,可直接实现两者上下文的双向同步,配置更简洁:

  1. 添加桥接依赖(根据你的Spring Boot版本调整版本号):
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-bridge-brave</artifactId>
    <version>1.32.0</version>
</dependency>
  1. 配置桥接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的Tracer Bean已被Spring正确注入(Spring Boot集成Brave时会自动配置)。
  • 若存在异步方法调用,需额外配置Spring异步任务执行器,确保上下文能传递到异步线程中。
  • 保持Brave与OpenTelemetry的采样状态一致,避免采样标记不一致导致链路断裂。

内容的提问来源于stack exchange,提问作者kpater87

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:46:30