SpringBoot使用TraceId进行日志链路追踪
什么是MDC
MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 、logback及log4j2 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。
为什么使用traceId
我们在定位问题的时候需要去日志中查找对应的位置,当我们一个接口的请求同用唯一的一个traceId,那我们只需要知道这个traceId,使用 grep ‘traceId’ xxx.log 语句就能准确的定位到目标日志。在这边文章会介绍如何去设置这个traceId,而后如何在接口返回这个traceId。
通过MDC设置traceId
使用MDC.put(key,val);设置追踪吗的值
新建一个过滤器doFilter设置追踪码destroy中清空
@Order(-999999)
@Slf4j
@Component
@WebFilter(filterName = "traceIdFilter",urlPatterns = "/*")
public class TraceIdFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
MDC.put(Constants.TRACE_ID, IdUtil.fastSimpleUUID());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
MDC.clear();
}
}
logback.xml中配置traceId
补充异步方法带入上下文的traceId
异步方法会开启一个新线程,我们想要是异步方法和主线程共用同一个traceId,首先先新建一个任务适配器MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {
/**
* 使异步线程池获得主线程的上下文
* @param runnable
* @return
*/
@Override
public Runnable decorate(Runnable runnable) {
Map<String,String> map = MDC.getCopyOfContextMap();
return () -> {
try{
MDC.setContextMap(map);
runnable.run();
} finally {
MDC.clear();
}
};
}
}
然后,线程池中增加配置如下:
然后在业务代码上开启@Async,SprongBoot上开启异步调用 @EnableAsync
在封装的统一返回实体中设置追踪码的值,统一相应给调用者
这样以后遇到问题就可以根据TraceId的值去日志里面找到相应的日志信息从而定位问题