- 业务需求
保证一次服务调用,在业务中可以一次追查到本次服务调用涉及的本地服务方法,第三方服务接口。实现日志的链路追踪。保证日志的高查找性。
- 实现步骤
1、pom.xml 依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></dependency><!--lombok配置--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency> </dependencies>
2、整合logback,打印日志,logback.xml (日志配置文件)
关键代码:[traceId:%X{traceId}],traceId是通过拦截器里MDC.put(traceId, tid)添加。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"><!--日志存储路径--><property name="log" value="D:/test/log" /><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--输出格式化--><pattern>[traceId:%X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 按天生成日志文件 --><appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件名--><FileNamePattern>${log}/%d{yyyy-MM-dd}.log</FileNamePattern><!--保留天数--><MaxHistory>30</MaxHistory></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>[traceId:%X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder><!--日志文件最大的大小--><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>10MB</MaxFileSize></triggeringPolicy></appender><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="console" /><appender-ref ref="file" /></root> </configuration>
3、application.yml指定logback.xml配置目录
logging:config: classpath:logback.xml
4、异步线程的跟踪ID链路追踪
业务逻辑是基于线程数据的传递进行处理,主线程传递线程ID到子线程。处理方式:重写线程池的execute(*)、submit(*)方法。
public final class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {public MyThreadPoolTaskExecutor() {super();}@Overridepublic void execute(Runnable task) {super.execute(TraceIdUtil.wrap(task, MDC.getCopyOfContextMap()));}@Overridepublic <T> Future<T> submit(Callable<T> task) {return super.submit(TraceIdUtil.wrap(task, MDC.getCopyOfContextMap()));}@Overridepublic Future<?> submit(Runnable task) {return super.submit(TraceIdUtil.wrap(task, MDC.getCopyOfContextMap()));} }
4、异步定时任务线程接口ScheduledExecutorService的日志链路追踪。在执行前,执行后进行跟踪ID的生成和删除。
@Bean(name = "scheduledExecutorService")protected ScheduledExecutorService scheduledExecutorService() {return new ScheduledThreadPoolExecutor(corePoolSize,new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),new ThreadPoolExecutor.CallerRunsPolicy()) {@Overrideprotected void beforeExecute(Thread thread, Runnable runnable) {super.beforeExecute(thread, runnable);// 为定时任务生成一个 traceId TraceIdUtil.setTraceId();// 可选:添加任务标识System.out.println("Scheduled task starting with traceId: " + TraceIdUtil.getTraceId());}@Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);Threads.printException(r, t);TraceIdUtil.remove();}};}
注:萌新一枚,该博客用于记录所学知识,如有不对的地方,请及时指教,谢谢各位。
2025-10-20 15:46:36