Spring Cloud Sleuth 2.x WebFlux项目自定义trace id实现方案咨询
适配Spring Cloud Sleuth 2.2.8 + WebFlux 自定义TraceId实现方案
第一步:基础配置修改
先在application.yml中调整Sleuth默认传播规则,替换链路Header名称为correlation-id:
spring: sleuth: # 声明自定义传播的Header名称 propagation-keys: - correlation-id # 关闭默认B3协议传播规则 b3: enabled: false baggage: correlation: # 保证traceId自动注入MDC上下文 fields: - traceId enabled: true # 若自定义traceId不符合16/32位十六进制规则,开启以下配置关闭格式校验 # sleuth: # trace-id128: true # supports-join: false
第二步:自定义TraceId注入Filter(WebFlux适配)
实现优先级低于Sleuth默认链路Filter的WebFilter,在Sleuth初始化链路后替换默认traceId为自定义拼接值:
import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Tracer; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.server.reactive.ServerHttpRequest; 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; @Component // Sleuth默认TraceWebFilter优先级是HIGHEST_PRECEDENCE + 10,此处优先级更低,保证Sleuth先创建初始Span @Order(Ordered.HIGHEST_PRECEDENCE + 15) public class CustomTraceIdFilter implements WebFilter { private final Tracer tracer; public CustomTraceIdFilter(Tracer tracer) { this.tracer = tracer; } @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String customTraceId; // 优先读取请求头中的correlation-id作为traceId customTraceId = request.getHeaders().getFirst("correlation-id"); if (customTraceId == null) { // 从请求中获取三个参数拼接,此处示例为从query参数取,实际可根据需求调整为从请求体、路径变量取值 String param1 = request.getQueryParams().getFirst("param1"); String param2 = request.getQueryParams().getFirst("param2"); String param3 = request.getQueryParams().getFirst("param3"); // 自定义拼接规则,可自行调整 customTraceId = String.join("_", param1, param2, param3); } // 替换当前链路的traceId Span currentSpan = tracer.currentSpan(); if (currentSpan != null) { Span modifiedSpan = currentSpan.toBuilder() .traceId(customTraceId) .build(); // 将修改后的Span写入响应式上下文 return chain.filter(exchange) .contextWrite(tracer.withSpan(modifiedSpan)); } return chain.filter(exchange); } }
注意:如果三个参数存放在POST请求体中,需要先在Filter中缓存请求体数据,避免流只能读取一次导致后续业务逻辑报错。
第三步:WebClient自动携带Header配置
如果使用Spring容器自动注入的WebClient,Sleuth会自动将correlation-id注入到请求头中,无需额外配置。如果是手动构建的WebClient,需要添加Sleuth的链路过滤器:
import org.springframework.cloud.sleuth.instrument.web.client.TraceExchangeFilterFunction; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean public WebClient customWebClient(TraceExchangeFilterFunction traceFilter) { return WebClient.builder() .filter(traceFilter) .build(); } }
第四步:日志配置
原有log4j.xml中配置的%X{traceId}不需要修改,自定义traceId会自动注入到MDC上下文,直接就能按原有规则打印到所有日志中。
内容的提问来源于stack exchange,提问作者justAnotherDev
相关产品推荐
相关产品推荐

