SpringBoot MDC
在程序中,日志一直是一个至关重要的部分,排查问题、统计数据…
解决问题
SpringBoot
添加全局自定义日志链路信息。
1.过滤器,拦截指定请求,可取出参数、请求头等信息,可根据业务自定义添加进日志进程(MDC)
。
2.时间拦截器,根据注解进行拦截,向进程日志(MDC)
中,注入方法执行时间。
3.具体业务,可自行向进程日志(MDC)
中注入所需信息。
1.MDCFilter
请求过滤器,用于向MDC
中添加请求头等信息。
/**
* 拦截请求信息,添加到日志
*
* @author litong
* @date 2020/7/23 10:46
*/@Component@Log4j2@Order(2)@AllArgsConstructorpublicclassMDCFilterextendsOncePerRequestFilter{private MDCLogProperties mdcLogProperties;@OverrideprotectedvoiddoFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException{try{
MDC.put(mdcLogProperties.getHeaderSessionKey(),
request.getHeader(mdcLogProperties.getHeaderSessionKey()));
MDC.put("url", request.getRequestURI());
chain.doFilter(request, response);}finally{
MDC.clear();}}}
2.ApiTimerLog
注解,用于标注需要打印方法执行时间的标识。
/**
* 时间记录annotation
* 标注需要记录时间消耗的方法
*
* @author litong
* @date 2020/7/23 15:30
*/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interfaceApiTimerLog{}
3.TimeAspect
时间切片
/**
* @author litong
* @date 2020/7/23 15:31
*/@Aspect@Component@Slf4jpublicclassTimeAspect{// 修正Timer注解的全局唯一限定符@Pointcut("@annotation(com.ltz.ltzg.common.log.annotation.ApiTimerLog)")privatevoidpointcut(){}// 按包注入// @Around("execution(* com.ltz.ltzg.auth.controller.*.*(..))" +// "|| execution(* com.ltz.ltzg.api.controller.*.*(..))")// 按注解注入@Around("pointcut()")public Objectaround(ProceedingJoinPoint joinPoint)throws Throwable{// 开始时间long start= System.currentTimeMillis();// 调用目标方法
Object result= R.err(ErrorEnums.SHOW_FAIL);try{
result= joinPoint.proceed();}catch(Throwable throwable){throw throwable;}finally{// 获取执行时间long end= System.currentTimeMillis();long time= end- start;
MDC.put("executionTime", time+"");
R result1=newR();try{
result1=(R) result;}catch(Exception e){}
MDC.put("errcode", result1.getCode()+"");
log.info("Api-Link");}return result;}}
4.logback-local.xml
<?xml version="1.0" encoding="UTF-8"?><!--该日志将日志级别不同的log信息保存到不同的文件中 --><configuration><includeresource="org/springframework/boot/logging/logback/defaults.xml"/><includeresource="org/springframework/boot/logging/logback/console-appender.xml"/><includeresource="org/springframework/boot/logging/logback/file-appender.xml"/><springPropertyscope="context"name="springAppName"source="spring.application.name"/><!-- 日志在工程中的输出位置 --><propertyname="LOG_FILE"value="C:/data/logs/${springAppName}"/><!--<property name="LOG_FILE" value="/data/ltz/logs/${springAppName}" />--><!-- 控制台的日志输出样式 --><propertyname="CONSOLE_LOG_PATTERN"value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- })[%thread] [url=%X{url};ltz-token=%X{ltz-token};executionTime=%X{executionTime};errcode=%X{errcode}] {magenta} %clr(---){faint} %clr([%15.15t]){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!-- 控制台输出 --><appendername="console"class="ch.qos.logback.core.ConsoleAppender"><filterclass="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><!-- 日志输出编码 --><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><!-- 文件输出 --><appendername="localfile"class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_FILE}.json</file><rollingPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.%i.gz</fileNamePattern><maxFileSize>${LOG_FILE_MAX_SIZE:-1000MB}</maxFileSize><maxHistory>${LOG_FILE_MAX_HISTORY:-7}</maxHistory></rollingPolicy><filterclass="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [url=%X{url};ltz-token=%X{ltz-token};executionTime=%X{executionTime};errcode=%X{errcode}] %-5level %logger{35} - %msg%n</pattern></encoder></appender><!-- sql文件输出 --><appendername="sqlfile"class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_FILE}.sqllog</file><rollingPolicyclass="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.sqlLog</fileNamePattern><maxHistory>3</maxHistory></rollingPolicy><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern></encoder></appender><!-- 日志输出级别 --><rootlevel="INFO"><appender-refref="console"/><appender-refref="localfile"/></root><loggername="dao"level="debug"additivity="false"><appender-refref="sqlfile"/></logger></configuration>
5.日志模板说明
MDC中添加的key,需要在日志模板中,用%X{url}
的方式,打印。
使用案例
/**
* @author litong
* @date 2020/6/1 17:10
*/@RequestMapping("/test")@RestControllerpublicclassTestController{@ApiTimerLog@GetMapping("/a")public Ra(){return R.ok("a");}}
日志输出
2020-07-27 13:41:16.960 INFO 24052[http-nio-18989-exec-5] [url=/test/a;ltz-token=123;executionTime=0;errcode=1000]{magenta} --- [io-18989-exec-5] Api-Link