slf4j中的MDC

https://blog.csdn.net/qq897958555/article/details/76927003

slf4j中的MDC

slf4j中MDC是什么鬼

  slf4j除了trace、debug、info、warn、error这几个日志接口外,还可以配合MDC将数据写入日志。换句话说MDC也是用来记录日志的,但它的使用方式与使用日志接口不同。

  在使用日志接口时我们一般这么做

1

2

3

4

Logger LOG = LoggerFactory.getLogger("LOGNAME_OR_CLASS");

if(LOG.isDebugEnabled()) {

  LOG.debug("log debug");

}

  MDC从使用方式上有些不同,我对它的理解是MDC可以将一个处理线程中你想体现在日志文件中的数据统一管理起来,根据你的日志文件配置决定是否输出。

  比如以下但不限于以下场景可以考虑使用MDC来达到目的

  1. 我们想在日志中体现请求用户IP地址
  2. 用户使用http客户端的user-agent
  3. 记录一次处理线程的日志跟踪编号(这个编号目的是为了查询日志方便,结合grep命令能根据跟踪编号将本次的处理日志全部输出)

MDC的使用

  org.slf4j.MDC我个人会用AOP或Filter或Interceptor这类工具配合使用,获得你希望输出到日志的变量并调用MDC.put(String key, String val),比如下面代码片段第5行:

1

2

3

4

5

6

7

8

9

10

11

12

13

@Around(value = "execution(* com.xx.xx.facade.impl.*.*(..))", argNames="pjp")

  public Object validator(ProceedingJoinPoint pjp) throws Throwable {

      try {

          String traceId = TraceUtils.begin();

          MDC.put("mdc_trace_id", traceId);

          Object obj = pjp.proceed(args);

          return obj;

      catch(Throwable e) {

          //TODO 处理错误

      finally {

          TraceUtils.endTrace();

      }

  }   

   代码通过AOP记录了每次请求的traceId并使用变量"mdc_trace_id"记录,在日志配置文件里需要设置变量才能将"mdc_trace_id"输出到日志文件中。我以logback配置文件为例,看日志第10行%X{mdc_trace_id}:

1

2

3

4

5

6

7

8

9

10

11

12

<appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">

      <file>${CATALINA_BASE}/logs/all.log</file>

      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

          <!-- daily rollover -->

          <fileNamePattern>${CATALINA_BASE}/logs/all.%d{yyyy-MM-dd}.log</fileNamePattern>

          <!-- keep 30 days' worth of history -->

          <maxHistory>30</maxHistory>

      </rollingPolicy>

      <encoder charset="UTF-8">

          <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - traceId:[%X{mdc_trace_id}] - %msg%n</pattern>

      </encoder>

  </appender>

package cn.quantgroup.pinjamancepat.filter.commons;

import cn.quantgroup.pinjamancepat.model.commons.Constants;
import cn.quantgroup.pinjamancepat.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Instant;

/**
 * Created by liqing on 2018/8/1 0001.
 */
@Slf4j
public class RequestTraceFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            MDC.put(Constants.THREAD_TRACE_ID_KEY, RandomUtil.generateRandomTraceId());
            filterChain.doFilter(request, response);
        } finally {
            MDC.remove(Constants.THREAD_TRACE_ID_KEY);
            MDC.clear();
        }
    }
}

MDC带来的好处

  1. 如果你的系统已经上线,突然有一天老板说我们增加一些用户数据到日志里分析一下。如果没有MDC我猜此时此刻你应该处于雪崩状态。MDC恰到好处的让你能够实现在日志上突如其来的一些需求
  2. 如果你是个代码洁癖,封装了公司LOG的操作,并且将处理线程跟踪日志号也封装了进去,但只有使用了你封装日志工具的部分才能打印跟踪日志号,其他部分(比如hibernate、mybatis、httpclient等等)日志都不会体现跟踪号。当然我们可以通过linux命令来绕过这些困扰。
  3. 使代码简洁、日志风格统一

文章标签: slf4j

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值