java 開發環境,JDK 預設有提供 logging 機制,但 logging 機制的發展,也是一段精彩的歷史。就以往使用的經驗,從一開始的 log4j,後來換成了 logback + slf4j,到現在這個階段,似乎又要換成 log4j2,因為 log4j2 的效能評估,結果已經是又超過了 logback。
logging framwork 的發展可以參考這一篇文章: Java Logging 的歷史與戰爭
但這種情況也說明了,開放且多元的 java 開發環境,一個必要且熱門的 framework,會吸引大家注意並不斷提出更好的框架,但使用者就得跟著時代不斷的進步。
使用 log4j 用 maven 引用 library,在 pom.xml 的 dependencies 裡面加上 log4j2 及 slf4j。
slf4j 是 logging 的 wrapper,可用一致 API 介面進行程式開發,在不修改程式的狀況下,可替換內部的實作為 logback 或 log4j 或 jdk logging。
<dependencies>
<!-- log4j2 + slf4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.22.1</version>
</dependency>
</dependencies>
在 classpath 裡面加上設定檔 log4j2.xml
以下是調整後的設定
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5p %c %L - %m%n</Pattern>
</PatternLayout>
</Console>
<!--
<File name="FILE" fileName="testweb.log">
<PatternLayout>
<Pattern>%d [%thread] %-5p %c %L - %m%n</Pattern>
</PatternLayout>
</File>
-->
<RollingFile name="RollingFile" fileName="logs/testweb.log" filePattern="logs/testweb-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<Pattern>%d [%thread] %-5p %c %L - %m%n</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${baseDir}" maxDepth="2">
<IfFileName glob="*/test-*.log.gz" />
<IfLastModified age="30d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<!-- hibernate -->
<logger name="org.hibernate" level="INFO" />
<Logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.cfg" level="ERROR" />
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
RollingFile 的部分可以參考官方說明Log4j 2 Appenders
Policies 的部分,決定什麼時候要 trigger rolling 的機制。OnStartupTriggeringPolicy 代表程式啟動要做一次。TimeBasedTriggeringPolicy 則是跟著 Pattern 裡面日期的最小精度的部分 trigger,目前日期是設定為日,所以這個範例,每天會處理一次。SizeBasedTriggeringPolicy 則是會判斷 log file 的檔案大小 trigger,pattern 部分會因為 %i
這個設定,每次會將檔案改為 -1, -2 這樣的檔名。
DefaultRolloverStrategy 可將超過 30 天,符合glob 設定的 pattern 的檔案刪除。
使用 logging 是透過 sl4j 介面
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
Logger log = LoggerFactory.getLogger(this.getClass().getName());
public void sayHello(){
log.debug("This will be printed on debug");
log.info("This will be printed on info");
log.warn("This will be printed on warn");
log.error("This will be printed on error");
log.info("Appending string: {}.", "Hello, World");
}
}
log4j2 對效能最大的改進點在非同步的 file appender Log4j 2 Appenders
調整 log4j2.xml 設定,基於上面的 RollingFile 增加 Appenders。
bufferSize 預設為 1024,代表可暫存 1024 則 log,必須要設定為 2 的指數。
<Async name="AsyncRollingFile" bufferSize="262144">
<AppenderRef ref="RollingFile"/>
</Async>
然後修改下面的 AppenderRef,就可以換成 AsyncRollingFile
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="AsyncRollingFile"/>
</Root>
References
Log4j2中RollingFile的文件滚动更新机制 - Ye_yang - 博客园
Java Logging Frameworks: log4j vs logback vs log4j2
Log4j; Performance