logback输出日志区分所属线程:方便运维排查问题
背景
业务上,当同一个请求日志很多,我们需要查看,某一次请求的上下文日志信息,怎么办?
先来看看我们的请求过程:
不同用户发起同一个请求 -----> web容器(tomcat) -----> 从线程池拿到一个线程,处理具体一个用户的请求 -----> 我们的业务代码,输出日志
那就在每行日志输出上,增加代表这个线程,会话的信息,方案如下:
1. 输出线程id
2. 输出自己生成的随机字符,如uuid
先来看第一种方案: 线程是从线程池拿到,id是可能会重复,不符合我们的需求。那么只有第二中方案符合我们的需求了。
输出自己生成的随机字符
slf4j为我们提供了MCD工具类,可以让我们放一些变量值到日志中输出。
自定义拦截器,设置MCD
生成每次请求的唯一标识
/**
* @author xuelongjiang
* @description logback拦截器
**/
public class LogInterceptor implements HandlerInterceptor {
public static final String REQUESTUUID = "REQUEST_UUID";
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String token = UUID.randomUUID().toString().replace("-", "").toUpperCase();
MDC.put(REQUESTUUID, token);
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception {
// nothing
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
MDC.remove(REQUESTUUID);
}
}
HandlerInterceptor业务处理器拦截器,给我们提供了三个方法:
1.preHandle:在业务处理器请求之前被调用。预处理可以可以进行编码控制、安全控制、权限校验等
2.postHandle:在业务处理器处理请求完成之后,在生成视图之前执行。
3.afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。
设置拦截所有请求
@Configuration
public class WebAppconfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry interceptorRegistry) {
interceptorRegistry.addInterceptor(new LogInterceptor()).addPathPatterns("/**");
return;
}
}
logback日志输出增加请求唯一标识
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} | %thread | %logger{56} | %-5level | %X{HOST_IP} | %X{USER_NAME} | %X{REQUEST_UUID} | %X{REQUEST_URL} | %msg%n
</pattern>
</encoder>
参考
https://blog.csdn.net/zhibo_lv/article/details/81699360