slf4j 打印traceID介绍
slf4j除了trace、debug、info、warn、error这几个日志接口外,还可以配合日志分析将数据写入日志。
在使用日志接口时我们一般这么做
Logger LOG = LoggerFactory.getLogger("LOGNAME_OR_CLASS");
if(LOG.isDebugEnabled()) {
LOG.debug("log debug");
}
那么 如果我们想在日志文件中打印自定义信息该怎么办呢?比如打印以下信息:
- 我们想在日志中体现请求用户IP地址
- 用户使用http客户端的user-agent
- 记录一次处理线程的日志跟踪编号(这个编号目的是为了查询日志方便,结合grep命令能根据跟踪编号将本次的处理日志全部输出)
解决办法
org.slf4j.MDC我个人会用AOP或Filter或Interceptor这类工具配合使用,获得你希望输出到日志的变量并调用MDC.put(String key, String val),比如下面代码
片段第5行:
@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}:
<``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``>
MDC带来的好处
-
如果你的系统已经上线,突然有一天老板说我们增加一些用户数据到日志里分析一下。如果没有MDC我猜此时此刻你应该处于雪崩状态。MDC恰到好处的让
你能够实现在日志上突如其来的一些需求
-
如果你是个代码洁癖,封装了公司LOG的操作,并且将处理线程跟踪日志号也封装了进去,但只有使用了你封装日志工具的部分才能打印跟踪日志号,其他部
分(比如hibernate、mybatis、httpclient等等)日志都不会体现跟踪号。当然我们可以通过linux命令来绕过这些困扰。
-
使代码简洁、日志风格统一