1. 程式人生 > 程式設計 >Log4j 筆記

Log4j 筆記

Log4j 似乎已經被淘汰了為什麼還要寫這篇文章?

log4j、log4j2、logback 從基礎思想上三者的實現是一致的,無非就是輸出內容到檔案,且看配置檔案也都大同小異(logger、appender、layout),無非後兩者比前者具有更多的高階功能,此塊可以單獨拎出講。所以如果想了解本質,從最開始的版本開始會比較好下手。

簡單體驗

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version
>
</dependency> 複製程式碼

測試類:

public static void main(String[] args) {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.debug("log4j debug");
    logger.info("log4j info");
    logger.error("log4j error");
}
複製程式碼

輸出到控制檯:log4j.properties

# 定義一個名為 csAppender 的日誌附加器
log4j.appender.csAppender=org.apache.log4j.ConsoleAppender
log4j.appender.csAppender.Threshold=INFO
log4j.appender.csAppender.Target=System.out
log4j.appender.csAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.csAppender.layout.ConversionPattern=[%d] [%t] [%c.%M:%L] [%-5p]: %m%n

# 配置根日誌級別為 debug,並設定輸出器為剛定義的 csAppender
log4j.rootLogger=debug,csAppender
複製程式碼

輸出到檔案:log4j.properties

# 定義一個名為 fileAppender 的日誌附加器
log4j.appender.fileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileAppender.Threshold=INFO
log4j.appender.fileAppender.File=D://data//usr//local//logs//home//log4j-log.log
log4j.appender.fileAppender.DatePattern = '.'yyyy-MM-dd'.log'
log4j.appender.fileAppender.Encoding=UTF-8
log4j.appender.fileAppender.Append=true
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=[%d] [%t] [%-5p] [%c.%M:%L]: %m%n
# 配置根日誌級別為 debug,並設定輸出器為剛定義的 fileAppender
log4j.rootLogger=debug,fileAppender
複製程式碼

上面示例配置中的 root 日誌例項分別使用 csAppender(控制檯)、fileAppender(檔案)附加器將日誌內容輸出到目的地。當然也可以同時輸出。log4j 官網並沒有對配置進行說明,但在 org.apache.log4j.PropertyConfigurator#doConfigure 方法註釋上可看到完整的說明。

第一步需要配置根 Logger 格式如下:

log4j.rootLogger = [level],appenderName1,appenderName2,…
複製程式碼
  • level 設定日誌記錄的最低階別,可設的值有 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定義的級別,比如在這裡設定了INFO級別,則應用程式中所有DEBUG級別的日誌資訊將不會被打印出來。

  • appenderName

    就是指定日誌資訊要輸出到哪裡。可以同時指定多個輸出目的地,用逗號隔開。 例如:log4j.rootLogger=INFO,A1,B2,C3

第二步配置日誌資訊輸出目的地(appender)格式如下:

# For appender named
log4j.appender.appenderName=fully.qualified.name.of.appender.class
# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
複製程式碼

三大元件

Log4j has three main components: loggers,appenders and layouts. These three types of components work together to enable developers to log messages according to message type and level,and to control at runtime how these messages are formatted and where they are reported.

Log4j 有三個主要的元件:Loggers(記錄器),Appenders (輸出源)和 Layouts(佈局)。這裡可簡單理解為日誌類別,日誌要輸出的地方和日誌以何種形式輸出。綜合使用這三個元件可以輕鬆地記錄資訊的型別和級別,並可以在執行時控制日誌輸出的樣式和位置。

Logger

Loggers 元件在此係統中被分為五個級別:DEBUG、INFO、WARN、ERROR和FATAL。這五個級別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,分別用來指定這條日誌資訊的重要程度。Log4j 有一個規則:只輸出級別不低於設定級別的日誌資訊。假設 Loggers 級別設定為 INFO,則 INFO、WARN、ERROR 和 FATAL 級別的日誌資訊都會輸出,而級別比 INFO 低的 DEBUG 則不會輸出。

定義 logger

Log4J 中總是存在一個 rootLogger,即使沒有顯示配置也是存在的,並且預設輸出級別為 DEBUG。其它的 logger 都繼承自這個 rootLogger(如果其他logger未單獨定義其輸出級別)。

其次,Log4J 中的層次(Hierarchy)是用 '.' 來分隔的,如 log4j.logger.com.example.test,並不是說 log4j.logger 後面一定是具體的包名乃至類名,這個名稱可以自定義,我們甚至可以定義一個log4j.logger.A.B.C,如下例所示,建立了 3 個 logger 例項,它們分別是 AA.BA.B.C

## log4j.properties
log4j.logger.A.B.C = ERROR,appenderName
## 在程式碼中獲取名為 A.B 的日誌物件
Logger logger = Logger.getLogger("A.B")
複製程式碼

當獲取不到當前需要的 logger 時,查詢動作會傳遞,直到 root 節點仍沒找到對應名字的 logger,就返回 root logger 例項。

Appender

Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy

log4j 官網這句話的意思是,logger 物件可以繼承,且 appender 是可以累加的。當呼叫層次較低的 logger 物件輸出日誌時,log4j 會把該請求輸出到當前所有附加在此 logger 上的所有 appender。

假設存在如下配置檔案:

log4j.rootLogger=DEBUG,consoleAppender

log4j.logger.com=DEBUG,consoleAppender
log4j.logger.com.A.B=INFO,consoleAppender
log4j.logger.com.X=INFO,consoleAppender

## ... 省略 consoleAppender 配置
複製程式碼

則 log4j 日誌容器中存在如下圖示例項關係:

對於名為 A.B 的 logger 輸出的日誌會往控制檯輸出三次,原因是 A.B 繼承 A 的以及A 的父 logger 的所有 appender,這種繼承關係僅僅是把父 logger 的 appender 新增到自己的 appender 列表中,父 logger 的輸出 level 不會影響子 logger 的輸出。

log4j.rootLogger=DEBUG,consoleAppender
log4j.logger.A=DEBUG,consoleAppender
log4j.logger.A.B=INFO,consoleAppender
log4j.additivity.A.B=false
複製程式碼

名為 A.B 的 logger 日誌僅會輸出到自己的 appender 中,不會繼承任何父 logger 的 appender。

若想對輸出到 appender 中的日誌級別進行限制的話,就需要用到 threshold 來控制。

log4j.threshold=ERROR
複製程式碼

用來控制所有的 appender,即輸出到所有appender的日誌,不管原來是什麼級別的,都不能低於threshold所規定的級別。

log4j.appender.Console.threshold=ERROR 
複製程式碼

用來控制指定的 appender 的輸出級別。

Log4j 日誌系統還提供許多強大的功能,比如允許把日誌輸出到不同的地方,如控制檯(Console)、檔案(Files)等,可以根據天數或者檔案大小產生新的檔案,可以以流的形式傳送到其它地方等等。

控制檯(console)

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
複製程式碼

日誌檔案(logFile)

log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
複製程式碼

回滾檔案(rollingFile)

  • Threshold=WARN:指定日誌資訊的最低輸出級別,預設為DEBUG
  • ImmediateFlush=true:表示所有訊息都會被立即輸出,設為false則不輸出,預設值是true。
  • Append=false:true表示訊息增加到指定檔案中,false則將訊息覆蓋指定的檔案內容,預設值是true。
  • File=D:/logs/logging.log4j:指定訊息輸出到logging.log4j檔案中。
  • MaxFileSize=100KB:字尾可以是KB,MB 或者GB。在日誌檔案到達該大小時,將會自動滾動,即將原來的內容移到logging.log4j.1檔案中。
  • MaxBackupIndex=2:指定可以產生的滾動檔案的最大數,例如,設為2則可以產生logging.log4j.1,logging.log4j.2兩個滾動檔案和一個logging.log4j檔案。
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
複製程式碼

定期回滾日誌檔案(dailyFile)

DatePattern='.'yyyy-MM:即每月產生一個新的日誌檔案。當前月的日誌檔名為 logging.log4j,前一個月的日誌檔名為 logging.log4j.yyyy-MM。另外,也可以指定按周、天、時、分等來滾動日誌檔案,對應的格式如下:

- yyyy-MM:每月
- yyyy-ww:每週
- yyyy-MM-dd:每天
- yyyy-MM-dd-a:每天兩次
- yyyy-MM-dd-HH:每小時
- yyyy-MM-dd-HH-mm:每分鐘
複製程式碼
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
複製程式碼

應用於 socket

log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
複製程式碼

傳送日誌到指定郵件

log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = [email protected]
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= [email protected]
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
複製程式碼

應用於資料庫

log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
複製程式碼

Layout

有時使用者希望根據自己的喜好格式化自己的日誌輸出,Log4j 可以在 Appenders 的後面附加Layouts來完成這個功能。Layouts 提供四種日誌輸出樣式,如根據HTML樣式、自由指定樣式、包含日誌級別與資訊的樣式和包含日誌時間、執行緒、類別等資訊的樣式。常使用的類如下:

- org.apache.log4j.HTMLLayout(以HTML表格形式佈局)
- org.apache.log4j.PatternLayout(可以靈活地指定佈局模式)
- org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串)
- org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等資訊)
複製程式碼

格式化符號說明

%p:輸出日誌資訊的優先順序,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:輸出日誌時間點的日期或時間,預設格式為ISO8601,也可以在其後指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:輸出自應用程式啟動到輸出該log資訊耗費的毫秒數。
%t:輸出產生該日誌事件的執行緒名。
%l:輸出日誌事件的發生位置,相當於%c.%M(%F:%L)的組合,包括類全名、方法、檔名以及在程式碼中的行數。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:輸出日誌資訊所屬的類目,通常就是所在類的全名。
%M:輸出產生日誌資訊的方法名。
%F:輸出日誌訊息產生時所在的檔名稱。
%L::輸出程式碼中的行號。
%m::輸出程式碼中指定的具體日誌資訊。
%n:輸出一個回車換行符,Windows平臺為"rn",Unix平臺為"n"。
%x:輸出和當前執行緒相關聯的NDC(巢狀診斷環境),尤其用到像java servlets這樣的多客戶多執行緒的應用中。
%%:輸出一個"%"字元。
另外,還可以在%與格式字元之間加上修飾符來控制其最小長度、最大長度、和文字的對齊方式。如:
1) c:指定輸出category的名稱,最小的長度是20,如果category的名稱長度小於20的話,預設的情況下右對齊。
2)%-20c:"-"號表示左對齊。
3)%.30c:指定輸出category的名稱,最大的長度是30,如果category的名稱長度大於30的話,就會將左邊多出的字元截掉,但小於30的話也不會補空格。
複製程式碼

實戰分析

定義兩個 appender 分別輸出到控制檯和檔案,針對名為 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager 日誌輸出級別調成 ERROR,且禁用 appender 繼承,只在當前 logger 的 appender 中輸出。在類 UnifiedServiceManager 中若是使用如下方式獲取 logger 則日誌只有在 ERROR 級別及以上會輸出

Logger logger1 = Logger.getLogger(UnifiedServiceManager.class)
複製程式碼

分析 Logger getLogger(Class clazz) 原始碼可知,預設使用類全路徑作為 loggerName 傳入。故獲取到的 logger1 即為配置檔案中指定名為 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager 的日誌物件。

使用技巧

在 .properties 配置檔案中定義變數

LOG_HOME=D://data//usr//local//logs//home1

log4j.rootLogger=debug,fileAppender
# ...
log4j.appender.fileAppender.File=${LOG_HOME}//log4j-log.log
複製程式碼

差不多是隱藏功能了...

log4j 不同模組輸出到不同的檔案

不同模組:以包名為 loggerName 定義多個 logger 例項

不同檔案:定義多個 fileAppender,並與對應的 loggerName 的 logger 例項關聯

參考:www.cnblogs.com/0201zcr/p/5…

日誌輸出動態改變路徑

參考:blog.csdn.net/wiwipetter/…

參考