日志traceId追踪

文章目录

背景

在定位问题时,我们希望通过grep traceId=xxx *.log快速的过滤出某次请求的所有日志。

MDC简介

SLF4J日志框架提供了一个MDC(Mapped Diagnostic Contexts)工具类
MDC可以帮我们记录追踪日志的功能,它支持 Log4JLogBack 两种日志框架,通常打印出的日志会有线程号等信息来标志当前日志属于哪个线程。
使用日志控件提供的MDC功能,生成一个唯一序列标记一个线程的日志。

MDC原理简介
MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。
MDC 中包含的内容可以被同一线程中执行的代码所访问。
当需要记录日志时,只需要从 MDC 中获取所需的信息即可。 配置好日志格式即可打印带有traceId的日志如:

2024-04-04 20:37:05.572 [main] [traceId=dab8412a-f070-4406-9940-89fcdbd3473f] DEBUG com.example.mdc.mdc.Main - log in main thread 1
2024-04-04 20:37:05.572 [main] [traceId=dab8412a-f070-4406-9940-89fcdbd3473f] DEBUG com.example.mdc.mdc.Main - log in main thread 2
2024-04-04 20:37:05.572 [main] [traceId=dab8412a-f070-4406-9940-89fcdbd3473f] DEBUG com.example.mdc.mdc.Main - log in main thread 3

MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。
服务之间的调用,则需要上层服务在 header 中添加标识同请求一起传输过来。下层服务直接使用上层服务的标识,就可以将日志串联起来。

有了MDC工具,只要在过滤器/拦截器/接口切面植入MDC.put("traceId", traceId)MDC.remove("traceId")
代码。

新增一个过滤器,检查请求的请求头是否有traceId信息,有直接用,没有就生成一个traceId。

Logback日志
LogbackMDCAdapter implements MDCAdapter
数据读写都是基于ThreadLocal。

MDC的局限性
● 父子线程数据无法传递
● 线程池使用MDC存在数据传递重复

阿里巴巴开源的transmittable-thread-local解决了以上2个问题,

其解决思路:
1、针对父子线程数据无法传递问题,TransmittableThreadLocal继承并加强InheritableThreadLocal类;2、针对线程池InheritableThreadLocal数据数据传递存在重复问题,TransmittableThreadLocal提供了TtlRunnable和TtlCallable来修饰提交到线程池的任务,保证每次任务执行前强制从父线程copy下ThreadLocalMap的最新的值。

使用TtlMDCAdapter,整合TransmittableThreadLocal的能力并直接实现MDCAdapter接口

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值