SpringBoot实现简单的日志链路追踪

2023年 9月 28日 21.3k 0

一. 背景

随着分布式应用的普及,现在的一些应用系统不再像以前,所有的文件(前后端程序)都打包在一个包中,现在的很多应用都是模块化开发,开发的团队也是不一样,服务与服务之间的调用也比较多,在这种情况下,系统的日志就显得尤其的重要,然而,在多数情况下,当我们的系统出现了异常,需要查看日志时,就会很抓狂。为了避免这种情况,我们需要把同一次的业务调用链上的日志串联起来。

本次通过一个简单的SpringBoot应用来总结,我们如何将日志串联起来,以下截图是最终的实现效果

日志链效果图.jpg

二. 代码演示

1. 创建一个SpringBoot项目

使用idea创建一个SpringBoot项目的详细步骤,本文不介绍了,具体的步骤,网上有很多例子可以参考

1.1. 我的SpringBoot项目名称是:springboot-track,以下是工程pom.xml文件中所需要的必要依赖


  
    org.springframework.boot
    spring-boot-starter-web
  
  
    org.springframework.boot
    spring-boot-starter-logging
  
​
  
    org.projectlombok
    lombok
    true
  
  
    org.springframework.boot
    spring-boot-starter-test
    test
  

1.2. 在项目的resource目录下,创建日志框架整合配置文件:logback-spring.xml文件内容配置如下:



  
  
  
  
    
      
      [%X{TRACE_ID}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
    
  
  
  
    
      
      ${log}/%d{yyyy-MM-dd}.log
      
      30
    
    
      [%X{TRACE_ID}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
    
    
    
      10MB
    
  
​
  
  
    
    
  

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=张三

控制台的输出如下:

日志效果图1.jpg

至此,一个最简单的日志串联就做好了

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论