log4j2配置一次请求的logId,子线程获取父线程数据

前言:在服务端排查日志时,想查看一次接口请求的完整日志,而不受其他其他日志干扰,可以在log4j中添加request维度的logId来实现过滤。

目录

1、如何添加logId

2、子线程如何获取logId


1、如何添加logId

log4j提供了很多常用的API功能接口,其中包括ThreadContext。顾名思义这是一个日志上下文,那我们猜想在日志入口加入的数据下文可以使用,也即在请求入口加入的数据,请求处理过程中,日志线程可以使用。ThreadContext本质是一个map或stack。官网这样说:

The Stack and the Map are managed per thread and are based on ThreadLocal by default.  

其实就是基于ThreadLoacl实现,感兴趣的同学可以自行看源码拓展学习。大家可以思考一下又了这个“日志线程上下文”我们可以做些什么以实现每次请求的日志识别?很简单当然是加标识!

@Component
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 日志id
        ThreadContext.put("logId", UuidUtil.getTimeBasedUuid().toString());
        return true;
    }
}

配置spring的拦截器,在ThreadContext中加入logId。然后呢再在log4j2的配置的pattern中加入%X{logId}

    <Properties>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss,SSS} %X{logId} %5p %c{1}:%L - %m%n</Property>
    </Properties>

添加测试接口

@GetMapping("testLogId")
    public String testLogId() {
        log.info("test");
        return "ok";
    }

输出结果,标黄为logId:

2022-10-19 15:47:50,959 550b4c61-4f82-11ed-b02a-5ec48148ecef  INFO HealthController:16 - test

2、子线程如何获取logId

好像大功告成,可是等等上面提到ThreadContext实现基于ThreadLocal,当前输出没问题,那子线程呢?测试试一下!

    @GetMapping("testLogId")
    public String testLogId() {
        log.info("test");
        new Thread(() -> {
            log.info("sub thead!");
        }).start();
        return "ok";
    }

结果应该在意料之中:

2022-10-19 15:53:56,969 2f3361c1-4f83-11ed-9d3d-5ec48148ecef  INFO HealthController:16 - test
2022-10-19 15:53:56,970   INFO HealthController:18 - sub thead!

查资料得知log4j提供了很多系统参数

其中包括 log4j2.isThreadContextMapInheritable

log4j2.isThreadContextMapInheritable
(isThreadContextMapInheritable)
LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLEfalse

 isThreadContextMapInheritable顾名思义ThreadContext是否可“遗传”。配置为true即可,有四种配置的方式:

SourcePriorityDescription
Spring Boot Properties-100This property source is enabled only if the Java application uses Spring Boot and the log4j-spring module is present. It resolves properties using a Spring Environment.
System Properties0All properties can be set using normal system property patterns. 
Environment Variables100Environment variables are all prefixed with LOG4J_, are in all caps, and words are all separated by underscores. 
log4j2.component.properties file200Including this file on the classpath can be used as an alternative to providing properties as system properties. 

我测试了其中的两种System Properties,Environment Variables。

//system 加在JAVA_OPTS 系统变量里
-Dlog4j2.isThreadContextMapInheritable=true

//environment 加在代码里
static {
        System.setProperty("LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLE", "true");
}

 结果如下:

2022-10-19 16:13:17,490 e2edbfb1-4f85-11ed-b003-5ec48148ecef  INFO HealthController:16 - test
2022-10-19 16:13:17,490 e2edbfb1-4f85-11ed-b003-5ec48148ecef  INFO HealthController:18 - sub thead!

总结一下如果添加一次请求维度的logId: 

  1. 添加接口拦截器。
  2. 拦截器里ThreadContext加入logId。
  3. log4j2.xml中pattern加入%X{logId}
  4. 配置系统参数log4j2.isThreadContextMapInheritable为true。

参考:

Log4j – Configuring Log4j 2

Log4j – Log4j 2 API

转载注明来源❤️

个人网站:www.sanjie.site

个人微信公众号:叁戒

网站ai、游戏、摸鱼等板块,欢迎学习ai和玩游戏,有任何问题网站或公众号留言,欢迎交流沟通

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值