slf4j中的MDC slf4j中MDC是什么鬼
slf4j除了trace、debug、info、warn、error这几个日志接口外,还可以配合MDC将数据写入日志。换句话说MDC也是用来记录日志的,但它的使用方式与使用日志接口不同。
在使用日志接口时我们一般这么做
1 2 3 4 |
|
MDC从使用方式上有些不同,我对它的理解是MDC可以将一个处理线程中你想体现在日志文件中的数据统一管理起来,根据你的日志文件配置决定是否输出。
比如以下但不限于以下场景可以考虑使用MDC来达到目的
- 我们想在日志中体现请求用户IP地址
- 用户使用http客户端的user-agent
- 记录一次处理线程的日志跟踪编号(这个编号目的是为了查询日志方便,结合grep命令能根据跟踪编号将本次的处理日志全部输出)
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 |
|
代码通过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 |
|
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带来的好处
- 如果你的系统已经上线,突然有一天老板说我们增加一些用户数据到日志里分析一下。如果没有MDC我猜此时此刻你应该处于雪崩状态。MDC恰到好处的让你能够实现在日志上突如其来的一些需求
- 如果你是个代码洁癖,封装了公司LOG的操作,并且将处理线程跟踪日志号也封装了进去,但只有使用了你封装日志工具的部分才能打印跟踪日志号,其他部分(比如hibernate、mybatis、httpclient等等)日志都不会体现跟踪号。当然我们可以通过linux命令来绕过这些困扰。
- 使代码简洁、日志风格统一