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

如何通过Reactor Context将OpenTelemetry ParentId注入MDC?

解决方案

一、关于配置项的说明

OpenTelemetry Java Agent从1.28.0版本开始,提供了otel.instrumentation.log-injection.baggage.keys配置项,用于指定需要注入到MDC的Baggage字段(多字段用逗号分隔)。不存在otel.instrumentation.log-injection.baggage.enabled这类开关,只要配置了具体的键,对应的Baggage字段就会自动被注入到MDC中。

示例配置:

# 将parentId及其他自定义Baggage字段注入MDC
otel.instrumentation.log-injection.baggage.keys=parentId,user-id

二、修正你的WebFilter实现

你当前的代码存在两个核心问题:

  1. 错误地从X-B3-SpanId头获取parentId,正确的parentId来源是X-B3-ParentSpanId
  2. OTel上下文的绑定逻辑可以简化,Spring WebFlux环境下OTel的Reactor instrumentation会自动将上下文关联到Reactor Context

修正后的代码:

import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.context.Context;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class ParentIdBaggageWebFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // 从X-B3协议头获取真实的parentSpanId
        String parentSpanId = exchange.getRequest().getHeaders().getFirst("X-B3-ParentSpanId");
        // 无parentId时直接放行
        if (parentSpanId == null) {
            return chain.filter(exchange);
        }

        return Mono.deferContextual(reactorCtx -> {
            // 从Reactor Context获取OTel上下文,不存在则用当前线程上下文兜底
            Context otelCtx = reactorCtx.getOrDefault(Context.class, Context.current());

            // 合并现有Baggage并添加parentId字段
            Baggage updatedBaggage = Baggage.fromContext(otelCtx)
                    .toBuilder()
                    .put("parentId", parentSpanId)
                    .build();
            Context updatedOtelCtx = otelCtx.with(updatedBaggage);

            // 将更新后的OTel上下文写入Reactor Context,确保后续链路能获取到
            return chain.filter(exchange)
                    .contextWrite(ctx -> ctx.put(Context.class, updatedOtelCtx));
        });
    }
}

三、额外注意事项

  1. 依赖版本要求:确保你的OpenTelemetry依赖(Java Agent或Spring Boot Starter)版本≥1.28.0,否则无法使用otel.instrumentation.log-injection.baggage.keys配置
  2. X-B3协议启用:如果使用X-B3链路协议,需要在配置中启用对应的 propagator:
    otel.propagators=x-b3,tracecontext
    
  3. 避免线程污染:Spring WebFlux是非阻塞模型,OTel的Reactor instrumentation会自动处理上下文跨线程传播,无需手动同步MDC(配置生效后OTel会自动完成注入)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:14:49