MDC是干什么的

他是在多线程下追踪日志的工具,我们都知道日志的组成基本都是,由时间、线程名、类package组成的。当一个请求进来的时候,打印的日志是一套类的调用链。
这个并没有问题,但是多线程的情况下日志会乱,我们需要根据特有的线程名标识也是能找到请求所对应的日志,但是spring的请求线程是复用的,也就是说多线程的情况下,日志线程名称是重复的,所以需要一个标识去标识日志,代表这个日志是这次调用的日志,我们只需要grep即可。
这个线程并不复杂,我这边生成一个uuid,设置日志的时候设置一下不就好了吗?没错,很简单!但是太麻烦了,我们 需要一个无侵入式的东西。于是,MDC就出来了。

MDC怎么做的

他的实现很简单,只需要在xml设置日志格式为

1
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread | [%X{X-B3-TraceId}] | %-5level %logger{50} %msg%n</pattern> 

然后再加个切点即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   /**
* controller的切点
*/
@Pointcut("execution(public * com.lhp.*.controller..*.*(..))")
public void controllerTraceId() {
}
/**
* 所有controller环绕切点
*
* @param proceedingJoinPoint 切入点
* @return Object
* @throws Throwable 异常
*/
@Around("controllerTraceId()")
public Object doControllerAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
MDC.put("X-B3-TraceId", UUID.randomUUID().toString());
Object result = proceedingJoinPoint.proceed();
MDC.clear();
return result;
}

你会发现,他是在打印日志之前加的,并设置了一哥标识数据,和上面的打印日志的[%X{X-B3-TraceId}]一样,这个时候点进去MDC类,发现这个是一个日志框架实现类,这个时候,我们就明白了。
日志框架实现了这个功能,我在设置日志格式的时候,设置一个取值格式,我在代码里打日志前执行,给这个取值的标识设置一个可取的值,这样的实现是最方便简单的。