• SpringBoot+slf4j实现全链路调用日志跟踪 一


    关注作者公众号【互联网专栏】获取本项目源码

    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}] : /*[%logger{50}:%line] %msg*/%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的日志跟踪

  • 相关阅读:
    eclipse下对中文乱码问题的一些思考
    项目已经部署,tomcat已经启动,网址也没问题,却出现404错误
    The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
    java.lang.ClassCastException: $Proxy0 cannot be cast to javax.servlet.ServletRequestWrapper
    java 线程之-volatile
    带备注的 config
    带备注的 头文件加载文件
    带个人备注的,模板->编译文件->缓存文件
    错过一个订单后,吐槽下自己(顺便分享下书单),剧终版
    错过一个订单后,吐槽下自己(顺便分享下书单),欢迎交流
  • 原文地址:https://www.cnblogs.com/kevin-ying/p/14483171.html
Copyright © 2020-2023  润新知