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可在資源區下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM