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


    MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j、 logback及 log4j2提供的一种方便在多线程条件下记录日志的功能,基于ThreadLocal实现的一种工具类。

    1、新增拦截器,统一处理trace问题(Constant.TRACE_ID = "traceId")

    先看MDC是否存在 traceId,有则不作处理,没有时再看header里是否有 traceId,没有的话则新生成并放置在MDC中,能解决接口请求,第三方调用,异步方法执行等场景,但线程存在丢失的情况

    1. @Component
    2. public class TraceIdInterceptor implements HandlerInterceptor {
    3. /**
    4. * 确保MDC有traceId
    5. * @param request
    6. * @param response
    7. * @param handler
    8. * @return
    9. * @throws Exception
    10. */
    11. @Override
    12. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    13. //如果有上层调用就用上层的ID
    14. String mdcTraceId = MDC.get(Constant.TRACE_ID);
    15. //MDC有traceId,直接返回
    16. if (StringUtils.isNotBlank(mdcTraceId)) {
    17. return true;
    18. }
    19. String headerTraceId = request.getHeader(Constant.TRACE_ID);
    20. //MDC没有traceId,从header取
    21. if (StringUtils.isNotBlank(headerTraceId)) {
    22. MDC.put(Constant.TRACE_ID, headerTraceId);
    23. return true;
    24. }
    25. //MDC、Header都没有则新生成
    26. MDC.put(Constant.TRACE_ID, TraceIdUtil.getTraceId());
    27. return true;
    28. }
    29. @Override
    30. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    31. throws Exception {
    32. }
    33. @Override
    34. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    35. throws Exception {
    36. //调用结束后删除
    37. MDC.remove(Constant.TRACE_ID);
    38. }
    39. }
    1. public class TraceIdUtil {
    2. public static String getTraceId () {
    3. return UUID.randomUUID().toString().replaceAll("-", "");
    4. }
    5. }

    2、

    1. @PostMapping("/pageList")
    2. public Object list (@RequestBody ProductPage productPage) {
    3. IPage<Product> result = productService.pageList(productPage);
    4. final ResponsePage<Product> responsePage = new ResponsePage<>();
    5. BeanUtils.copyProperties(result, responsePage);
    6. //异步方法
    7. for (int i = 0; i < 2; i++) {
    8. new Asy().print(i);
    9. }
    10. HttpRequestUtil.doPost("http://127.0.0.1:9009/product/category/detail/1562264184600199170", MDC.get(Constant.TRACE_ID), new HashMap<>(), null);
    11. HttpHeaders headers = new HttpHeaders();
    12. headers.add("traceId", MDC.get(Constant.TRACE_ID));
    13. HttpEntity<String> requst = new HttpEntity<>(null, headers);
    14. RestTemplate restTemplate = new RestTemplate();
    15. restTemplate.postForObject("http://127.0.0.1:9009/product/category/detail/1562265011976994817", requst, Object.class);
    16. }
    17. @Slf4j
    18. @Async
    19. class Asy {
    20. public void print (int i) {
    21. try {
    22. Thread.sleep(1000L);
    23. log.info("异步 " + i);
    24. } catch (InterruptedException e) {
    25. e.printStackTrace();
    26. }
    27. }
    28. }

    3、日志打印格式设置:%X{traceId}

    1. "CONSOLE_LOG_PATTERN"
    2. value="[${ServerIP}:${ServerPort}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr([traceId:%X{traceId}]){yellow} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
    3. "CONSOLE_LOG_PATTERN_NO_COLOR" value="[${APP_NAME}:${ServerIP}:${ServerPort}] %d{yyyy-MM-dd HH:mm:ss.SSS} %level [traceId:%X{traceId}] [%thread] %logger %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />

    //使用线程池时,traceId将会丢失

  • 相关阅读:
    机器人工程是否有红利期
    药师帮再冲刺上市:研发远低于营销,债务高企,张步镇为董事长
    ZZULIOJ:1158: 又是排序(指针专题)
    你的团队工作量饱和吗?
    自私型人格分析,如何改变自私型性格?
    vue3个人网站电子宠物
    如何在IDEA中设置字体随鼠标放大缩小
    嵌入式人工智能ESP32(4-PWM呼吸灯)
    Go语言关于协程何时退出的问题
    为什么说程序员是一个极度劳累的工作?
  • 原文地址:https://blog.csdn.net/u012843873/article/details/126665096