文章目录
1. MDC 的功能
slf4j
除了日常使用的几个日志接口外,还可以配合 MDC
将必要的数据写入日志,但它的使用方式与其他的日志接口不同。MDC 可以将一个处理线程中你想体现在日志文件中的数据统一管理起来,根据日志文件配置决定是否输出。比如以下场景可以考虑使用 MDC
来达到目的:
- 在日志中体现请求用户IP地址
- 记录一次处理线程的日志跟踪编号(有了这个编号结合
grep
命令能将本次的处理日志全部输出,达到过滤效果)
2. MDC 的使用
MDC
一般会借助AOP
或者Filter
、Interceptor
使用,一个示例如下:
-
创建切面,分别是切入点注解
UnifiedTraceId
和切面逻辑UnifiedTraceIdAspect
,使用的时候将注解添加到要使用统一ID
的处理方法上就可以了。切面逻辑中把希望输出到日志的变量trace_id
存入,最后在 finally 代码块中再将其移除即可@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface UnifiedTraceId { }
@Slf4j @Aspect @Component public class UnifiedTraceIdAspect { @Around(value = "@annotation(com.nathan.common.aop.annotation.UnifiedTraceId)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { String uuid = UUID.randomUUID().toString(); MDC.put("trace_id", uuid); try { return joinPoint.proceed(); } catch (Throwable throwable) { throw throwable; } finally { MDC.remove("trace_id"); } } }
-
代码通过
AOP
记录了每次请求的traceId
并使用变量trace_id
记录,在日志配置文件里需要设置变量才能将trace_id
输出到日志文件中。以logback
配置文件为例,注意以下代码第 10 行<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <maxHistory>90</maxHistory> <fileNamePattern>${BASE_PATH_ALL}/%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>200MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder charset="UTF-8"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - traceId:[%X{trace_id}] - %msg%n</pattern> </encoder> </appender>