如何通过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实现
你当前的代码存在两个核心问题:
- 错误地从
X-B3-SpanId头获取parentId,正确的parentId来源是X-B3-ParentSpanId - 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)); }); } }
三、额外注意事项
- 依赖版本要求:确保你的OpenTelemetry依赖(Java Agent或Spring Boot Starter)版本≥1.28.0,否则无法使用
otel.instrumentation.log-injection.baggage.keys配置 - X-B3协议启用:如果使用X-B3链路协议,需要在配置中启用对应的 propagator:
otel.propagators=x-b3,tracecontext - 避免线程污染:Spring WebFlux是非阻塞模型,OTel的Reactor instrumentation会自动处理上下文跨线程传播,无需手动同步MDC(配置生效后OTel会自动完成注入)
内容的提问来源于stack exchange,提问作者fernando1979
相关产品推荐
相关产品推荐

