SpringBoot实现简单的日志链路追踪
作者:Ethan
一. 背景
随着分布式应用的普及,现在的一些应用系统不再像以前,所有的文件(前后端程序)都打包在一个包中,现在的很多应用都是模块化开发,开发的团队也是不一样,服务与服务之间的调用也比较多,在这种情况下,系统的日志就显得尤其的重要,然而,在多数情况下,当我们的系统出现了异常,需要查看日志时,就会很抓狂。为了避免这种情况,我们需要把同一次的业务调用链上的日志串联起来。
本次通过一个简单的SpringBoot应用来总结,我们如何将日志串联起来,以下截图是最终的实现效果

二. 代码演示
1. 创建一个SpringBoot项目
使用idea创建一个
SpringBoot项目的详细步骤,本文不介绍了,具体的步骤,网上有很多例子可以参考
1.1. 我的SpringBoot项目名称是:springboot-track,以下是工程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-logging</artifactId> ?</dependency> ? ?<dependency> ? ?<groupId>org.projectlombok</groupId> ? ?<artifactId>lombok</artifactId> ? ?<optional>true</optional> ?</dependency> ?<dependency> ? ?<groupId>org.springframework.boot</groupId> ? ?<artifactId>spring-boot-starter-test</artifactId> ? ?<scope>test</scope> ?</dependency> </dependencies>
1.2. 在项目的resource目录下,创建日志框架整合配置文件:logback-spring.xml文件内容配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
?<!--日志存储路径-->
?<property name="log" value="/Users/username/Downloads"/>
?<!-- 控制台输出 -->
?<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
? ?<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
? ? ?<!--输出格式化-->
? ? ?<pattern>[%X{TRACE_ID}] %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>[%X{TRACE_ID}] %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>1.3. 在项目的resource目录下的主配置文件(application.yml)中添加日志整合配置信息,添加内容如下:
需要注意的是:使用
idea创建的SpringBoot项目,application文件的默认后缀是.properties,本人比较喜欢.yml文件,所以将文件后缀名修改了一下
server: port: 8080 logging: config: classpath:logback-springboot.xml pattern: ? dateformat: MM-dd HH:mm:ss
1.4. 自定义日志拦截器:LogInterceptor.java
public class LogInterceptor implements HandlerInterceptor {
?
?private static final String TRACE_ID = "TRACE_ID";
?
?@Override
?public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
? ?// 使用UUID自动生成链路ID
? ?String tid = UUID.randomUUID().toString().replace("-", "");
? ?// 客户端可以传入链路ID,需要唯一性
? ?String traceId = request.getHeader(TRACE_ID);
? ?if (!StringUtils.isEmpty(traceId)) {
? ? ?tid = request.getHeader(TRACE_ID);
? }
? ?// MDC(Mapped Diagnostic Context)诊断上下文映射,是@Slf4j提供的一个支持动态打印日志信息的工具
? ?MDC.put(TRACE_ID, tid);
? ?return true;
}
?
?@Override
?public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
? ?MDC.remove(TRACE_ID);
}
}自定义的拦截器需要实现HandlerInterceptor.java接口,然后重写preHandle方法;MDC(Mapped Diagnostic Context)诊断上下文映射,@Slf4j提供的动态打印日志工具。
1.5. 添加拦截器:WebConfigurerAdapter.java
@Configuration
public class WebConfigurerAdapter implements WebMvcConfigurer {
?
?@Bean
?public LogInterceptor logInterceptor() {
? ?return new LogInterceptor();
}
?
?@Override
?public void addInterceptors(InterceptorRegistry registry) {
? ?registry.addInterceptor(logInterceptor())
? ? ?// 自定义需要拦截的和不需要拦截的
? ? .addPathPatterns("/**")
? ? .excludePathPatterns("/test***.html");
?
}
}经过上述的几个步骤,基本上就可以简单的将同一次的业务调用链上的日志串联起来了。
2. 测试验证
简单的写一个测试类:TestController.java
@RestController
@Slf4j
public class TestController {
?
?@Resource(name = "userService")
?private IUserService userService;
?
?@PostMapping("/test")
?public String testTrace01(@RequestParam("name") final String name) {
? ?log.info("入参 name={}", name);
? ?testTrace02();
? ?log.info("调用结束name={}", name);
? ?return "Hello," + name;
}
}使用Postman调用接口:http://localhost:8080/test?name=张三
控制台的输出如下:

至此,一个最简单的日志串联就做好了
到此这篇关于SpringBoot实现简单的日志链路追踪的文章就介绍到这了,更多相关SpringBoot日志链路追踪内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
