1. 程式人生 > >Log4j2-Log4j 2介紹及使用

Log4j2-Log4j 2介紹及使用

Log4j 2 官網 Log4j 2簡介 架構 日誌級別 Filter Appender 將日誌請求列印到多個目標 Layout 自定義輸出格式 轉到Log4j 2 API 控制檯Appender的簡單配置 檔案Appender的簡單配置 SocketAppender AsyncAppender 控制檯和檔案的AsyncAppender 配置Log4j 2 使用Log4j 2 Log4j 2 官網 https://logging.apache.org/log4j/2.x/ Log4j 2簡介 Log4j的1.x版本已經被廣泛使用於很多應用程式中。然而,它這些年的發展已經放緩。它變得越來越難以維護,因為它需要嚴格遵循很老的Java版本,並在2015年8月壽終正寢。它的替代品,SLF4J和Logback對框架做了很多必要的改進。 那麼為什麼還要費心去做Log4j 2呢?幾個原因如下: Log4j 2被設計為可以作為審計框架使用。Log4j 1.x和Logback都會在重新配置的時候失去事件,而Log4j2不會。在Logback中,Appender當中的異常對應用從來都是不可見的。但Log4j2的Appender可以設定為允許將異常滲透給應用程式。 Log4j 2包含基於LMAX Disruptor庫的下一代非同步日誌器。在多執行緒情況下,非同步日誌器具有比Log4j 1.x和Logback高出10倍的吞吐效能以及更低的延遲。 Log4j 2在穩定記錄狀態下,對單機應用是無垃圾的,對Web應用是低垃圾的。這不僅降低了垃圾回收器的壓力,還可以提供更好的響應效能。 Log4j 2使用外掛系統使得它非常容易通過新的Appender、Filter、Layout、Lookup和Pattern Converter來擴充套件框架,且不需要對Log4j做任何修改。 由於外掛系統的配置更簡單了,配置項不需要宣告類名稱。 支援自定義日誌級別。自定義日誌級別可以在程式碼或配置中定義。 支援Lambda表示式。執行在Java 8上的客戶端程式碼可以使用Lambda表示式來實現僅在對應的日誌級別啟用時延遲構造日誌訊息。由於不需要明確地層層把關,這帶來了更簡潔的程式碼。 支援Message物件。Message允許支援感興趣或複雜的結構體在日誌系統中傳輸,且可以被高效地操作。使用者可以自由地建立他們自己的Message型別,並編寫自定義的Layout、Filter和Lookup來操作它們。 Log4j 1.x支援Appender上的Filter。Logback引入了TurboFilter來在事件被Logger處理之前對它們進行過濾。Log4j 2支援的Filter可以設定為在被Logger接管之前即處理事件,如同它在Logger或Appender中被處理。 很多Logback的Appender不接受一個Layout,且只能傳送固定格式的資料。而大多數Log4j 2的Appender接受Layout,允許資料以任意一種所需的格式傳輸。 Log4j 1.x和Logback中的Layout返回一個String。這導致了在Logback Encoder中討論的問題。Log4j 2用更簡單的方法,Layout總是返回一個位元組陣列。優點是這意味著它們可以用於任何Appender,而不僅僅是寫入到OutputStream中的那些。 Syslog Appender既支援TCP也支援UDP,同樣支援BSD系統日誌以及RFC 5424格式。 Log4j 2利用了Java 5的併發優勢,並在儘可能最低的程度上進行鎖定。Log4j 1.x中已知存在死鎖問題。其中很多已經在Logback中修復,但很多Logback的class檔案仍然需要在更高的編譯級別中同步。 這是一個被所有ASF專案集體支援使用的Apache軟體基金會專案。如果你想要貢獻或修改,只要參照貢獻中的方法。 架構 應用程式要使用Log4j 2的API,需要從LogManager中獲取一個有明確名稱的Logger。 LogManager將會定位到一個合適的LoggerContext並且從中獲取Logger。 如果Logger必須被建立,那麼它會和包含這些資訊的LogConfig相關聯:  a)與Logger相同的名稱;  b)父包的名稱;  c)根LoggerConfig。LoggerConfig物件根據配置中的Logger宣告而建立。 LoggerConfig與實際處理LogEvent事件的Appender關聯。 日誌級別 在表格中,垂直列為LogEvent的級別,水平列為從合適的LoggerConfig中分配到的級別。二者的交點處標識了LogEvent是否會被通過並傳遞給下一步處理,是(YES)或否(NO)。 Filter Log4j提供Filter並可應用於:控制被傳遞到任何LoggerConfig之前、控制被傳遞到達一個LoggerConfig但在呼叫任何Appender之前、控制被傳遞到一個LoggerConfig單在呼叫一個指定的Appender和每一個Appender之前。 與防火牆過濾的方式類似,每一個Filter都將返回三個結果之一:Accept(接受)、Deny(拒絕)或Neutral(中立)。 響應Accept意味著其他的Filter都不應該再被呼叫,而事件應該被處理。 響應Deny意味著事件應該被立即忽略,且將控制講給呼叫處。 響應Neutral代表事件應該被傳遞給其他的Filter。如果沒有其他Filter,則事件將被處理。 儘管一個事件可能被Filter接受,但事件仍然可能不被記錄。這種情況會發生於事件被LoggerConfig之前的Filter接受,但被LoggerConfig的Filter拒絕或者被所有的Appender拒絕。 Appender 將日誌請求列印到多個目標 http://logging.apache.org/log4j/2.x/manual/appenders.html Log4j允許將日誌請求列印到多個目標。用Log4j的說法,一個輸出的目標位置被稱為Appender。目前,Appender存在幾種:控制檯、檔案、遠端Socket伺服器、Apache Flume、JMS、遠端UNIX系統日誌後臺以及好幾種資料庫API。 一個Logger上可以裝配多個Appender。 Layout 自定義輸出格式 使用者不僅希望自定義輸出的目的位置,也希望自定義輸出格式。 這可以通過將一個Layout與Appender關聯來實現。Layout負責根據使用者的希望來格式化LogEvent,然而是Appender負責將格式化的內容輸出到目的位置。 PatternLayout,Log4j中的一部分,讓使用者根據C語言printf函式的方式來具體化輸出格式。 例如,使用轉換模式“%r [%t] %-5p %c - %m%n”的PatternLayout將會輸出類似於下面的內容: 176 [main] INFO  org.foo.Bar - Located nearest gas station. 第一個欄位是程式啟動以來鎖經過的毫秒時間。  第二個欄位是發出日誌請求的執行緒。  第三個欄位是日誌宣告的級別。  第四個欄位是與日誌請求相關聯的Logger名稱。 在“-”之後的文字是日誌的訊息內容。 Log4j帶有很多不同的Layout以支援諸如JSON、XML、HTML和Syslog 轉到Log4j 2 API 大多數情況下,從Log4j 1.x API轉換到Log4j 2相當簡單。很多日誌宣告都不需要修改,但以下這些變更是必要的 控制檯Appender的簡單配置 <?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> 檔案Appender的簡單配置 <?xml version="1.0" encoding="UTF-8"?> <Configuration>   <Appenders>     <File name="A1" fileName="A1.log" append="false">       <PatternLayout pattern="%t %-5p %c{2} - %m%n"/>     </File>     <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> SocketAppender <?xml version="1.0" encoding="UTF-8"?> <Configuration>   <Appenders>     <Socket name="A1" host="localHost" port="5000">       <SerializedLayout/>     </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> AsyncAppender <?xml version="1.0" encoding="UTF-8"?> <Configuration status="debug">   <Appenders>     <File name="TEMP" fileName="temp">       <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>     </File>     <Async name="ASYNC">       <AppenderRef ref="TEMP"/>     </Async>   </Appenders>   <Loggers>     <Root level="debug">       <AppenderRef ref="ASYNC"/>     </Root>   </Loggers> </Configuration> 控制檯和檔案的AsyncAppender 注意AsyncAppender應該在它引用Appender的後面被配置,這會讓它正確地關閉。

<?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> 配置Log4j 2 Log4j 2的配置可以通過以下4種方式之一完成: 通過以XML、JSON、YAML或屬性格式編寫的配置檔案。 以程式設計方式,通過建立ConfigurationFactory和配置實現。 通過呼叫配置介面中公開的API,以程式設計方式將元件新增到預設配置。 以程式設計方式,通過呼叫內部Logger類上的方法 舉例,具體請根據實際需要修改 <?xml version="1.0" encoding="UTF-8"?> <!-- log4j2使用說明: 使用方式如下: private static final Logger logger = LogManager.getLogger(實際類名.class.getName());

2、日誌說明: (1)請根據實際情況配置各項引數 (2)需要注意日誌檔案備份數和日誌檔案大小,注意預留目錄空間 (3)實際部署的時候backupFilePatch變數需要修改成linux目錄  --> <configuration status="debug">     <Properties>         <Property name="fileName">loginModule.log</Property>         <Property name="backupFilePatch">D:/workspace/workspace-jee/HelloSpring/hello-spring4/log/</Property>       </Properties>     <!--先定義所有的appender-->     <appenders>         <!--這個輸出控制檯的配置-->         <Console name="Console" target="SYSTEM_OUT">              <!--控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch)-->             <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />             <!-- 輸出日誌的格式-->             <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />         </Console>         <!--這個會打印出所有的資訊,每次大小超過size,則這size大小的日誌會自動存入按年份-月份建立的資料夾下面並進行壓縮,作為存檔-->         <RollingFile name="RollingFile" fileName="${backupFilePatch}${fileName}"             filePattern="${backupFilePatch}$${date:yyyy-MM}/app-%d{yyyyMMddHHmmssSSS}.log.gz">             <PatternLayout                 pattern="%d{yyyy.MM.dd 'at' HH:mm:ss.SSS z} %-5level %class{36} %L %M - %msg%xEx%n" />

            <!-- 日誌檔案大小 -->             <SizeBasedTriggeringPolicy size="20MB" />             <!-- 最多保留檔案數 -->             <DefaultRolloverStrategy max="20"/>         </RollingFile>     </appenders>

    <!--然後定義logger,只有定義了logger並引入的appender,appender才會生效-->     <loggers>         <!--建立一個預設的root的logger-->         <Logger name="org.apache.log4j.xml" level="trace"             additivity="true">             <AppenderRef ref="RollingFile" />         </Logger>         <Root level="error">             <AppenderRef ref="Console" />         </Root>     </loggers> </configuration> 使用Log4j 2 maven 的引用

<!-- slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.11.1</version>
    </dependency>
    <!-- web容器中需要新增log4j-web -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-web</artifactId>
        <version>2.11.1</version>
    </dependency>

import com.foo.Bar; // 匯入Log4j的類 import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class MyApp {     // 定義一個靜態的日誌器變數,引用名為MyApp的例項     private static final Logger logger = LogManager.getLogger(MyApp.class);     public static void main(final String... args) {         // 設定一個簡單的配置,日誌顯示在控制檯中         logger.trace("Entering application.");         Bar bar = new Bar();         if (!bar.doIt()) {             logger.error("Didn't do it.");         }         logger.trace("Exiting application.");     } } import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class Bar {   static final Logger logger = LogManager.getLogger(Bar.class.getName());

  public boolean doIt() {     logger.entry();     logger.error("Did it again!");     return logger.exit(false);   } } 如果Log4j找不到配置檔案,它將提供預設配置。DefaultConfiguration類中提供的預設配置將設定: 一個附加到根記錄器的ConsoleAppender。 一個設定為“%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} -  %msg%n”的PatternLayout,被附加到ConsoleAppender上。 注意,預設情況下Log4j將根日誌記錄器分配給Level.ERROR。 MyApp的輸出類似如下: 17:13:01.540 [main] ERROR com.foo.Bar - Did it again! 17:13:01.540 [main] ERROR MyApp - Didn't do it. 如前所述,Log4j將首先嚐試從配置檔案配置自身。與預設配置相同的配置如下所示: <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN">   <Appenders>     <Console name="Console" target="SYSTEM_OUT">       <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>     </Console>   </Appenders>   <Loggers>     <Root level="error">       <AppenderRef ref="Console"/>     </Root>   </Loggers> </Configuration> 一旦上述檔案作為log4j2.xml放入到類路徑中,你將得到與上面列出的相同結果。將根級別更改為trace將得到類似於以下的結果: 17:13:01.540 [main] TRACE MyApp - Entering application. 17:13:01.540 [main] TRACE com.foo.Bar - entry 17:13:01.540 [main] ERROR com.foo.Bar - Did it again! 17:13:01.540 [main] TRACE com.foo.Bar - exit with (false) 17:13:01.540 [main] ERROR MyApp - Didn't do it. 17:13:01.540 [main] TRACE MyApp - Exiting application.