在SpringBoot项目中添加logback的MDC
先看下MDC是什么
Mapped Diagnostic Context,用于打LOG时跟踪一个“会话“、一个”事务“。举例,有一个web controller,在同一时间可能收到来自多个客户端的请求,如果一个请求发生了错误,我们要跟踪这个请求从controller开始一步步都执行到了哪些代码、有哪些log的输出。这时我们可以看log文件,但是log文件是多个请求同时记录的,基本无法分辨哪行是哪个请求产生的,虽然我们可以看线程,但线程可能被复用,也是很难分辨出,这时MDC就派上用场了。
我们可以加一个web filter,在请求进来时,把”标识“放到MDC context中,比如:put( ip, 8.8.8.8), put(username, 'yang'),在filter结束时把context再清掉,即可在整个请求处理过程中,都可以打印出ip, username这些数据,就可以方便的用于日志跟踪。
在SpringBoot中怎么用
1. 写一个LogInterceptor,用于统一处理MDC:
-
-
public class LogInterceptor implements HandlerInterceptor {
-
-
private final static String REQUEST_ID = "requestId";
-
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);
-
-
-
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
-
String xForwardedForHeader = httpServletRequest.getHeader("X-Forwarded-For");
-
String remoteIp = httpServletRequest.getRemoteAddr();
-
String uuid = UUID.randomUUID().toString();
-
LOGGER.info("put requestId ({}) to logger", uuid);
-
LOGGER.info("request id:{}, client ip:{}, X-Forwarded-For:{}", uuid, remoteIp, xForwardedForHeader);
-
MDC.put(REQUEST_ID, uuid);
-
return true;
-
}
-
-
-
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
-
String uuid = MDC.get(REQUEST_ID);
-
LOGGER.info("remove requestId ({}) from logger", uuid);
-
MDC.remove(REQUEST_ID);
-
}
-
-
-
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
-
-
}
-
}
关键代码在于:MDC.put(REQUEST_ID, uuid);
2. 注册一下这个Interceptor,写一个WebMvcConfigurer类:
-
-
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
-
-
private LogInterceptor logInterceptor;
-
-
-
public void addInterceptors(InterceptorRegistry registry) {
-
registry.addInterceptor(logInterceptor);
-
super.addInterceptors(registry);
-
}
-
}
3. 放一个logback.xml到src/main/resources/目录中,用于配置logback的参数,如没有,请新建一个
-
<configuration scan="true" scanPeriod="30 seconds" debug="true">
-
-
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-
<target>System.out</target>
-
<encoder>
-
<pattern>[%date{ISO8601}] [%-5level] - [%thread] [%X{requestId}] [%logger] [%X{akkaSource}] - %msg %rootException %n
-
</pattern>
-
-
</encoder>
-
</appender>
-
-
-
-
<root level="INFO">
-
<appender-ref ref="STDOUT"/>
-
</root>
-
-
</configuration>
4. 最后看下效果,下面加粗的即为requestId
[2017-12-14 16:08:45,677] [INFO ] - [http-nio-8080-exec-1] [a08f86cd-6743-48ce-816a-f5ee61b802b8]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2015-03-25 ormlite 文档