Log4j 2架構

本文譯自:
http://logging.apache.org/log4j/2.x/maven-artifacts.html

詳細目錄
Apache Log4j 2 中文文檔

主要組件

Log4j 使用到了下圖中的類。

使用 Log4j 2 API 時,應用需要從 LogManager 處獲取一個有特定名字的 Logger。而 LogManager 則是查找出一個合理的 LoggerContext,並從中獲取到Logger。當 Logger 被創建時它將與 LoggerConfig 關聯,LoggerConfig 包含了要麼是當前 Logger 類路徑,要麼是母包路徑,要麼就是根LoggerConfig 。LoggerConfig 對象由 Logger 基於配置文件中的聲明來創建,它所關聯的 Appender 則用於傳遞 LogEvent 。

Logger 層次

相比於普通的System.out.println,日誌API最重要的優勢在於它可以在打印某些級別日誌的同時還能禁用某些級別的打印。這種能力使得開發者可以依照自己的標準來對日誌進行歸類。

在 Log4j 1.x 中 Logger 層次由 Logger 之間的關係來維持。然而在 Log4j 2 裏,這種關係已不復存在,取而代之的是由 LoggerConfig 對象來維護這一關係。

Logger 和 LoggerConfig 都被稱之爲實體,Logger 名大小寫敏感,並遵循層次命名規則:

命名層次
當我們說 LoggerConfig A 是 LoggerConfig B 的祖先時,這意味着A的名字加上“.”是B的名字的前綴。
當A與B之前沒有其他東西時,那麼A爲父LoggerConfig ,B爲子LoggerConfig 。

比如名爲 “com.foo”的 LoggerConfig 是名爲 “com.foo.Bar” 的 LoggerConfig 的父親。類似的, “java”是 “java.util” 的父親,是”java.util.Vector”的祖先。

根LoggerConfig 位於 LoggerConfig 層次的頂部,它始終存在。一個 Logger 可以通過以下方式與根LoggerConfig關聯:

Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

或者更簡單地:

Logger logger = LogManager.getRootLogger();

我們可通過爲靜態方法 LogManager.getLogger傳遞一個名字來獲得想要的 Logger。

LoggerContext

LoggerContext 在日誌系統中扮演着錨點的角色,然而依據不同的應用環境可能存在多個有效的LoggerContext,更多細節可查看 日誌隔離 章節。

Configuration

每一個 LoggerContext 都有一個有效的 Configuration, Configuration 包含所有的Appender 、Filter、LoggerConfig 以及StrSubstitutor引用。在修改配置後兩個 Configuration 對象會同時存在,一旦所有的 Logger 都已重定向到新的 Configuration上時,老的Configuration就會被停止並棄用。

Logger

Logger 繼承自 AbstractLogger 並實現了所需的方法。當配置被修改後,它將與不同的 LoggerConfig 相關聯,這導致其行爲也被改變。

獲取Logger

使用相同的名字調用 LogManager.getLogger方法將會的到相同的Logger。例如

Logger x = LogManager.getLogger("wombat");
Logger y = LogManager.getLogger("wombat");

其中x和y是同一個對象。

通常Logger名爲定義時的類限定名,這樣方便定位問題,但開發者仍可以按需自由定義所要的名字。鑑於前者爲人們約定俗成的規則,不帶參數調用LogManager.getLogger()將自動使用當前類的全限定名。

LoggerConfig

LoggerConfig 對象在 Logger 被聲明時創建,它包含了一組用於處理事件的Appender引用,以及一組用於過濾傳遞給Appender事件的Filter。

日誌級別

LoggerConfig會被分配一個日誌級別,內建的級別包含TRACE, DEBUG, INFO, WARN, ERROR 和 FATAL。Log4j 2 還支持自定義日誌級別,此外另一種可獲得更多粒度的方式便是使用Marker。

Log4j 1.x 和Logback 都使用了“級別繼承”的概念。在Log4j 2中Logger和LoggerConfig是兩個不同的對象,所以這種概念實現起來也有所不同。每個 Logger 引用到的 LoggerConfig 都帶有父輩的引用,這樣便可以達到相似的效果。

日誌級別的繼承就不細說了,大意就是如果X.Y.Z的級別未定義,那麼默認使用X.Y的LoggerConfig 的級別,如果X.Y也沒定義,那麼使用X的,一直到使用root的,根LoggerConfig的默認級別爲DEBUG。

Filter

Log4j 提供了Filter 來過濾消息事件,它可被應用於事件傳遞給LoggerConfig之前,及傳遞給LoggerConfig之後但在調用任一/特定Appender之前。類似於防火牆,Filter將返回三種結果: Accept, DenyNeutral。“接受”意味該事件不必再經過其他Filter,可直接被處理;“拒絕”意味着事件將立即被忽略,控制權返回給調用者;“中立”意味着事件應由其他Filter來處理。如果未配置任何Filter,那麼事件將直接被處理。

當事件被前置LoggerConfig Filter通過後,仍有可能被LoggerConfig Filter或Appender拒絕。

Appender

選擇性地啓用或禁用記錄請求的能力只是Log4j 的一部分功能,Log4j 還允許將記錄請求輸出到多個目標中,而這種輸出目標被稱爲Appender。目前appender的類型有控制檯、文件、遠程套接字服務器、Apache Flume、JMS、遠程UNIX 系統日誌守護進程以及各種數據庫API。更多細節可查看Appenders章節。此外,一個Logger可以關聯多個Appender。

通過addLoggerAppender方法可以爲Logger添加上Appender。如果符合Logger名字的LoggerConfig 還未被創建,那麼它將被自動創建,並關聯上Appender,然後所有的Logger(通常爲子類)都會被通知升級它們的LoggerConfig引用。

logger的每一個記錄請求都將被髮送到其所有appender中,同樣也會發送到父LoggerConfig的appender中。換句話說,Appender是依照LoggerConfig的層級關係附加繼承的。比如一個控制檯appender如果被加到了根logger中,那麼所有的記錄請求都會打印到控制檯。當然我們可以在配置文件中使用additivity="false"來禁用這種默認功能。

Layout

用戶往往不僅希望自定義輸出目標,還希望自定義輸出格式。這一功能由與Appender關聯的Layout來實現。Layout 負責對日誌事件進行格式化,而Appender 則負責將格式化後的輸出發送到指定位置。其中 PatternLayout 可以讓用戶使用類似C語言中printf的方式來進行格式化輸出。

比如,格式爲”%r [%t] %-5p %c - %m%n” 的 PatternLayout 將輸出:

176 [main] INFO  org.foo.Bar - Located nearest gas station.

Log4j 具有多種不同的Layout來滿足例如JSON、XML、HTML和Syslog等用戶場景。而其他的appender(如數據庫連接)需要填充特定的字段,而非特殊的文本結構。

同樣重要的是 log4j 可以根據用戶指定的規則來呈現日誌信息的內容。比如若你需要頻繁打印項目中的自定義對象,如Orange,那麼你可以創建一個OrangeMessage 來接收傳遞到 log4j 的 Orange 對象,它將被按要求格式化爲合適的字節數組。

StrSubstitutor 和 StrLookup

StrSubstitutor 類和 StrLookup 接口來自於 Apache Commons Lang,並被修改爲支持LogEvent的賦值。此外,來自 Apache Commons Configuration 的Interpolator類允許StrSubstitutor從多個 StrLookup中進行變量賦值。同時它們還提供了從系統屬性、配置文件、ThreadContext Map、LogEvent中的StructuredData 中讀取引用變量的機制。這些變量解析既可以發生在配置被處理時,也可以發生在事件被處理時。詳情請看LookUp

轉載請註明出處:http://blog.csdn.net/yangcheng33/article/details/78172526

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章