閱讀520 返回首頁    go 技術社區[雲棲]


SLF4J 使用手冊

Java的簡單日誌門麵( Simple Logging Facade for Java  SLF4J)作為一個簡單的門麵或抽象,用來服務於各種各樣的日誌框架,比如java.util.logging、logback和log4j。SLF4J允許最終用戶在部署時集成自己想要的日誌框架。
需要注意的是,你的應用啟用SLF4J意味著需要一個額外的依賴:slf4j-api-1.7.19.jar

從1.6.0開始:如果在class path沒有找到綁定,SLF4J將默認一個無操作的實現。

從1.7.0開始:Logger接口中的打印方法現在提供variants取代了Object[]用來接收可變長參數。這個改變意味著SLF4J需要JDK 1.5或更高的版本。Java編譯器在底層把方法中的可變參數部分轉換成Object[]。因此,編譯器生成的Logger接口在1.7.x版本中和它對應的的1.6.x版本中是沒有區別的。因此SLF4J得1.7.x版本和1.6.x版本是 完全兼容的。

從1.7.5開始:日誌的檢索時間有了一個顯著的改善,鑒於這個改善,非常鼓勵用戶遷移到SLF4J 1.7.5或更高的版本。

從1.7.9開始: 通過設置  slf4j.detectLoggerNameMismatch 係統屬性為true,SLF4J能自動的  spot incorrectly named loggers.

Hello World

按照慣例,下麵的示例說明最簡單的方法使用SLF4J輸出”hello world“。他首先獲取一個名為”HelloWorld“的記錄器,這個記錄器用來記錄”HelloWorld“。
1 import org.slf4j.Logger;
2 import org.slf4j.LoggerFactory;
3  
4 public class HelloWorld {
5   public static void main(String[] args) {
6     Logger logger = LoggerFactory.getLogger(HelloWorld.class);
7     logger.info("Hello World");
8   }
9 }

運行這個示例,首先你需要下載slf4j發行版 download the slf4j distribution,然後解壓。做完這些之後,把 slf4j-api-1.7.19.jar添加到你的class path。

編譯運行HelloWorld,控製台將有一下輸出:

 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
 SLF4J: Defaulting to no-operation (NOP) logger implementation
 SLF4J: See https://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

這個警告會被打印是因為在class path下沒有找到綁定的slf4j。

一旦你添加一個綁定在你的class path下,這個警告將會消失。假設你添加了 slf4j-simple-1.7.19.jar,你的class path包含:

  • slf4j-api-1.7.19.jar
  • slf4j-simple-1.7.19.jar

編譯並運行HelloWorld程序,現在在控製台會有下列輸出:

 0 [main] INFO HelloWorld - Hello World

典型使用模式

下麵的示例代碼表明了SLF4J的典型使用模式。注意15行”{}“的使用,查看  “What is the fastest way of logging?”獲取更多細節。

  1: import org.slf4j.Logger;
  2: import org.slf4j.LoggerFactory;
  3: 
  4: public class Wombat {
  5: 
  6:   final Logger logger = LoggerFactory.getLogger(Wombat.class);
  7:   Integer t;
  8:   Integer oldT;
  9:
10:   public void setTemperature(Integer temperature) {
11:   
 12:     oldT = t;       
 13:     t = temperature;
14:
15:     logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
16:
17:     if(temperature.intValue() > 50) {
18:       logger.info("Temperature has risen above 50 degrees.");
19:     }
20:   }
21: }

在部署時綁定一個日誌框架

像在之前提到過的,SLF4J支持各種各樣的日誌框架。SLF4J的發行版附帶的幾個jar被稱為” SLF4J bindings“ ,每個綁定都對應一個支持的框架。


slf4j-log4j12-1.7.19.jar

綁定  log4j version 1.2,一個廣泛使用的日誌框架,你也需要在class path放置  log4j.jar


slf4j-jdk14-1.7.19.jar

綁定 java.util.logging,也被稱為JDK 1.4 日誌。


slf4j-nop-1.7.19.jar

綁定 NOP,默默地打出所有的日誌。


slf4j-simple-1.7.19.jar

綁定  Simple實現,輸出所有的System.err事件,隻有INFO和更高級別的信息會被打印。這個綁定或許 在小應用程序的上下文中非常有用。


logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)

本地實現:也有SLF4J的綁定在SLF4J項目之外,比如  logback 在本地實現了SLF4J。Logback的 ch.qos.logback.classic.Logger 類直接實現了SLF4J的  org.slf4j.Logger接口。因此,和logback一起使用SLF4J涉及到嚴格零內存和計算開銷。
切換日誌框架,隻需要替換class path中的slf4j綁定。比如說,從  java.util.logging切換到 log4j,僅僅把  slf4j-jdk14-1.7.19.jar替換成 slf4j-log4j12-1.7.19.jar。

SLF4J不依賴於特定的類加載機製。事實上,每個SLF4J綁定在編譯時硬連接來使用一個指定的日誌框架。比如說, slf4j-log4j12-1.7.19.jar在編譯時綁定使用log4j。在你的代碼中,除  slf4j-api-1.7.19.jar之外,隻能有一個你選擇的綁定 到正確的class path 路徑上。不要在class path 放置多個綁定。下麵是一個圖表來說明一般的想法。

s

SLF4J接口和他們的各種各樣的適配器非常簡單。大多數熟悉Java語言的開發者應該能在一小時之內讀懂代碼。不需要類加載的知識。因此,SLF4J沒有遭受類加載問題或者 Jakarta Commons Logging (JCL)觀察到的內存泄露問題。

鑒於SLF4J接口的簡單性和它的部署模型,新的日誌框架開發者應該覺得很容易編寫SLF4J綁定。

為了避免給他們的終端用戶強加一個日誌框架 ,一些組件和庫的作者可能會針對SLF4J接口進行編程。因此,終端用戶在部署時可以通過在classpath插入對應的slf4j綁定來選擇他們期望的日誌框架。並且,可以把在classpath存在的綁定替 換到另外一個,然後重啟應用,從而達到切換日誌框架的目的,這個方法被證明是非常簡單和健壯的。

SLF4J的1.6.0版本,如果在class path 沒有發現綁定,slf4j-api將默認一個無操作的實現來忽略所有的日誌請求。因此,SLF4J從1.6.0版開始發出一個缺少綁定的警告,然後丟棄所有的打印日誌請求,而不是拋出 NoClassDefFoundError異 常因為缺少 org.slf4j.impl.StaticLoggerBinder 類 。比如說: Wombat 一些基礎框架依賴於SLF4J來打印日誌。為了避免強加一個日誌框架給終端用戶,Wombat  包含  slf4j-api.jar但是沒有綁定。在class path 沒有SLF4J綁定的情 況下,Wombat的發行版依然能開箱即用,不需要終端用戶下載從SLF4J網站下載一個綁定。僅僅當終端用戶開啟日誌的時候,將需要安裝他選擇的日誌框架對應的SLF4J綁定。

基本準則:內置的組件比如庫和框架不應該聲明任何SLF4J的依賴,但是依賴於SLF4J-api。當一個庫在一個指定的綁定聲明一個傳遞依賴,這個強加於終端用戶的綁定否定了SLF4J的目的。注意,在綁定上聲明一個非傳遞性的依賴,比如說 對測試,不影響終端用戶。

內嵌組件中SLF4J的使用也在FAQ中進行討論。有關係的章節:  logging configuration    dependency reduction   testing

聲明項目的日誌依賴

鑒於Maven的傳遞依賴規則,對於”regular“項目(不是庫和框架),日誌依賴聲明 可以通過一個單獨的依賴聲明來實現。

LOGBACK-CLASSIC: 如果你希望使用 logback-classic 作為底層的日誌框架,你需要做的所有事情就是聲明” ch.qos.logback:logback-classic“依賴到你的pom.xml文件中。除了 logback-classic-1.0.13.jar之外,它將拉取 slf4j-api-1.7.19.jar和 logback-core-1.0.13.jar 到你的項目中。注意,顯式的聲明  logback-core-1.0.13或  slf4j-api-1.7.19.jar 沒有錯,並且可能需要強加一個正確的版本。

1 <dependency>
2   <groupId>ch.qos.logback</groupId>
3   <artifactId>logback-classic</artifactId>
4   <version>1.0.13</version>
5 </dependency>

LOG4J:如果你希望使用log4j作為底層的日誌框架,你需要做的所有事情就是聲明” org.slf4j:slf4j-log4j12“依賴到你的pom.xml文件中。除了 slf4j-log4j12-1.7.19.jar之外,它將拉取 slf4j-api-1.7.19.jar和  log4j-1.2.17.jar到你的項目 中。注意,顯示地聲明一個依賴  log4j-1.2.17.jar或 slf4j-api-1.7.19.jar 沒有錯。並且可能需要強加一個正確的版本

1 <dependency>
2   <groupId>org.slf4j</groupId>
3   <artifactId>slf4j-log4j12</artifactId>
4   <version>1.7.19</version>
5 </dependency>

JAVA.UTIL.LOGGING:如果你希望使用  java.util.logging 作為底層的日誌框架,你需要做的所有事情就是聲明” org.slf4j:slf4j-jdk14“依賴到你的pom.xml文件中。除了 slf4j-jdk14-1.7.19.jar之外,它將拉取  slf4j-api-1.7.19.jar到你 的項目中。注意,顯示地聲明一個依賴  slf4j-api-1.7.19.jar  沒有錯。並且可能需要強加一個正確的版本。

1 <dependency>
2   <groupId>org.slf4j</groupId>
3   <artifactId>slf4j-jdk14</artifactId>
4   <version>1.7.19</version>
5 </dependency>

二進製兼容

一個SLF4J綁定指定一個具體的依賴用來在底層日誌框架綁定slf4j,比如說 slf4j-jdk14.jar或 slf4j-log4j12.jar

不同版本的 slf4j-api.jar和SLF4J綁定混合在一起可能會引起問題。比如說,如果你使用  slf4j-api-1.7.19.jar,然後你應該使用 slf4j-simple-1.7.19.jar,使用 slf4j-simple-1.5.5.jar將不會正常工作。

然而,從客戶端的觀點來看,所有版本的 slf4j-api都是兼容的。使用 slf4j-api-N.jar編譯的客戶端代將和  slf4j-api-M.jar一起完美運行,N和M都是任意的。你僅僅需要確保你綁定的版本和 slf4j-api.jar 匹配。你不需要擔心項目中給定的依 賴的slf4j-api.jar的版本。你可以使用任何版本的 slf4j-api.jar,隻要 slf4j-api.jar的版本和它的綁定匹配,就不會有問題。

在初始化的時間,如果SLF4J懷疑可能有不匹配問題。將會發出關於不匹配的警告信息。

通過SLF4J統一日誌

通常,一個給定的項目依賴於各種各樣的組件,這些組件依賴的日誌API不是SLF4J。一個項目依賴於一個JCL、java.util.logging、log4j和SLF4J是很常見的。然後通過一個單獨的方式來統一日誌變得讓人滿意。SLF4J通過提供對JCL、

java.util.logging、和slf4j的橋接模塊來滿足這個普通的用例。更詳細的內容,請參考 Bridging legacy APIs.

MDC支持

“Mapped Diagnostic Context”本質上是日誌框架包含的一個map,應用程序代碼提供了key-value對,這個鍵值對能被日誌框架插入到日誌信息中去。MDC數據在過濾信息或觸發某些操作時是非常有用的。

SLF4J支持MDC,如果一個底層的日誌框架提供了MDC功能,SLF4J將委托給底層日誌框架的MDC。注意,現在僅僅隻有log4j和logback提供了MDC功能。如果底層日誌框架不支持MDC,比如說java.util.loggin,SLF4J將存儲MDC數 據,但是裏麵的數據需要用戶通過代碼來獲取。

因此,作為一個SLF4J使用者,能利用當 log4j和logback存在時的 MDC信息,但是不能強迫用戶依賴這些日誌框架。

關於MDC的更多信息參見 chapter on MDC

行動綱要

Advantage Description
在部署時候選擇日誌框架 通過在class path插入合適的jar,期望的日誌框架能在部署時集成。
快速失敗操作 由於虛擬機加載類的方式,很早就自動驗證框架綁定。如果SLF4J沒有在class path 發現一個綁定,它將會發出一個警告信息,並且默認一個無操作的實現。
綁定流行的日誌框架 SLF4J支持流行的日誌框架,log4J、java.util.logging、Simple logging和NOP。  logback天生支持SLF4J。
橋接遺留的logging APIs 通過SLF4J實現JCL,如  jcl-over-slf4j.jar,將允許項目遷移到SLF4J,沒有破壞使用JCL的軟件的兼容性。同樣的,  log4j-over-slf4j.jar 和  jul-to-slf4j模塊重定向log4j到SLF4J。查看             Bridging legacy APIs 獲取更多信息
移動你的源碼 slf4j-migrator工具能幫助你遷移你的代碼來使用SLF4J。
支持參數化的日誌信息 所有的SLF4J綁定支持參數化的日誌信息。並且可以顯著提高性能。 improved performance

 

最後更新:2017-05-19 17:02:24

  上一篇:go  《雲數據管理:挑戰與機遇》 簡介
  下一篇:go  沙龍報名啦:頂級架構師為您講述企業互聯網架構優化升級之路(阿裏雲授權中心沙龍計劃)