SpringBoot中除了常见的分布式链路跟踪系统zipkin、skywalking等,如果需要快速定位一次请求的所有日志,那么该如何实现?实际slf4j提供了MDC(Mapped Diagnostic Contexts)功能,支持用户定义和修改日志的输出格式以及内容。本文将介绍 Tracer集成的slf4j MDC功能,方便用户在只简单修改日志配置文件的前提下输出当前 Tracer 上下文 TraceId。
MDC介绍
MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 、logback及log4j2 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。
springboot中如何使用
添加拦截器
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String tid = UUID.randomUUID().toString().replace("-", "");
MDC.put(CloudConstant.MDC_TRACE, tid);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
MDC.remove(CloudConstant.MDC_TRACE);
}
}
注册拦截器
@Configuration
public class WebInterceptorAdapter implements WebMvcConfigurer {
@Bean
public LogInterceptor logInterceptor() {
return new LogInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor());
}
}
修改日志输出格式,添加%X{traceId},traceId和MDC中的键名称一致
<pattern>%date %-5level ${PID:- } [%thread] [%X{tid}] : %n</pattern>
添加一个controller调用测试
@RestController
@RequestMapping("trace")
@Slf4j
public class TestTraceController {
@GetMapping("traceLog")
public String traceLog() {
log.info("---接口调用了---");
traceService();
return "success";
}
private void traceService(){
log.error("## 执行traceService方法");
}
}
日志打印如下,我们可以通过traceId快速查找出同一个请求的所有日志
细心的同学就会发现,MDC还是存在一些问题
- 在子线程中打印日志丢失traceId
- HTTP调用丢失traceId
在下一篇文章中小编继续讲解子线程中如何实现traceId的日志跟踪
到此这篇关于SpringBoot+slf4j实现全链路调用日志跟踪 一的文章就介绍到这了,更多相关SpringBoot全链路调用日志跟踪内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!