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

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

目录

MDC使用

用法一 

用法二


MDC使用

引入相关依赖

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.21</version>
    </dependency>

    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>

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

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd hh:mm:ss} [%thread] [traceId = %X{traceId}] [%logger{32}] - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console"/>
    </root>
</configuration>

用法一 

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

@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<String, String> context = MDC.getCopyOfContextMap();
        executor.execute(()->{
            try{
                MDC.setContextMap(context);
                LogConstant.ACC_LOG.info("xxx ");
            } finally {
                MDC.clear();
            }
        });

关键代码是: 

 Map<String, String> context = MDC.getCopyOfContextMap();

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

MDC.setContextMap(context);

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

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值