• Log4j打印日志添加线程ID


    目的:

    区分每个请求用户,更好的跟踪分析问题(用户登录之后加上userId更佳)

    在进行多线程编程时,经常会在调试信息中看到线程的处理流程,需要在日志中体现当前线程信息。因Java中的线程名称采用了默认的“Thread-1”等字符串,定位不方便。

    分析:

    在JDK1.5开始对Thread类加入了getId()方法,即每个线程都有一个唯一的数字来代替。

    在记录日志时,是否可以通过记录线程ID来提升日志线程信息的清晰度?

    解决:

    Log4j默认只提供了对线程名称的现实,即使用占位符%t来显示名称。

    如果需要显示线程ID,需要拓展log4j。

    1.拓展Log4j的PatternParser

    代码:

    package org.apache.log4j;
     
    import org.apache.log4j.helpers.FormattingInfo;
    import org.apache.log4j.helpers.PatternConverter;
    import org.apache.log4j.helpers.PatternParser;
    import org.apache.log4j.spi.LoggingEvent;
     
    public class ExPatternParser extends PatternParser {
         
         public ExPatternParser(String pattern) {
           super(pattern);
          }
         
         /**
           * 重写finalizeConverter,对特定的占位符进行处理,T表示线程ID占位符
           */
          @Override
          protected void finalizeConverter(char c) {
           if (c == 'T') {
            this.addConverter(new ExPatternConverter(this.formattingInfo));
           } else {
            super.finalizeConverter(c);
           }
          }
         
         private static class ExPatternConverter extends PatternConverter {
         
          public ExPatternConverter(FormattingInfo fi) {
            super(fi);
           }
         
          /**
            * 当需要显示线程ID的时候,返回当前调用线程的ID
            */
           @Override
           protected String convert(LoggingEvent event) {
            return String.valueOf(Thread.currentThread().getId());
           }
        }
    }

      

    2.拓展PatternLayout类,使用拓展的ExPatternParser类

    代码:

    package org.apache.log4j;
     
    import org.apache.log4j.PatternLayout;
    import org.apache.log4j.helpers.PatternParser;
     
    public class ExPatternLayout extends PatternLayout {
         
         public ExPatternLayout(String pattern) {
           super(pattern);
          }
         
         public ExPatternLayout() {
           super();
          }
          
          /**
           * 重写createPatternParser方法,返回PatternParser的子类
           */
          @Override
          protected PatternParser createPatternParser(String pattern) {
           return new ExPatternParser(pattern);
          }
         }

    3.修改Log4j的配置文件,将输出样式修改为拓展类ExPatternLayout

    #设置输出样式  
    log4j.appender.appender1.layout=org.apache.log4j.ExPatternLayout  

    到此已经扩展完成,将以上内容编译后(可以打成jar包)和log4j.jar一同使用(使用同一个类装载器装载),然后配置log4j.properties类,修改

    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout


    log4j.appender.stdout.layout=ex.log4j.ExPatternLayout

    在输出格式中增加%T(log4j定义%t表示线程名称,%T没有定义,所以这里使用%T表示线程ID),

    log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %T %c %5p - %m%n

    下面就按照平常的习惯使用log4j即可,再输出的日志中就会包含线程ID,例如:

    2009-03-29 10:43:58 1 test.log.Log4jTest  INFO - ok

    时间后面的'1'就表示线程id,当在多线程环境下,例如web环境,用这种方式就能很容易区分出一次web请求过程中打印出的日志信息,而不会和其他web请求打印出的日志信息混淆。这样即增加的日志的可读性,也不会输出太多的无用信息。

    例子:

    log4j.appender.console.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] [%-3p] %x %c{1}:  %m%n

    [11:03:36.656] [INFO] [<T=U0Lg2h5HdGqMpvaS,U=9709677>] CommonWebFilter:  >>>>>>> Completed request[/omm/http/pss/text][360.86ms].

    4.运行程序。 

    demo可在资源区下载

  • 相关阅读:
    border-radius:50%和100%究竟有什么区别
    GoLang几种读文件方式的比较
    Golang Import使用入门
    golang: 常用数据类型底层结构分析
    Python--字典操作
    Python--字符串操作
    Python split 分割中文
    LR(逻辑回归)
    Python--列表操作
    Eclipse 使用Anaconda python 解释器
  • 原文地址:https://www.cnblogs.com/fanblogs/p/13501978.html
Copyright © 2020-2023  润新知