Spring Cloud Gateway升级Boot3.1.5后Micrometer Tracing日志问题求助
解决Spring Cloud Gateway 3.x中Reactor Netty日志丢失TraceId/SpanId的问题
针对你升级后遇到的Reactor Netty HttpClient/HttpServer日志、Netty访问日志丢失TraceId/SpanId的问题,可以通过以下步骤修复:
1. 替换依赖,适配Micrometer Tracing
原有的io.projectreactor.netty:reactor-netty-http-brave是Sleuth专属集成,在Micrometer Tracing环境下不再生效,需要替换为Micrometer官方的Reactor桥接依赖:
Maven配置
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-reactor</artifactId> </dependency>
Gradle配置
implementation 'io.micrometer:micrometer-tracing-bridge-brave' implementation 'io.micrometer:micrometer-reactor'
2. 配置Reactor Netty追踪自定义器
注册自定义的HttpClientCustomizer和HttpServerCustomizer,将Micrometer Tracing的上下文注入到Reactor Netty的请求链路中,让日志能获取到TraceId/SpanId:
import io.micrometer.tracing.Tracer; import io.micrometer.tracing.reactor.ReactorTracing; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import reactor.netty.http.client.HttpClient; import reactor.netty.http.server.HttpServer; @Configuration public class ReactorNettyTracingConfig { @Bean public HttpClientCustomizer httpClientTracingCustomizer(Tracer tracer) { return httpClient -> httpClient.tracer(spec -> spec.tracer(ReactorTracing.create(tracer))); } @Bean public HttpServerCustomizer httpServerTracingCustomizer(Tracer tracer) { return httpServer -> httpServer.tracer(spec -> spec.tracer(ReactorTracing.create(tracer))); } }
3. 修复Netty访问日志的TraceId注入
Netty访问日志默认不会自动携带Trace上下文,需要自定义AccessLogFactory来手动注入TraceId和SpanId:
import io.micrometer.tracing.Tracer; import reactor.netty.http.server.AccessLog; import reactor.netty.http.server.AccessLogFactory; import java.util.function.Supplier; @Configuration public class NettyAccessLogConfig { @Bean public AccessLogFactory accessLogFactory(Tracer tracer) { return protocol -> () -> new AccessLog() { @Override public void log(String remoteAddress, String username, String method, String uri, String protocol, int status, int contentLength, String referer, String userAgent, long elapsedTime) { String traceId = tracer.currentSpan() != null ? tracer.currentSpan().context().traceId() : "N/A"; String spanId = tracer.currentSpan() != null ? tracer.currentSpan().context().spanId() : "N/A"; // 按原有访问日志格式拼接,追加TraceId和SpanId String logContent = String.format("%s %s - \"%s %s %s\" %d %d \"%s\" \"%s\" %dms traceId=%s spanId=%s", remoteAddress, username, method, uri, protocol, status, contentLength, referer, userAgent, elapsedTime, traceId, spanId); // 可替换为项目日志框架输出,例如LoggerFactory.getLogger(AccessLog.class).info(logContent) System.out.println(logContent); } }; } }
同时在配置文件中开启Netty访问日志和Wiretap:
spring: cloud: gateway: httpclient: wiretap: true httpserver: wiretap: true reactor: netty: http: server: access-log-enabled: true
4. 确认日志格式配置
确保你的日志框架(如Logback)的格式中包含%X{traceId}和%X{spanId},以保证日志能正确输出追踪ID。例如Logback的配置片段:
<encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg traceId=%X{traceId} spanId=%X{spanId}%n</pattern> </encoder>
完成以上配置后,Reactor Netty的HttpClient/HttpServer日志以及Netty访问日志就能正常输出TraceId和SpanId了。
内容的提问来源于stack exchange,提问作者Sandra Markerud
相关产品推荐
相关产品推荐

