log4j-升級log4j2

common-logging

common-logging是apache提供的一個通用的日誌接口。用戶可以自由選擇第三方的日誌組件作爲具體實現,像log4j,或者jdk自帶的logging, common-logging會通過動態查找的機制,在程序運行時自動找出真正使用的日誌庫。當然,common-logging內部有一個Simple logger的簡單實現,但是功能很弱。所以使用common-logging,通常都是配合着log4j來使用。使用它的好處就是,代碼依賴是common-logging而非log4j, 避免了和具體的日誌方案直接耦合,在有必要時,可以更改日誌實現的第三方庫。

 

使用common-logging的常見代碼:
[java] view plain copy 
  1. import org.apache.commons.logging.Log;  
  2. import org.apache.commons.logging.LogFactory;  
  3.   
  4. public class A {  
  5.     private static Log logger = LogFactory.getLog(this.getClass());  
  6. }  
動態查找原理:Log 是一個接口聲明。LogFactory 的內部會去裝載具體的日誌系統,並獲得實現該Log 接口的實現類。LogFactory 內部裝載日誌系統的流程如下:
  1. 首先,尋找org.apache.commons.logging.LogFactory 屬性配置。
  2. 否則,利用JDK1.3 開始提供的service 發現機制,會掃描classpah 下的META-INF/services/org.apache.commons.logging.LogFactory文件,若找到則裝載裏面的配置,使用裏面的配置。
  3. 否則,從Classpath 裏尋找commons-logging.properties ,找到則根據裏面的配置加載。
  4. 否則,使用默認的配置:如果能找到Log4j 則默認使用log4j 實現,如果沒有則使用JDK14Logger 實現,再沒有則使用commons-logging 內部提供的SimpleLog 實現。
從上述加載流程來看,只要引入了log4j 並在classpath 配置了log4j.xml ,則commons-logging 就會使log4j 使用正常,而代碼裏不需要依賴任何log4j 的代碼。

slf4j

slf4j全稱爲Simple Logging Facade for JAVA,java簡單日誌門面。類似於Apache Common-Logging,是對不同日誌框架提供的一個門面封裝,可以在部署的時候不修改任何配置即可接入一種日誌實現方案。但是,他在編譯時靜態綁定真正的Log庫。使用SLF4J時,如果你需要使用某一種日誌實現,那麼你必須選擇正確的SLF4J的jar包的集合(各種橋接包)。

使用slf4j的常見代碼:

[java] view plain copy 
  1. import org.slf4j.Logger;  
  2. import org.slf4j.LoggerFactory;  
  3.   
  4. public class A {  
  5.     private static Log logger = LogFactory.getLog(this.getClass());  
  6. }  


slf4j靜態綁定原理:SLF4J 會在編譯時會綁定import org.slf4j.impl.StaticLoggerBinder; 該類裏面實現對具體日誌方案的綁定接入。任何一種基於slf4j 的實現都要有一個這個類。如:org.slf4j.slf4j-log4j12-1.5.6: 提供對 log4j 的一種適配實現。注意:如果有任意兩個實現slf4j 的包同時出現,那麼就可能出現問題。

 

slf4j 與 common-logging 比較

common-logging通過動態查找的機制,在程序運行時自動找出真正使用的日誌庫。由於它使用了ClassLoader尋找和載入底層的日誌庫, 導致了象OSGI這樣的框架無法正常工作,因爲OSGI的不同的插件使用自己的ClassLoader。 OSGI的這種機制保證了插件互相獨立,然而卻使Apache Common-Logging無法工作。

slf4j編譯時靜態綁定真正的Log庫,因此可以再OSGI中使用。另外,SLF4J 支持參數化的log字符串,避免了之前爲了減少字符串拼接的性能損耗而不得不寫的if(logger.isDebugEnable()),現在你可以直接寫:logger.debug(“current user is: {}”, user)。拼裝消息被推遲到了它能夠確定是不是要顯示這條消息的時候,但是獲取參數的代價並沒有倖免。

Log4j

Apache的一個開放源代碼項目,通過使用Log4j,我們可以控制日誌信息輸送的目的地是控制檯、文件、GUI組件、甚至是套接口服務 器、NT的事件記錄器、UNIX Syslog守護進程等;用戶也可以控制每一條日誌的輸出格式;通過定義每一條日誌信息的級別,用戶能夠更加細緻地控制日誌的生成過程。這些可以通過一個 配置文件來靈活地進行配置,而不需要修改程序代碼。

LogBack

Logback是由log4j創始人設計的又一個開源日記組件。logback當前分成三個模塊:logback-core,logback- classic和logback-access。logback-core是其它兩個模塊的基礎模塊。logback-classic是log4j的一個 改良版本。此外logback-classic完整實現SLF4J API使你可以很方便地更換成其它日記系統如log4j或JDK14 Logging。logback-access訪問模塊與Servlet容器集成提供通過Http來訪問日記的功能。 

Log4j 與 LogBack 比較

LogBack作爲一個通用可靠、快速靈活的日誌框架,將作爲Log4j的替代和SLF4J組成新的日誌系統的完整實現。LOGBack聲稱具有極佳的性能,“ 某些關鍵操作,比如判定是否記錄一條日誌語句的操作,其性能得到了顯著的提高。這個操作在LogBack中需要3納秒,而在Log4J中則需要30納秒。 LogBack創建記錄器(logger)的速度也更快:13微秒,而在Log4J中需要23微秒。更重要的是,它獲取已存在的記錄器只需94納秒,而 Log4J需要2234納秒,時間減少到了1/23。跟JUL相比的性能提高也是顯著的”。 另外,LOGBack的所有文檔是全面免費提供的,不象Log4J那樣只提供部分免費文檔而需要用戶去購買付費文檔。 


性能自測

slf4j-     count for   10000000 time   cosume  time:572159

log4j2     count for   10000000 time   cosume  time:566609

               count for   10000000time   cosume  time:520813


               

沒有控制檯輸出  count for   100000000  time   cosume  time:82587  

                                         count for   200000000time   cosume  time:168422

異步 

             count for   100000000time   cosume  time:81240

             count for   200000000time   cosume  time:166411

 

             沒有控制檯輸出     count for   100000000time   cosume  time:94931  沒加三方jar

             count for   10000000time   cosume  time:930125  沒加三方jar

              count for   10000000time   cosume  time:413857

 

異步log 大大提升io性能   可以全部異步 可部分異步

優點:

高吞吐量     使用異步io的性能的是同步io的68倍;

響應延遲很低比同步io

缺點:

有少量情況下會丟失異常信息

官方性能

 

 

 

接入步驟

 

1.刪除所有log4j slf4j   common-logging的相關jar包

列舉oms和switch-lib中刪除的包

<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>1.7.6</version>
</dependency>

<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>jcl-over-slf4j</artifactId>
 <version>1.7.6</version>
</dependency>
<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 <version>1.7.6</version>
</dependency>

<dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>1.2.15</version>
</dependency>
<dependency>
 <groupId>commons-logging</groupId>
 <artifactId>commons-logging</artifactId>
 <version>1.1</version>
</dependency>

2.添加mavan依賴

<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-api</artifactId>
 <version>2.6.2</version>
</dependency>
<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-core</artifactId>
 <version>2.6.2</version>
</dependency>
<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-slf4j-impl</artifactId>
 <version>2.6.2</version>
</dependency>

3.修改配置文件log4j和log4j2 配置文件需要生成一個新的配置名字爲log4j

  配置文件幾個區別詳情看文檔

http://logging.apache.org/log4j/2.x/manual/migration.html 

舉例下工程中的修改的小列子

log4j1的控制檯輸出

log4j2的控制檯輸出

然後把log4j1配置文件中  

改爲

 

 

4.統一使用slf4j配置log4j2的方式,刪除代碼中用到的其餘log組件代碼

統一用下列方式

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 private static final Logger  log = LoggerFactory.getLogger(LogConstants.SERVICE_LOG);

 

5.排除系統中所有包涵的slf4j-log4j12,本人是用eclipse的組件進行排除的,有其餘方法尚可

列覺排除過的包

<dependency>
 <groupId>com.meituan.mobile</groupId>
 <artifactId>hotel-switch-lib</artifactId>
 <version>1.0.1.68-SNAPSHOT</version>
 <exclusions>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 </exclusion>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-simple</artifactId>
 </exclusion>
 <exclusion>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-api</artifactId>
 </exclusion>
 </exclusions>
</dependency>

 

<dependency>
 <groupId>com.sankuai.xm</groupId>
 <artifactId>xm-pub-api-sdk</artifactId>
 <version>1.2-SNAPSHOT</version>
 <exclusions>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 </exclusion>
 </exclusions>
</dependency>

<dependency>
 <groupId>com.meituan.mobile</groupId>
 <artifactId>hotel-lib</artifactId>
 <version>1.5.7.4</version>
 <exclusions>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 </exclusion>
 </exclusions>
</dependency>

 

<dependency>
 <groupId>com.meituan.cache</groupId>
 <artifactId>redis-cluster-client</artifactId>
 <version>1.0.2.1</version>
 <exclusions>
 <exclusion>
 <groupId>com.alibaba.fastjson</groupId>
 <artifactId>fastjson</artifactId>
 </exclusion>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 </exclusion>
 </exclusions>
 <!-- 這裏請換成要使用的版本,正式發佈版本在1.0以上,目前僅有測試版本0.2 -->
</dependency>

 

 

 

小提示:一定要排出系統其餘依賴包中附帶的不同的log4j版本,如果出現多個版本會出現對版本綁定錯誤



qq交流羣:468246651  歡迎更多技術達人進羣討論技術一起成長
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章