前言
log4j2
是 log4j
的進化版本,並提供了許多 logback
可用的改進,同時解決了 Logback
體系結構中的一些固有問題。本文將從slf4j+log4j2
的快速使用開始,然後介紹log4j2
的優異性能以及log4j2
配置文件相關的詳細說明。
log4j2 官網文檔:https://logging.apache.org/log4j/2.x/
快速使用
引入依賴
- 如果是
SpringBoot
項目,可以引入下面的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
- 如果是普通的
Maven
項目則需引入如下依賴
<properties>
<log4j2.version>2.13.3</log4j2.version>
</properties>
<!-- 日誌框架 slf4j+log4j2-->
<!-- slf4j依賴 -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<!-- log4j2和slf4j橋接依賴-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
<scope>test</scope>
</dependency>
<!-- log4j2依賴-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
</dependencies>
排除依賴衝突
如Spring Boot 2.x默認使用Logback
日誌框架,要使用 log4j2
必須先排除 logback
。
例子
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<!--排除logback-->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
如果還有其他的依賴衝突,看控制檯報錯信息和pom.xml
文件的依賴圖(右鍵點擊Show Dependencies…), 進行排除(Exclude), 依賴圖裏面有紅線的,就是存在依賴衝突的,但運行不一定會報錯,報錯的衝突是一定要解決的。排除後,需要進行 Reimport 重新導入依賴。
依賴圖裏查找依賴的方法
快捷鍵 ctrl
+F
,彈出圖元素框後,雖然沒有搜索框,但是可以繼續輸入查找的內容,輸入之後,查找的內容就會出現了,如下圖所示。
配置文件
log4j2 配置文件名稱和加載順序
使用log4j2
之前需要在classpath
下新建一個配置文件。如果沒有任何配置,log4j2
將使用缺省配置。需要注意的是 log4j 2.x
版本不再支持像 1.x
中的.properties
後綴的文件配置方式,2.x
版本配置文件後綴名只能爲".xml
",".json
“或者”.jsn
"。
系統選擇配置文件的優先級(從先到後)如下:
classpath
下的名爲log4j2-test.json
或者log4j2-test.jsn
的文件
classpath
下的名爲log4j2-test.xml
的文件
classpath
下名爲log4j2.json
或者log4j2.jsn
的文件
classpath
下名爲log4j2.xml
的文件
我們一般默認使用log4j2.xml
進行命名。如果本地要測試,可以把log4j2-test.xml
放到classpath
,而正式環境使用log4j2.xml
,則在打包部署的時候不要打包log4j2-test.xml
即可。
log4j2配置文件的位置
默認情況下,只要把log4j2
配置文件放在 classpath
環境變量所指定的目錄即可,即IDEA
中的resources
根目錄下(不是它裏面的子文件夾)。如果想放在其他位置,比如resources/config
文件夾下,則需要在application.yml
增加自定義的配置:
# 日誌
logging:
config: classpath:config/log4j2.xml
配置文件例子
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="debug" monitorInterval="30">
<!-- 先定義所有的appender(附加器)-->
<appenders>
<!-- 輸出控制檯的配置 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 控制檯只輸出level及以上級別的信息(onMatch),其他的直接拒絕(onMismatch) -->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 輸出日誌的格式 -->
<PatternLayout pattern="[%d{HH:mm:ss.SSS}] [%-5p] %l - %m%n"/>
</Console>
<!-- 文件會打印出所有信息,這個log每次運行程序會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用 -->
<!-- append爲TRUE表示消息增加到指定文件中,false表示消息覆蓋指定的文件內容,默認值是true -->
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="[%d{HH:mm:ss.SSS}] [%-5p] %l - %m%n"/>
</File>
<!-- 添加過濾器ThresholdFilter,可以有選擇的輸出某個級別以上的類別 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否則直接拒絕 -->
<File name="ERROR" fileName="logs/error.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{yyyy.MM.dd 'at' HH:mm:ss z}] [%-5p] %l - %m%n"/>
</File>
<!-- 這個會打印出所有的信息,每次大小超過size,則這size大小的日誌會自動存入按年份-月份建立的文件夾下面並進行壓縮,作爲存檔 -->
<RollingFile name="RollingFile" fileName="logs/web.log"
filePattern="logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="[%d{yyyy-MM-dd 'at' HH:mm:ss z}] [%-5p] %l - %m%n"/>
<SizeBasedTriggeringPolicy size="2MB"/>
</RollingFile>
</appenders>
<!-- 然後定義logger,只有定義了logger並引入的appender,appender纔會生效 -->
<loggers>
<!-- 過濾掉spring和mybatis的一些無用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<!-- 建立一個默認的root的logger -->
<root level="trace">
<appender-ref ref="RollingFile"/>
<appender-ref ref="Console"/>
<appender-ref ref="ERROR"/>
<appender-ref ref="log"/>
</root>
</loggers>
</configuration>
日誌打印代碼
使用lombok
插件中的@Slf4j
註解可以很方便的使用 org.slf4j.Logger
對象。日常開發儘量使用Slf4j門面來處理日誌,儘量避免使用具體的日誌框架。
@Slf4j
@SpringBootTest
public class LogTests {
@Test
public void m1() {
log.trace("trace");
log.debug("debug");
log.info("info");
log.warn("warn");
log.error("error");
log.error("error {}", "param");
}
}
控制檯輸出:
[17:54:58.712] [INFO ] com.chenqunhui.blog.LogTests.m1(LogTests.java:20) - info
[17:54:58.712] [WARN ] com.chenqunhui.blog.LogTests.m1(LogTests.java:21) - warn
[17:54:58.712] [ERROR] com.chenqunhui.blog.LogTests.m1(LogTests.java:22) - error
[17:54:58.713] [ERROR] com.chenqunhui.blog.LogTests.m1(LogTests.java:23) - error param
log4j2的優點
市面上的日誌框架多種多樣:log4j
、log4j2
、slf4j
、JDKLog
、logback
等等。log4j
目前已經停止更新了。Apache推出了新的log4j2
來代替log4j
,log4j2
是對log4j
的升級,與其前身log4j
相比有了顯着的改進,並提供了許多logback
可用的改進,同時解決了logback
體系結構中的一些固有問題。因此,log4j2 + slf4j
應該是未來的大勢所趨。
log4j2的性能
log4j2
最牛逼的地方在於異步輸出日誌時的性能表現,log4j2
在多線程的環境下吞吐量與log4j
和logback
的比較如下圖。下圖比較中log4j2
有三種模式:
1)全局使用異步模式;
2)部分Logger採用異步模式;
3)異步Appender。
可以看出在前兩種模式下,log4j2
的性能較之log4j
和logback
有很大的優勢。
完整的官方性能文檔:https://logging.apache.org/log4j/2.x/performance.html
log4j2.xml配置文件說明
<configuration status="debug" monitorInterval="30">
-
根節點
Configuration
有兩個屬性:status
和monitorinterval
, 兩個子節點:Appenders
和Loggers
(表明可以定義多個Appender
和Logger
)。
其中,status
用來指定log4j
本身的打印日誌的級別。
monitorinterval
用於指定log4j
自動重新配置的監測間隔時間, 是用來設置配置文件的動態加載時間的,單位是s, 最小是5s。monitorInterval="30"
表示每30秒配置文件會動態加載一次。在程序運行過程中,如果修改配置文件,程序會隨之改變。 -
Appenders
節點,常見的有三種子節點:Console
、RollingFile
、File
。●
Console
節點用來定義輸出到控制檯的Appender
。
(1)name
:指定Appender
的名字.
(2)target
:SYSTEM_OUT
或SYSTEM_ERR
,一般只設置默認:SYSTEM_OUT
.
(3)PatternLayout
:輸出格式,不設置默認爲:%m%n
.●
File
節點用來定義輸出到指定位置的文件的Appender
.
(1)name
:指定Appender
的名字.
(2)fileName
:指定輸出日誌的目的文件帶全路徑的文件名.
(3)PatternLayout
:輸出格式,不設置默認爲:%m%n
.●
RollingFile
節點用來定義日誌文件超過指定大小自動刪除舊的創建新的的Appender.
自動追加日誌信息到文件中,直至文件達到預定的大小,然後自動重新生成另外一個文件來記錄之後的日誌。
(1)name
:指定Appender
的名字.
(2)fileName
:指定輸出日誌的目的文件帶全路徑的文件名.
(3)PatternLayout
:輸出格式,不設置默認爲:%m%n
.
(4)filePattern
:指定新建日誌文件的名稱格式.
(5)Policies
:指定滾動日誌的策略,就是什麼時候進行新建日誌文件輸出日誌.
(6)TimeBasedTriggeringPolicy
:Policies
子節點,基於時間的滾動策略,interval
屬性用來指定多久滾動一次,默認是1hour。modulate=true
用來調整時間:比如現在是早上3am,interval
是4,那麼第一次滾動是在4am,接着是8am,12am…而不是7am.
(7)SizeBasedTriggeringPolicy
:Policies
子節點,基於指定文件大小的滾動策略,size
屬性用來定義每個日誌文件的大小.
(8)DefaultRolloverStrategy
:用來指定同一個文件夾下最多有幾個日誌文件時開始刪除最舊的,創建新的(通過max屬性)。 -
Loggers
節點,常見的有兩種子節點:Root
和Logger
.●
Root
節點用來指定項目的根日誌,如果沒有單獨指定Logger
,那麼就會默認使用該Root日誌輸出
○level
:日誌輸出級別,共有8個級別,按照從低到高爲:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
○appender-ref
:Root
的子節點,用來指定該日誌輸出到哪個Appender
.●
Logger
節點用來單獨指定日誌的形式,比如要爲指定包下的class指定不同的日誌級別等。
○level
:日誌輸出級別,共有8個級別,按照從低到高爲:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
○name
:用來指定該Logger所適用的類或者類所在的包全路徑,繼承自Root節點.
○appender-ref
:Logger
的子節點,用來指定該日誌輸出到哪個Appender,如果沒有指定,就會默認繼承自Root.如果指定了,那麼會在指定的這個Appender
和Root
的Appender
中都會輸出,此時我們可以設置Logger
的additivity="false"
只在自定義的Appender
中進行輸出。