Log4j 2.x 相較 1.x 實現了架構級重寫,採用無鎖非同步日誌、插件化架構,吞吐量提升 10 倍以上。本文涵蓋 Maven 依賴、多格式配置文件、核心組件詳解、Web 專案整合與最佳實踐。
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.23.1</version> <!-- 建議升級至最新穩定版 -->
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.23.1</version>
<scope>runtime</scope>
</dependency>
Log4j2 依次掃描 classpath 下列文件,首個匹配生效:
log4j.configurationFile 系統屬性指定路徑log4j2-test.propertieslog4j2-test.yaml / .ymllog4j2-test.json / .jsnlog4j2-test.xmllog4j2.propertieslog4j2.yaml / .ymllog4j2.json / .jsnlog4j2.xml(最常用)DefaultConfiguration(預設僅輸出 ERROR 級別到控制台)建議:開發環境用 log4j2-test.xml,生產環境用 log4j2.xml,透過 Maven Profile 切換。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30"> <!-- status: 內部日誌級別;monitorInterval: 熱重載間隔(秒) -->
<Properties>
<Property name="logPath">${sys:catalina.home}/logs/myapp/</Property>
<Property name="pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}][%t][%-5level][%c:%L] %msg%n</Property>
</Properties>
<Appenders>
<!-- 控制台輸出 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}"/>
</Console>
<!-- 滾動文件:按時間+大小雙重觸發 -->
<RollingFile name="RollingFile"
fileName="${logPath}/app.log"
filePattern="${logPath}/app-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- 每天 -->
<SizeBasedTriggeringPolicy size="100 MB"/> <!-- 或超過 100MB -->
</Policies>
<DefaultRolloverStrategy max="30"/> <!-- 最多保留 30 個歸檔 -->
</RollingFile>
<!-- 非同步 Appender:高併發場景必備 -->
<Async name="AsyncAppender">
<AppenderRef ref="RollingFile"/>
</Async>
</Appenders>
<Loggers>
<!-- 業務 Logger:僅輸出到文件,不向上傳遞 -->
<Logger name="com.myapp.business" level="DEBUG" additivity="false">
<AppenderRef ref="AsyncAppender"/>
</Logger>
<!-- Root Logger:控制台 + 文件 -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="AsyncAppender"/>
</Root>
</Loggers>
</Configuration>
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
level="WARN" 則 TRACE/DEBUG/INFO 不會輸出。status="WARN" 僅控制 Log4j2 內部啟動日誌,不影響業務日誌。| 屬性 | 說明 | 範例 |
|---|---|---|
| fileName | 當前活躍日誌文件路徑 | ${logPath}/app.log |
| filePattern | 歸檔命名規則,支援日期/索引佔位符 | app-%d{yyyy-MM-dd}-%i.log.gz |
| Policies | 觸發策略組合(Time/Size/Cron) | 見上方範例 |
| DefaultRolloverStrategy.max | 最大歸檔數量,超過刪除最舊 | 30 |
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector,所有 Logger 自動非同步。<AsyncRoot> 或 <AsyncLogger> 指定部分非同步,搭配 <Async name="AsyncAppender"> 封裝同步 Appender。disruptor 依賴(Log4j 2.9+ 內建,無需額外添加)。import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class OrderService {
private static final Logger logger = LogManager.getLogger(OrderService.class);
public void createOrder(Order order) {
logger.info("建立訂單: {}", order.getId()); // 佔位符延遲計算,效能佳
logger.debug("訂單詳情: {}", order); // DEBUG 級別時才序列化 order
try { /* ... */ }
catch (Exception e) {
logger.error("訂單建立失敗", e); // 異常堆疊自動記錄
}
}
}
Log4j2 透過 ServletContainerInitializer 自動掃描 log4j2.xml,**無需在 web.xml 配置 Listener**。若配置文件不在 classpath 根目錄,需在 web.xml 指定:
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/classes/log4j2.xml</param-value>
</context-param>
logger.info("User {} logged in", name) 避免字串拼接開銷。error.log,便於告警掃描。filePattern 以 .gz 結尾自動壓縮,節省磁碟空間。monitorInterval="30" 讓生產環境無需重啟即可調整日誌級別。MDC.put("traceId", traceId) 實現全鏈路追蹤。