# Log4j 2最佳實踐 #
Log4j的1.x版本已經被普遍使用於不少應用程序中。然而,它這些年的發展已經放緩。它變得愈來愈難以維護,由於它須要嚴格遵循很老的Java版本,並在2015年8月壽終正寢。它的替代品,SLF4J和Logback對框架作了不少必要的改進。
```
一、首先移除log4j相關的jar包
<dependency>
...
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
二、添加slf4j和log4j 2的jar包
<!-- log4j2 依賴的jar包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- 與slf4j整合所需 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- web網站須要 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- 異步使用的依賴 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.7</version>
<scope>runtime</scope>
</dependency>
三、添加配置文件:log4j2.xml
# Log4j 2最佳實踐 #
Log4j的1.x版本已經被普遍使用於不少應用程序中。然而,它這些年的發展已經放緩。它變得愈來愈難以維護,由於它須要嚴格遵循很老的Java版本,並在2015年8月壽終正寢。它的替代品,SLF4J和Logback對框架作了不少必要的改進。
```
一、首先移除log4j相關的jar包
<dependency>
...
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
二、添加slf4j和log4j 2的jar包
<!-- log4j2 依賴的jar包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- 與slf4j整合所需 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- web網站須要 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- 異步使用的依賴 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.7</version>
<scope>runtime</scope>
</dependency>
三、添加配置文件:log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
首先看Configuration元素,log4j2框架本身也有一系列日誌,好比框架初始化日誌或者初始化失敗日誌什麼的。
status表示應該記錄哪一個等級的log4j2自身的日誌,通常狀況下WARN就行,若是出現了了WARN等級的日誌,就要及時排查排查了。
log4j2支持自動熱更新配置文件,直接改log4j2的配置文件,它就能自動從新加載,monitorInterval表示應該多久檢測一次更新,單位:秒,默認5秒。
-->
<Configuration status="WARN" monitorInterval="5">
<!-- 將一些經常使用值提取出來,而後在文件的其餘部分經過${}的形式引用,這些值能夠隨便定義 -->
<Properties>
<!-- 定義日誌文件根目錄 -->
<Property name="logDir" value="d:/logs" />
<!-- 定義日誌的通用格式 -->
<Property name="genericPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<!-- 定義日誌分卷文件通用文件名形式 -->
<Property name="genericFilePattern" value="%d{yyyy-MM-dd}-%i" />
</Properties>
<!--
Appenders元素,官方文檔表示有還有一種異步appender,寫文件等使用同步便可,在作數據庫插入等耗時操做時用,並且在多線程狀況下有可能出現問題,不討論那個。
官方文檔有不少種類型的appender,可是日常工做中經常使用的也就是console類型和file類型的。
console類型appender沒得選,只有這一種,結構很簡單,不用多說。
file類型appender有多種類型,建議使用RollingRandomAccessFile類型,由於這種類型的fileAppender有緩存功能,效率比RollingFile高(網上不少教程都是幾年前的了,用的仍是RollingFile),因此只討論這種類型。
fileName表示日誌文件名
filePattern表示日誌文件分卷的分卷文件的文件名(日誌文件分卷就是某些狀況,好比天天生成一個文件,或者單個日誌文件超過100MB時自動分紅多個日誌文件)
fileName若是已.zip結尾表示啓用壓縮功能,那些分卷好的日誌文件會被壓縮,某些狀況會頗有用。若是不想啓用壓縮功能,就不要已.zip或者其餘壓縮文件後綴結尾。PatternLayout表示日誌格式,沒必要多說。
Policies是觸發日誌文件分卷的條件。TimeBasedTriggeringPolicy表示按照時間來分卷
interval表示時間間隔,時間單位是從filePattern推導的,是filePattern中最小的時間的單位
好比上述示例中的filePattern爲%d{yyyy-MM-dd},這個日期時間格式必須符合java日期時間規範,其中最小日期單位爲dd,也就是天,推導出來也就是1天分一個日誌文件出來,若是filePattern的配置爲%d{yyyy-MM-dd HH:mm},最小單位是mm,也就是分鐘,那就是1分鐘分一個日誌文件出來,若是interval爲3,那就是3天一個日誌文件和3分鐘一個日誌文件,推導規則就是如此。
SizeBasedTriggeringPolicy表示日誌文件大小超過多大時對其進行分卷,size表示日誌大小,單位推薦寫MB,數值爲大於0的整數,100 MB中間有個空格,推薦寫上。DefaultRolloverStrategy表示分卷策略,只須要記住這個必需要配就好了,沒必要深究,max表示最多能夠有多少個分卷文件,默認爲7個,超出7個的日誌分卷文件將被刪除,也就是說可能致使重要日誌丟失,因此該參數配大點,100000應該夠了,compressionLevel表示壓縮等級,值爲0-9,只在filePattern以.zip結尾,也就是說壓縮格式爲zip時起做用,這也是爲何前面說建議壓縮格式爲zip。0表示不壓縮,只打包爲zip格式,9表示最高壓縮比(我的測試1MB日誌文件某些狀況下能壓縮到4KB左右)。若是不想啓用壓縮功能,前面說過,日誌filePattern不以.zip結尾就好了,這時compressionLevel是不起做用的。 -->
<!-- appender們的定義,能夠控制檯、文件、發郵件、存數據庫等等。常規狀況下只用控制檯和文件便可 -->
<!-- appender們的定義 -->
<Appenders>
<!-- 定義一個console類型定定義,若是須要,能夠以這個爲原型粘貼複製修改再定義適合本身的 -->
<Console name="app_console" target="SYSTEM_OUT">
<PatternLayout pattern="${patternLayout}" />
</Console>
<!-- debug及以上級別的日誌都打印在一個文本中 -->
<RollingRandomAccessFile name="app_debug" fileName="${logDir}/app-debug.log"
filePattern="${logDir}/app-debug_${genericFilePattern}.log" append="true">
<Filters>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${patternLayout}" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" />
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="1000000" compressionLevel="5" />
</RollingRandomAccessFile>
<!-- 只打印info -->
<RollingRandomAccessFile name="app_info_only" fileName="${logDir}/app-info.log"
filePattern="${logDir}/app-info_${genericFilePattern}.log" append="true">
<Filters>
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${patternLayout}" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" />
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="1000000" compressionLevel="5" />
</RollingRandomAccessFile>
</Appenders>
<!-- 定義logger們 -->
<Loggers>
<!-- 定義根logger,根logger是必須的,這裏我把根logger定義爲異步的,也可爲定義爲普通的同步的,可是注意在同步根logger和異步根logger中只能存在一個,不能兩個都配置 -->
<asyncRoot level="debug">
<AppenderRef ref="app_console" />
</asyncRoot>
<!-- 普通的根logger,注意,跟上面的異步跟root同時只能存在一個 -->
<!-- <Root level="trace"> <AppenderRef ref="consoleAppender" /> </Root> -->
<!-- 定義一個普通的logger,這裏我定義爲異步的 -->
<!-- 定義一個普通的logger,這裏我定義爲異步的
additivity:表示是否將本身所管目錄下的消息複製一份發送給父類(即rootLoggers)默認true
name:loggers監控的包名,好比com.sun.jdbc
lever:級別,只有大於等於該級別的才能被監聽到
-->
<asyncLogger name="logtest" level="debug" additivity="false">
<AppenderRef ref="app_console" />
<AppenderRef ref="app_debug" />
<AppenderRef ref="app_info_only" />
</asyncLogger>
</Loggers>
</Configuration>
```
```java