log4j與log4j不同:log4j是通過Logger的靜態方法getLogger()獲取Logger對象,而log4j2是通過LogManager的靜態方法getLogger()獲取Logger對象。
log4j2配置系列之1
1. log4j2原理

使用log4j 2 api的應用程序將從LogManager請求具有特定名稱的記錄器。LogManager將找到適當的LoggerContext,然后從中獲取記錄器。如果必須創建記錄器,它將與LoggerConfig關聯,loggerconfig包含a)與記錄器相同的名稱,b)父包的名稱,或c)根LoggerConfig。LoggerConfig對象是從配置中的記錄器聲明創建的。LoggerConfig與實際傳遞logevents的appender相關聯。
2.logger等級制度
與普通的system.out.println相比,任何日志api的首要優勢在於它能夠禁用某些日志語句,同時允許其他人不受阻礙地打印。此功能假定日志空間(即所有可能的日志語句的空間)是根據某些開發人員選擇的條件進行分類的。在log4j 1.x中,記錄器層次結構是通過記錄器之間的關系來維護的。在log4j 2中,這種關系不再存在。相反,層次結構是在loggerconfig對象之間的關系中維護的。
loggers和loggerconfigs是命名實體。記錄器名稱區分大小寫,並遵循分層命名規則:
Nameed HierchaHierarchy
A LoggerConfig is said to be an ancestor of another LoggerConfig if its name followed by a dot is a prefix of the descendant logger name.
A LoggerConfig is said to be a parent of a child LoggerConfig if there are no ancestors between itself and the descendant LoggerConfig.
For example, the LoggerConfig named "com.foo" is a parent of the LoggerConfig named"com.foo.Bar".
Root LoggerConfig位於LoggerConfig層次結構的頂部。它是例外,因為它總是存在的,它是每一個層次的一部分。直接鏈接到root LoggerConfig的記錄器可以按如下方式獲取:
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
還有更簡單的一種獲取方式:
Logger logger = LogManager.getRootLogger();
對於所有其他類型的記錄器,可以通過LogManager的靜態方法getLogger獲取。具體用法請查閱log4j2 API。
3.LoggerContext
loggercontext充當日志系統的定位點。但是,根據具體情況,應用程序中可能有多個活動loggercontext。有關loggercontext的更多詳細信息,請參閱日志分離部分。
4.Configuration
每個loggercontext都有一個活動配置。配置包含所有的appender、上下文范圍的Filters、loggerconfigs和對strsubstitutor的引用。在重新配置期間,將存在兩個配置對象。一旦所有的記錄器被重定向到新配置,舊配置將被停止並丟棄。
5.Logger
如前所述,通過調用logmanager.getlogger創建記錄器。記錄器本身不執行任何直接操作。它只是有一個名稱,並且與loggerconfig相關聯。它擴展了AbstractLogger並實現了所需的方法。當配置被修改時,記錄器可能與不同的loggerconfig相關聯,從而導致其行為被修改。
例如:x和y引用確切的指向相同的Logger對象。
Logger x = LogManager.getLogger("wombat");
Logger y = LogManager.getLogger("wombat");
log4j環境的配置通常在應用程序初始化時完成。首選方法是讀取配置文件。
log4j使按軟件組件命名記錄器變得很容易。這可以通過在每個類中實例化記錄器來實現,記錄器名稱等於類的完全限定名。這是定義記錄器的一種有用而直接的方法。由於日志輸出帶有生成日志的名稱,此命名策略使識別日志消息的來源變得容易。然而,這只是一種可能的(盡管很常見)命名記錄器的策略。log4j不限制可能的記錄器集。開發人員可以根據需要自由命名記錄器。由於以擁有的類命名日志記錄器是一種常見的習慣用法,因此提供了方便的方法LogManager.getLogger()來自動使用調用類的完全限定類名作為日志記錄器名稱。不過,以日志記錄器所在的類命名日志記錄器似乎是目前已知的最佳策略。
6.LoggerConfig
loggerconfig對象是在日志配置中聲明日志記錄器時創建的。loggerconfig包含一組篩選器,這些篩選器必須允許logevent在傳遞給任何附加程序之前進行傳遞。它包含對應用於處理事件的附加程序集的引用。
6.1 log levels
loggerConfigs將被分配一個日志級別。內置級別集包括trace、debug、info、warn、error和fatal。log4j 2還支持自定義日志級別。另一種獲得更多粒度的機制是使用標記。
log4j 1.x和logback都有“級別繼承”的概念。在log4j 2中,loggers和loggerconfigs是兩個不同的對象,所以這個概念的實現方式不同。每個記錄器都引用適當的loggerconfig。
7.Filter
除了如前一節所述進行的自動日志級篩選之外,log4j還提供了可以在控件傳遞給任何LoggerConfig之前、控件傳遞給LoggerConfig之后、調用任何appender之前、控件傳遞給l之后應用的篩選器。但在調用特定的appender之前,以及在每個appender上。以一種與防火牆過濾器非常相似的方式,每個過濾器可以返回三個結果之一,接受、拒絕或中立。accept的響應表示不應調用其他篩選器,事件應繼續。拒絕響應意味着應該立即忽略該事件,並將控制權返回給調用方。中性響應表示該事件應傳遞給其他篩選器。如果沒有其他篩選器,則將處理事件。
雖然篩選器可以接受事件,但仍可能不記錄該事件。當事件被預loggerconfig篩選器接受,但隨后被loggerconfig篩選器拒絕或被所有附加程序拒絕時,可能會發生這種情況。
8.appender
基於日志記錄程序有選擇地啟用或禁用日志記錄請求的能力只是圖片的一部分。log4j允許將日志記錄請求打印到多個目的地。在log4j speak中,輸出目的地稱為appender。目前,控制台、文件、遠程套接字服務器、apache flume、jms、遠程unix syslog守護進程和各種數據庫api都有附加程序。有關可用的各種類型的詳細信息,請參閱附錄部分。一個記錄器可以連接多個附加程序。
可以通過調用當前配置的addLoggerAppender方法將追加程序添加到記錄器。如果與記錄器名稱匹配的loggerconfig不存在,將創建一個loggerconfig,附加程序將附加到它,然后通知所有記錄器更新其loggerconfig引用。
為給定記錄器啟用的每個日志記錄請求都將轉發給該記錄器的loggerconfig中的所有附加程序以及loggerconfig父級的附加程序。換句話說,appender是從loggerconfig層次結構中附加繼承的。例如,如果將控制台附加程序添加到根日志記錄器,則所有啟用的日志記錄請求將至少在控制台上打印。如果另外在loggerconfig(比如c)中添加了一個文件追加器,那么對c和c的子級啟用的日志記錄請求將在文件和控制台中打印。可以重寫此默認行為,以便通過在配置文件中的記錄器聲明上設置additivity=“false”,不再對appender累加。
關於appender可加性的規則總結如下。
8.log4j 1.x Migration
1.Using the Log4j 1.x bridge
也許最簡單的轉換為使用log4j 2的方法是用log4j2的log4j-1.2-api.jar替換log4j 1.xjar文件。但是,要成功使用此應用程序,必須滿足以下要求:
1.它們不能訪問log4j 1.x實現內部的方法和類,如Appenders、LoggerRepository或Category的callAppenders方法。
2.它們不能以編程方式配置log4j。
3.它們不能通過調用類DomConfigurator或PropertyConfigurator進行配置。
2.Converting to the Log4j 2 API
在大多數情況下,從log4j 1.x api到log4j 2的轉換應該相當簡單。許多日志語句不需要修改。但是,如有必要,必須進行以下更改:
1.版本1中的主包是org.apache.log4j,版本2中的主包是org.apache.logging.log4j
2.對org.apache.log4j.Logger.getLogger()的調用必須修改為org.apache.logging.log4j.LogManager.getLogger()。
3.對org.apache.log4j.Logger.getRootLogger()或org.apache.log4j.LogManager.getRootLogger()的調用必須替換為org.apache.logging.log4j.LogManager.getRootLogger()。
4.調用org.apache.log4j.Logger.getLogger接受LoggerFactory必須刪除org.apache.log4j.spi.LoggerFactory並使用log4j 2的其他擴展機制之一。
5.將對org.apache.log4j.Logger.getEffectiveLevel()的調用替換為org.apache.logging.log4j.Logger.getLevel()。
6.刪除對org.apache.log4j.LogManager.shutdown()的調用,在版本2中不需要它們,因為log4j核心現在會在啟動時自動添加一個jvm關閉掛鈎來執行任何核心清理。
從log4j 2.1開始,您可以指定一個自定義的shutdownCallbackRegistry來覆蓋默認的jvm shutdown hook策略。
從log4j 2.6開始,現在可以使用org.apache.logging.log4j.LogManager.shutdown()手動啟動關閉。
7.API不支持對org.apache.log4j.Logger.setLevel()或類似方法的調用。應用程序應該刪除這些。log4j 2實現類中提供了等效的功能,請參見org.apache.logging.log4j.core.config.Configurator.setLevel(),但可能會使應用程序易受log4j2內部更改的影響。
8.在適當的情況下,應用程序應該轉換為使用參數化消息,而不是字符串連接。
9.org.apache.log4j.MDC和org.apache.log4j.NDC已被線程上下文替換。
3.configuring Log4j2
盡管log4j 2配置語法不同於log4j 1.x,但大多數(如果不是全部)相同的功能都是可用的。
注意,通過${foo}語法進行的系統屬性插值已經擴展,允許從許多不同的源進行屬性查找。有關詳細信息,請參閱查找文檔。例如,在log4j 1.x中使用名為catalina.base的系統屬性查找,語法將是${catalina.base}。在log4j 2中,語法是${sys:catalina.base}。
log4j 1.x有一個與log4j 2中的xmlayout不同的xmlayout,log4j-1.2-api模塊包含一個log4j1xmlayout,它以log4j 1.x中的格式生成輸出。log4j 1.x simplelayout可以用patternlayout%level-%m%n進行模擬。log4j 1.x ttcclayout可以用patternlayout“%r[%t]%p%c%notempty{%ndc}-%m%n”模擬。
log4j 1.x中的patternLayout和enhancedPatternLayout都可以替換為log4j 2中的patternLayout。log4j-1.2-api模塊包含兩個模式轉換“%ndc”和“%properties”,可用於模擬log4j 1.x patternlayout中的“%x”和“%x”(log4j 2中的%x和%x的格式略有不同)。
下面是log4j 1.x及其在log4j 2中的對應配置示例:
Sample 1 - Simple configuration using a Console Appender
Log4j 1.x XML configuration
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </layout> </appender> <category name="org.apache.log4j.xml"> <priority value="info" /> </category> <Root> <priority value ="debug" /> <appender-ref ref="STDOUT" /> </Root> </log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <Logger name="org.apache.log4j.xml" level="info"/> <Root level="debug"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
Sample 2 - Simple configuration using a File Appender, XMLLayout and SimpleLayout
Log4j 1.x XML configuration
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="A1" class="org.apache.log4j.FileAppender"> <param name="File" value="A1.log" /> <param name="Append" value="false" /> <layout class="org.apache.log4j.xml.XMLLayout" /> </appender> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.SimpleLayout" /> </appender> <category name="org.apache.log4j.xml"> <priority value="debug" /> <appender-ref ref="A1" /> </category> <root> <priority value ="debug" /> <appender-ref ref="STDOUT" /> </Root> </log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <File name="A1" fileName="A1.log" append="false"> <Log4j1XmlLayout /> </File> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%level - %m%n"/> </Console> </Appenders> <Loggers> <Logger name="org.apache.log4j.xml" level="debug"> <AppenderRef ref="A1"/> </Logger> <Root level="debug"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
Sample 3 - SocketAppender
Log4j 1.x XML configuration. This example from Log4j 1.x is misleading. The SocketAppender does not actually use a Layout. Configuring one will have no effect.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="A1" class="org.apache.log4j.net.SocketAppender"> <param name="RemoteHost" value="localhost"/> <param name="Port" value="5000"/> <param name="LocationInfo" value="true"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/> </layout> </appender> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </layout> </appender> <category name="org.apache.log4j.xml"> <priority value="debug"/> <appender-ref ref="A1"/> </category> <root> <priority value="debug"/> <appender-ref ref="STDOUT"/> </Root> </log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Socket name="A1" host="localHost" port="5000"> <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> </Socket> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <Logger name="org.apache.log4j.xml" level="debug"> <AppenderRef ref="A1"/> </Logger> <Root level="debug"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
Sample 4 - AsyncAppender and TTCCLayout
Log4j 1.x XML configuration using the AsyncAppender.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true"> <appender name="ASYNC" class="org.apache.log4j.AsyncAppender"> <appender-ref ref="TEMP"/> </appender> <appender name="TEMP" class="org.apache.log4j.FileAppender"> <param name="File" value="temp"/> <layout class="org.apache.log4j.TTCCLayout"> <param name="ThreadPrinting" value="true"/> <param name="CategoryPrefixing" value="true"/> <param name="ContextPrinting" value="true"/> </layout> </appender> <root> <priority value="debug"/> <appender-ref ref="ASYNC"/> </Root> </log4j:configuration>
Log4j 2 XML configuration.
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="debug"> <Appenders> <File name="TEMP" fileName="temp"> <PatternLayout pattern="%r [%t] %p %c %notEmpty{%ndc }- %m%n"/> </File> <Async name="ASYNC"> <AppenderRef ref="TEMP"/> </Async> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="ASYNC"/> </Root> </Loggers> </Configuration>
Sample 5 - AsyncAppender with Console and File
Log4j 1.x XML configuration using the AsyncAppender.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true"> <appender name="ASYNC" class="org.apache.log4j.AsyncAppender"> <appender-ref ref="TEMP"/> <appender-ref ref="CONSOLE"/> </appender> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </layout> </appender> <appender name="TEMP" class="org.apache.log4j.FileAppender"> <param name="File" value="temp"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </layout> </appender> <root> <priority value="debug"/> <appender-ref ref="ASYNC"/> </Root> </log4j:configuration>
Log4j 2 XML configuration. Note that the Async Appender should be configured after the appenders it references. This will allow it to shutdown properly.
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="debug"> <Appenders> <Console name="CONSOLE" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> <File name="TEMP" fileName="temp"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </File> <Async name="ASYNC"> <AppenderRef ref="TEMP"/> <AppenderRef ref="CONSOLE"/> </Async> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="ASYNC"/> </Root> </Loggers> </Configuration>
