slf4j中的MDC解决日志追踪问题

MDC是SLF4J中的一个类,通过MDC我们可以很方便的实现同一个线程内(包括父线程和子线程之间)的日志的追踪,对于一个请求能够很容易的根据traceId这样的值很快的找到该线程包括子线程所经历的全部的日志,轻松的把程序中的逻辑串联起来,通过一个例子来说明。

目录

MDC使用

用法一 

用法二


MDC使用

引入相关依赖

    
      org.slf4j
      slf4j-api
      1.7.21
    

    
      ch.qos.logback
      logback-classic
      1.2.3
    

同时需要在logback.xml中添加对应的appender的pattern,主要是这个[traceId = %X{traceId}]



    
        
            %d{yyyy-MM-dd hh:mm:ss} [%thread] [traceId = %X{traceId}] [%logger{32}] - %msg%n
        
    

    
        
    

用法一 

在一个线程中的使用,代码如下:

@ProviderAnnotation(value = "sync")
    public String sync(DTO dto) {
        MDC.put("traceId", dto.getTraceId);
        LogConstant.ACC_LOG.info("begin");
        return "hello";
    }

主要的代码是

MDC.put("traceId", dto.getTraceId);

需要注意的是和使用ThreadLocal一样,一定要记得clear,事实上这玩意的底层就是ThreadLocal,只是slf4j自己封装了而已,我此处的在aop中统一进行的clear操作。

 finally {
            MDC.clear();
        }

效果是:

[pool-12-thread-2] [traceId = aaa] .......

用法二

使用上面的方法发现在我主线程中开启异步的线程或者使用线程池时没有将该traceId打印出来,我们需要相关的代码做如下调整:

ExecutorService executor = Executors.newSingleThreadExecutor();
        Map context = MDC.getCopyOfContextMap();
        executor.execute(()->{
            try{
                MDC.setContextMap(context);
                LogConstant.ACC_LOG.info("xxx ");
            } finally {
                MDC.clear();
            }
        });

关键代码是: 

 Map context = MDC.getCopyOfContextMap();

这个一定要在run之前先获取一下,否则可能导致下面取不到值。

MDC.setContextMap(context);

同时别忘记clear的操作,打印效果和上面一致。

你可能感兴趣的:(日志跟踪,java,logback)