Apache Log4j 是一個基於 Java 的日志記錄工具。它是由瑞士程序員 Ceki Gülcü 於 2001 年開發的,現在則是Apache軟件基金會的一個項目。 Log4j是幾種Java日志框架之一。Log4j 團隊創建了 Log4j 的繼任者,版本號為 2.0 的新版本。Log4j 2.0 着重於 Log4j 1.2、1.3、java.util.logging 和logback中的問題,並解決這些框架中的架構問題。此外,Log4j 2.0 提供了一個插件架構,這使得其更可擴展。Log4j 2.0 不是與 1.x 向后兼容的版本。
—— wikipedia
日志系統在整個項目架構設計中占得比例很重,比如管理員操作記錄,一些捕獲的異常記錄等等。這時候有一個好的日志框架就是我們所必須的。目前最流行的是 Log4j 2.0 版本雖然前一段時間出了一個 0day 的 BUG 但是瑕不掩瑜。Log4j2 的配置也比較簡單,支持 yml 、xml 甚至是 json 都是可以的。這個實踐中我用的是 xml 格式,畢竟其他的沒用過。
先來看下整體的配置,然后在根據每個標簽單獨研究。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" name="log4j2-name" monitorInterval="5">
<Properties>
<Property name="console.pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} - [%t] %-5level %logger{36} - %msg%n</Property>
<Property name="file.pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} - [%t] %-5level %logger{36} - %msg%n</Property>
</Properties>
<Appenders>
<Console name="console-appender" target="SYSTEM_OUT">
<PatternLayout pattern="${console.pattern}"/>
</Console>
<File name="files-appender" fileName="logs/files-appender.log" append="false">
<PatternLayout>
<Pattern>${file.pattern}</Pattern>
</PatternLayout>
</File>
<Async name="async-appender">
<AppenderRef ref="files-appender"/>
</Async>
<RandomAccessFile name="random-access-file-appender" fileName="logs/random-access-file.log">
<PatternLayout>
<Pattern>${file.pattern}</Pattern>
</PatternLayout>
</RandomAccessFile>
<RollingFile name="rolling-file-appender" fileName="logs/rolling-file-appender.log"
filePattern="logs/rolling-file-appender-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<PatternLayout>
<Pattern>${file.pattern}</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
</RollingFile>
<RollingRandomAccessFile name="rolling-random-access-file-appender"
fileName="logs/rolling-random-access-file.log"
filePattern="logs/$${date:yyyy-MM}/rolling-random-access-file-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>${file.pattern}</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
</RollingRandomAccessFile>
<!-- to 收件者 from 寄件者 -->
<SMTP name="mail-appender" subject="錯誤日志信息" to="發送到哪里" from="發送者"
smtpHost="smtp.qiye.163.com"
smtpPort="465"
bufferSize="1"
smtpUsername="SMTP用戶名"
smtpPassword="SMTP密碼"
smtpProtocol="smtps"
mail.smtp.ssl.enable="true"
mail.smtp.starttls.enable="true"
>
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>${file.pattern}</Pattern>
</PatternLayout>
</SMTP>
</Appenders>
<Loggers>
<logger name="org.mybatis" level="INFO"></logger>
<Root level="info">
<AppenderRef ref="console-appender"/>
<!-- <AppenderRef ref="file-appender"/>-->
<AppenderRef ref="rolling-file-appender"/>
<AppenderRef ref="async-appender"/>
<AppenderRef ref="random-access-file-appender"/>
<AppenderRef ref="rolling-random-access-file-appender"/>
<AppenderRef ref="mail-appender"/>
</Root>
</Loggers>
</Configuration>
上面是我常用的幾個標簽,每個標簽都有其各自的意義。
Configuration
整個配置中最核心的標簽,他對應 log4j 的 ConfigurationFactory
因為我用的是 xml 所以 ConfigurationFactory
會把配置傳遞給 XmlConfigurationFactory
,最常用的標簽就是下面這些。
屬性名稱 | 描述 |
---|---|
name | 配置的名稱。 |
status | 日志的等級,有"off", "trace", "debug", "info", "warn", "error", "fatal" 和 "all" ,選擇 "trace" 就可以把 Log4j 的日志也顯示出來 |
monitorInterval | 每隔多少秒更新日志的配置信息 |
Properties & Property
properties 這個標簽很簡單就是一個屬性標簽可以配置一些全局的屬性,可以給后面的標簽使用。
<Properties>
<Property name="屬性名稱"></Property>
</Properties>
Appenders
Appenders 單獨沒有什么作用,主要是他的各種子標簽。下面子標簽的屬性是我常用的一些,如果不常用的可能沒有列出來。
-
Console 日志通過控制台打印
Parameter Name Type Description layout Layout 輸出格式化,可以使用 PatternLayout 標簽替代 name String 標識符 target String "SYSTEM_OUT" or "SYSTEM_ERR". 默認為 "SYSTEM_OUT". <Console name="console-appender" target="SYSTEM_OUT"> <!--PatternLayout: 輸出日志的格式--> <PatternLayout pattern=" %msg%n"/> <!--ThresholdFilter :日志輸出過濾--> <!--level="info" :日志級別,onMatch="ACCEPT" :級別在info之上則接受,onMismatch="DENY" :級別在info之下則拒絕--> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> </Console>
-
File 日志通過文件存儲
Parameter Name Type Description append boolean 如果為 true ( 默認值),則記錄將追加到文件末尾。如果設置為 false,則在寫入新記錄之前將清除該文件。 bufferedIO boolean 當 true 時 - 默認值,記錄將寫入緩沖區,並在緩沖區已滿時將數據寫入磁盤,或者,如果設置了立即Flush,則在寫入記錄時將數據寫入磁盤。文件鎖定不能與緩沖IO一起使用。性能測試表明,即使啟用了即時浮現,使用緩沖 I/O 也能顯著提高性能。 bufferSize int 當 bufferedIO 為 true 時,可以配置此項的緩沖區大小,默認值為 8192 字節。 fileName String 寫入文件的名稱,如果文件或者目錄不存在會創建生成 name String Appender 標識符 <File name="files-appender" fileName="logs/files-appender.log" append="false"> <!--PatternLayout: 輸出日志的格式 這種寫法和上面那個等同--> <PatternLayout> <Pattern>${file.pattern}</Pattern> </PatternLayout> </File>
-
Async 和其他的 Appenders 配合使用,可以使得 Appenders 變為異步處理
Parameter Name Type Description name String 標識符 <Async name="async-appender"> <!--AppenderRef: 引用其他的 appender 使其成為異步處理--> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <AppenderRef ref="files-appender"/> </Async>
-
RandomAccessFile 和 File 是一樣的只不過 RandomAccessFile 是始終是緩沖的而且不能關閉。據官方測量性能比 File 開啟
bufferedIO
還要快 200%。內部使用的機制是 ByteBuffer + RandomAccessFile 而不是BufferedOutputStreamParameter Name Type Description append boolean 如果為 true ( 默認值),則記錄將追加到文件末尾。如果設置為 false,則在寫入新記錄之前將清除該文件。 fileName String 要寫入的文件的名稱。如果文件或其任何父目錄不存在,則將創建它們。 bufferSize int 緩沖區大小默認為 262144 字節 (256 * 1024)。 name String 標識符 <RandomAccessFile name="random-access-file-appender" fileName="logs/random-access-file.log"> <PatternLayout> <Pattern>${file.pattern}</Pattern> </PatternLayout> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> </RandomAccessFile>
-
RollingFile 是一個 OutputStreamAppender,它寫入 fileName 參數中指定的 File,並根據 TriggeringPolicy 和 RolloverPolicy 滾動文件。
Parameter Name Type Description append boolean 如果為 true ( 默認值),則記錄將追加到文件末尾。如果設置為 false,則在寫入新記錄之前將清除該文件。 bufferedIO boolean 當 true 時 - 默認值,記錄將寫入緩沖區,並在緩沖區已滿時將數據寫入磁盤,或者,如果設置了立即Flush,則在寫入記錄時將數據寫入磁盤。文件鎖定不能與緩沖IO一起使用。性能測試表明,即使啟用了即時浮現,使用緩沖 I/O 也能顯著提高性能。 bufferSize int 當 bufferedIO 為 true 時,可以配置此項的緩沖區大小,默認值為 8192 字節。 fileName String 要寫入的文件的名稱。如果文件或其任何父目錄不存在,則將創建它們。 name String 標識符 <RollingFile name="rolling-file-appender" fileName="logs/rolling-file-appender.log" filePattern="logs/rolling-file-appender-INFO-%d{yyyy-MM-dd}_%i.log.gz"> <PatternLayout> <Pattern>${file.pattern}</Pattern> </PatternLayout> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <Policies> <!-- TimeBasedTriggeringPolicy :時間滾動策略,默認0點小時產生新的文件 ,interval="6" : 自定義文件滾動時間間隔,每隔6小時產生新文件, modulate="true" : 產生文件是否以0點偏移時間,即6點,12點,18點,0點--> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- SizeBasedTriggeringPolicy: 當文件超過設定的大小就開始滾動--> <SizeBasedTriggeringPolicy size="1MB"/> </Policies> </RollingFile>
-
RollingRandomAccessFile 和 RollingFile 是一樣的,性能和 RandomAccessFile 差不多
Parameter Name Type Description append boolean 如果為 true ( 默認值),則記錄將追加到文件末尾。如果設置為 false,則在寫入新記錄之前將清除該文件。 fileName String 要寫入的文件的名稱。如果文件或其任何父目錄不存在,則將創建它們。 bufferSize int 當 bufferedIO 為 true 時,可以配置此項的緩沖區大小,默認值為 8192 字節。 name String 標識符 -
SMTP 通過郵箱發送日志信息
Parameter Name Type Description name String 標識符 from String 寄件者郵箱地址 replyTo String 以逗號分隔的接受者郵箱地址 to String 接受者郵箱地址 subject String 郵件的標題 bufferSize integer 當 bufferedIO 為 true 時,可以配置此項的緩沖區大小,默認值為 512。 smtpHost String SMTP HOST smtpPassword String SMTP 密碼 smtpPort integer SMTP 端口 smtpProtocol String SMTP 傳輸協議 smtps 或 smtp 默認是 smtp smtpUsername String smtp 用戶名 <SMTP name="mail-appender" subject="錯誤日志信息" to="發送到哪里" from="發送者" smtpHost="smtp.qiye.163.com" smtpPort="465" bufferSize="1" smtpUsername="SMTP用戶名" smtpPassword="SMTP密碼" smtpProtocol="smtps" mail.smtp.ssl.enable="true" mail.smtp.starttls.enable="true" > <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout> <Pattern>${file.pattern}</Pattern> </PatternLayout> </SMTP>
配置 SMTP 之后報錯
main ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.SmtpAppender for element SMTP: java.lang.NoClassDefFoundError: javax/mail/Authenticator java.lang.NoClassDefFoundError: javax/mail/Authenticator
是應為沒有找到 javax.mail 導入下面坐標即可。
<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.5.0-b01</version> </dependency>
Loggers
<Loggers>
<logger name="org.springframework" level="INFO"></logger>
<Root level="info">
<AppenderRef ref="console-appender"/>
<!-- <AppenderRef ref="file-appender"/>-->
<AppenderRef ref="rolling-file-appender"/>
<AppenderRef ref="async-appender"/>
<AppenderRef ref="random-access-file-appender"/>
<AppenderRef ref="rolling-random-access-file-appender"/>
<AppenderRef ref="mail-appender"/>
</Root>
</Loggers>
使用 Logger 配置各種 Appenders ,Logger 必須指定一個包路徑。還可以給這個包設置一個日志等級(TRACE、DEBUG、INFO、WARN、ERROR、ALL 或 OFF)。比如上面的 org.springframework
,如果未指定等級,默認為 ERROR。如果在標簽內設置 additivity 屬性如果為 true 則被該標簽捕獲的內容不會出現在 Root 節點。
<logger name="org.springframework" level="INFO"></logger>
Logger 也可以使用 AppenderRef 標簽來指定輸出位置和日志等級
<logger name="org.springframework" level="INFO">
<AppenderRef ref="console-appender" level="error"/>
</logger>
沒有使用 logger 標簽捕獲到的內容或者沒有設置additivity 為 true 的日志會出現在 Root 節點, Root 節點沒有 additivity。
<Root level="info">
<AppenderRef ref="console-appender"/>
<!-- <AppenderRef ref="file-appender"/>-->
<AppenderRef ref="rolling-file-appender"/>
<AppenderRef ref="async-appender"/>
<AppenderRef ref="random-access-file-appender"/>
<AppenderRef ref="rolling-random-access-file-appender"/>
<AppenderRef ref="mail-appender"/>
</Root>
PatternLayout
上面一直出現的 PatternLayout 標簽很明顯是日志輸出的格式。官方有一套自己的格式非常多,非常豐富。
%d:發生時間,%d{yyyy-MM-dd HH:mm:ss,SSS},輸出類似:2020-02-20 22:10:28,921
%F:輸出所在的類文件名
%t:線程名稱
%p:日志級別
%c:日志消息所在類名
%m:消息內容
%M:輸出所在函數名
%x: 輸出和當前線程相關聯的NDC(嵌套診斷環境),尤其用到像java servlets這樣的多客戶多線程的應用中。
%l:執行的函數名(類名稱:行號)com.core.LogHelper.aroundService(LogHelper.java:32)
%n:換行
%i:從1開始自增數字
%-5level:輸出日志級別,-5表示左對齊並且固定輸出5個字符,如果不足在右邊補0
${sys:user.home}是HOME目錄 如:C:\Users\heave, 此處指定任意目錄如:D:\logs
%highlight{} 高亮顏色 如:%highlight{%d [%t]}
%style{%d [%t]}{black} 設置高亮顏色 Red Green Yellow Blue Magenta Cyan White 還有一個 bold 高亮和其他顏色配合使用
例如: [%d{yyyy-MM-dd HH:mm:ss} %p][%c]: %m%n
更詳細的可以查看官方手冊 https://logging.apache.org/log4j/2.x/manual/layouts.html
部分內容來自:
[1]Log4j2 官網 https://logging.apache.org/log4j/2.x/
[2]Log4j2中文文檔 https://www.docs4dev.com/docs/zh/log4j2/2.x/all/