SpringBoot MDC全链路调用日志跟踪实现详解

2023-02-08 10:06:31

目录MDC介绍API说明MDC使用添加拦截器修改日志格式常见问题子线程日志打印丢失traceIdMDC介绍MDC(MappedDiagnosticContext,映射调试上下文)是lo...

目录
MDC 介绍
API 说明
MDC 使用
添加拦截器
修改日志格式
常见问题
子线程日志打印丢失 traceId

MDC 介绍

MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 、logback及log4j2 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

API 说明

clear() => 移除所有 MDC
get (String key) => 获取当前线程 MDC 中指定 key 的值
getContext() => 获取当前线程 MDC 的 MDC
put(String key, Object o) => 往当前线程的 MDC 中存入指定的键值对
remove(String key) => 删除当前线程 MDC 中指定的键值对

MDC 使用

Constants.TRACE_ID = "traceId"

添加拦截器

public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果有上层调用就用上层的ID
        String traceId = request.getHeader(Constants.TRACE_ID);
        if (traceId == null) {
            traceId = TraceIdUtil.getTraceId();
        }
        MDC.put(Constants.TRACE_ID, traceId);
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        //调用结束后删除
        MDC.remove(Constants.TRACE_ID);
    }
}

修改日志格式

<!-- 日志输出格式 -->
<property name="log.pattern" value="[TraceId:%X{traceId}] %d{HHss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>

重点是 %X{traceId},traceId 和 MDC 中的键名称一致。

简单使用就这么容易,但是在有些情况下 traceId 将获取不到。

常见问题

子线程日志打印丢失 traceId

   //获取traceId
   Map<String, String> mdcContextMap = MDC.getCopyOfContextMap();
   return  () ->{
     //添加到子线程中
     MDC.setContextMap(mdcContextMap);
     System.out.println("你好呀!");
   }       

以上就是SpringBoot MDC全链路调用日志跟踪实现详解的详细内容,更多关于SpringBoot MDC日志跟踪的资料请关注我们其它相关文章!