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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:10:25