Spring Boot应用无logback.xml/log4j.properties,如何实现MDC?
微服务中实现MDC日志配置的方案
(注:Spring Boot默认采用Logback作为日志框架,即便没有手动创建日志配置文件,也可以通过以下方式完成MDC配置)
1. 手动创建适配Spring Boot的日志配置文件
直接在src/main/resources目录下创建logback-spring.xml(这个文件名比logback.xml更适配Spring Boot的自动配置逻辑),示例配置如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 继承Spring Boot默认的基础日志配置,不用重复写通用配置 --> <include resource="org/springframework/boot/logging/logback/base.xml"/> <!-- 自定义控制台输出格式,加入MDC的traceId字段 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{traceId} - %msg%n</pattern> </encoder> </appender> <!-- 设置根日志级别 --> <root level="info"> <appender-ref ref="CONSOLE"/> </root> </configuration>
其中%X{traceId}就是MDC的占位符,后续代码中往MDC存入对应key的值,日志就会自动输出该字段。
2. 直接用application配置文件定义日志格式
如果不想写XML配置,也可以直接在application.yml或application.properties里配置日志格式,加入MDC字段:
application.yml示例:
logging: pattern: console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{traceId} - %msg%n" level: root: info
application.properties示例:
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{traceId} - %msg%n logging.level.root=info
3. 实现MDC上下文的注入与清理
微服务中通常在请求入口处设置MDC值,比如用拦截器统一处理:
第一步:创建TraceId拦截器
import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.UUID; @Component public class TraceIdInterceptor implements HandlerInterceptor { private static final String TRACE_ID_KEY = "traceId"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 优先从请求头取traceId,没有则自动生成 String traceId = request.getHeader("traceId"); if (traceId == null || traceId.isEmpty()) { traceId = UUID.randomUUID().toString(); } // 把traceId放入MDC MDC.put(TRACE_ID_KEY, traceId); // 将traceId返回给前端,方便后续排查问题 response.setHeader("traceId", traceId); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求结束后清除MDC,避免线程复用导致脏数据 MDC.remove(TRACE_ID_KEY); } }
第二步:注册拦截器
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { private final TraceIdInterceptor traceIdInterceptor; public WebMvcConfig(TraceIdInterceptor traceIdInterceptor) { this.traceIdInterceptor = traceIdInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { // 对所有请求生效 registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**"); } }
4. 异步线程的MDC上下文传递
如果用到异步线程池,MDC不会自动传递上下文,需要手动包装线程任务:
第一步:创建MDC任务装饰器
import org.slf4j.MDC; import org.springframework.core.task.TaskDecorator; import java.util.Map; public class MdcTaskDecorator implements TaskDecorator { @Override public Runnable decorate(Runnable runnable) { // 保存当前线程的MDC上下文 Map<String, String> mdcContext = MDC.getCopyOfContextMap(); return () -> { try { // 在异步线程中恢复MDC上下文 if (mdcContext != null) { MDC.setContextMap(mdcContext); } runnable.run(); } finally { // 异步任务结束后清除MDC MDC.clear(); } }; } }
第二步:配置线程池时加入装饰器
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; @Configuration public class AsyncConfig { @Bean(name = "asyncExecutor") public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(20); executor.setThreadNamePrefix("async-task-"); // 加入MDC装饰器,实现上下文传递 executor.setTaskDecorator(new MdcTaskDecorator()); executor.initialize(); return executor; } }
内容的提问来源于stack exchange,提问作者gan7202
相关产品推荐
相关产品推荐

