本系列文章记录“智能提醒助理”产品建设历程,记录实践经验、巩固知识点、锻炼总结能力。
本篇介绍如何让springboot启动日志“彩打” 提升日志识别度,同时增加TraceID,便于同一请求,全链路的追踪。
一、需求出发点
提升日志识别度,可读性。
识别单一请求全链路日志。
二、结果展示
三、彩虹日志实现方案
springboot项目中 使用logback,关键点在于 日志格式化时 针对每段关键字进行 高亮。
<property name="PATTERN_DEFAULT" value="%highlight(%date{yyyy-MM-dd HH:mm:ss.SSS}) %cyan([%thread]) %yellow(
四、TraceID http场景实现方案
1、增加拦截器,拦截外部请求。
2、通过slf4j提供的MDC方案,注入traceID。
package com.jdy.common.config.interceptor;
import com.jdy.common.utils.security.IDUtil;
import com.jdy.platform.service.TokenService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* TraceID 日志 设置
* */
@Slf4j
public class TraceIdInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在日志框架中的MDC中添加请求的唯一标识(用于返回接口及保存mysql)
MDC.put("traceId", IDUtil.getID());
return true;
}
}
五、XXL-JOB调度发起的请求增加TraceID
package com.jdy.common.config.interceptor;
import com.jdy.common.utils.security.IDUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class XxlJobAspect {
/**
* 拦截到XXL-JOB的请求,在入口添加TraceID
*/
@Before("@annotation(com.xxl.job.core.handler.annotation.XxlJob)")
public void beforeMethod() {
MDC.put("traceId", IDUtil.getID());
}
}
六、代码总结
完整的代码如下:
application.yml 配置
# 日志配置
logging:
level:
root: INFO
com.jdy: debug
org.springframework: warn
com.xxl.job
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false">
<!-- 日志文件路径 -->
<property name="LOG_DIR" value="logs/" />
<property name="PROJECT_NAME" value="jdy-admin" />
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度,%msg:日志消息,%n是换行符 -->
<!-- 彩虹日志-->
<property name="PATTERN_DEFAULT" value="%highlight(%date{yyyy-MM-dd HH:mm:ss.SSS}) %cyan([%thread]) %yellow(%-5level) [%X{traceId}] [%green(%logger{36}).%white(%M)-%boldMagenta(%line)] - %blue(%msg%n)"/>
<!-- 控制台appender-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${PATTERN_DEFAULT}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 业务日志appender -->
<appender name="common-biz" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/${PROJECT_NAME}_biz.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/his/${PROJECT_NAME}.%d{yyyy-MM-dd}_biz.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${PATTERN_DEFAULT}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- 异常日志appender -->
<appender name="common-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/${PROJECT_NAME}_error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/his/${PROJECT_NAME}_error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${PATTERN_DEFAULT}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- httpclient 日志 -->
<Logger name="org.apache.http.client" level="warn"/>
<!-- 默认输出日志 -->
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="common-biz" />
<appender-ref ref="common-error" />
</root>
</configuration>