一、Log4j的簡介
Log4J 是 Apache 的一個開源項目(官網 http://jakarta.apache.org/log4j),通過在項目中使用 Log4J,我們可以控制日誌信息輸出到控制檯、文件、GUI 組件、甚至是數據庫中。我們可以控制每一條日誌的輸出格式,通過定義日誌的輸出級別,可以更靈活的控制日誌的輸出過程。方便項目的調試。
1.Log4j組件:
Log4j主要由以下幾個組件組成:
Loggers(日誌記錄器):控制日誌的輸出級別與日誌是否輸出;
Appenders(輸出端):指定日誌的輸出格式(輸出到控制檯、文件等);
Layout(日誌格式輸出器):控制日誌信息的輸出格式。
Log4j中有一個特殊的logger叫做“root”,他是所有Logger的根,也就意味着其他所有的logger都會直接或者間接地繼承自root.
root logger可以用Logger.getRootLogger()方法獲取。
2.Appenders:用來指定日誌輸出到哪個地方,可以同時指定日誌地輸出目的地,Log4j常用的輸出目的地有一下幾種:
輸出端類型 | 作用 |
ConsoleAppender | 將日誌輸出到控制檯 |
FileAppender | 將日誌輸出到文件中 |
DailyRollingFileAppender | 將日誌輸出到一個日誌文件,並且每天輸出到一個新的文件 |
RollingFileAppender | 將日誌信息輸出到一個日誌文件,並且指定文件的尺寸,當文件大小達到指定尺寸時,會自動把文件改名,同時產生一個新的文件 |
JDBCAppender | 把日誌信息保存到數據庫中 |
3.Layouts:佈局器Layouts用於控制日誌輸出內容的格式,讓我們可以使用各種需要的格式輸出日誌,Log4j常用的Layouts:
格式化類型 | 作用 |
HTMLLayout | 格式化日誌輸出爲HTML表格形式 |
SimpleLayout | 簡單的日誌輸出格式化,打印的日誌格式爲(info message) |
PatternLayout | 最強大的格式化期,可以根據自定義格式輸出日誌,如果沒有指定的轉化格式,就是用默認的轉化格式 |
xml.XMLLayout | XML格式輸出 |
4.Layout的格式:在Log4j.properties配置文件中,我們定義了日誌輸出級別與輸出端。在輸出端中分別配置日誌的輸出格式。
(1)Log4j採用類似C語言的printf函數的打印格式格式化日誌信息,具體的佔位符及其含義如下:
佔位符 | 含義 |
%m | 輸出代碼中指定的日誌信息 |
%p | 輸出優先級、及DEBUG、INFO等 |
%n | 換行符 |
%r | 輸出自應用啓動到輸出該log信息耗費的毫秒數 |
%c | 輸出打印語句所屬的類的全名 |
%t | 輸出產生該日誌的線程全名 |
%d | 輸出服務器當前時間,默認爲ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss} |
%l | 輸出日誌時間發生的位置,包括類名、線程、及在代碼中的行數 |
%F | 輸出日誌消息產生時所在的文件名稱 |
%L | 輸出代碼中的行號 |
%% | 輸出一個“%”字符 |
(2)可以在%與字符之間加上修飾符來控制最小寬度、最大寬度和文本的對其方式
佔位符 | 含義 |
%5c | 輸出category名稱,最小寬度是5,category<5,默認的情況下右對齊 |
%-5c | 輸出category名稱,最小寬度是5,category<5,"_"是指定左對齊,會有空格 |
%.5c | 輸出category名稱,最大寬度是5,category>5.就會將左邊多出的字符截掉,<5不會有空格 |
%20.30c | 輸出category名稱<20補空格,並且右對齊;輸出category名稱>30字符,就從左邊較遠輸出的字符截掉 |
二、快速入門
首先在 maven 中引入 log4j 的依賴:
<!-- log日誌 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
創建 Log4jTest 類,測試 Log4j 的使用:
@Test
public void testQuick() throws Exception{
// 開啓log4j內置日誌記錄
LogLog.setInternalDebugging(true);
// 初始化配置信息,在入門案例中暫不使用配置文件
BasicConfigurator.configure();
// 獲取日誌記錄器對象
Logger logger = Logger.getLogger(Log4jDemo.class);
// 日誌記錄輸出
logger.info("hello log4j");
// 日誌級別
//設置日誌輸出級別爲WARN,這將覆蓋配置文件中設置的級別,只有日誌級別高於WARN的日誌才輸出
logger.setLevel(Level.WARN);
logger.fatal("fatal");//嚴重錯誤,一般會造成系統崩潰並終止運行
logger.error("error");//錯誤信息,不會影響系統運行
logger.warn("warn"); //警告信息,可能會發生問題
logger.info("info"); //運行信息,數據連接、網絡連接、IO操作等等
logger.debug("debug");//調試信息,一般在開發中使用,記錄程序變量參數傳遞信息等等
logger.trace("trace");//追蹤信息,記錄程序所有的流程信息
// 在獲取一個日誌記錄器對象
Logger logger1 = Logger.getLogger(Logger.class);
logger1.fatal("fatal logger1");//嚴重錯誤,一般會造成系統崩潰並終止運行
logger1.error("error logger1");//錯誤信息,不會影響系統運行
logger1.warn("warn logger1"); //警告信息,可能會發生問題
logger1.info("info logger1"); //運行信息,數據連接、網絡連接、IO操作等等
logger1.debug("debug logger1");//調試信息,一般在開發中使用,記錄程序變量參數傳遞信息等等
logger1.trace("trace logger1");//追蹤信息,記錄程序所有的流程信息
}
這裏首先通過 Logger.getLogger(Log4Test.class) 創建 Logger 實例,然後調用 BasicConfigurator.configure() 方法指定該 Logger 使用默認的配置信息,接着調用 looger.setLevel(Level.WARN) 設置 Logger 的日誌輸出級別爲 WARN 。運行 main 函數,控制檯將會輸出 warn 以上的錯誤信息。控制檯輸出如下:
0 [main] INFO LoggerDemo.Log4jDemo - hello log4j
5 [main] FATAL LoggerDemo.Log4jDemo - fatal
5 [main] ERROR LoggerDemo.Log4jDemo - error
5 [main] WARN LoggerDemo.Log4jDemo - warn
6 [main] FATAL org.apache.log4j.Logger - fatal logger1
6 [main] ERROR org.apache.log4j.Logger - error logger1
6 [main] WARN org.apache.log4j.Logger - warn logger1
7 [main] INFO org.apache.log4j.Logger - info logger1
7 [main] DEBUG org.apache.log4j.Logger - debug logger1
7 [main] TRACE org.apache.log4j.Logger - trace logger1
注:如果沒有調用 BasicConfigurator.configure() 方法,則運行 main 函數的時候則會報錯,因爲 Log4j 框架在運行的時候會加載項目路徑下的 log4j.properties 配置文件(關於配置文件的使用,會在後面講解)。而我們此時的項目中是沒有該文件的。如果配置文件的名稱不是 log4j.properties,則可以通過 PropertyConfigurator.configure(String configFilename) 指定配置文件的名稱。
格式化器的使用
修改 Log4JTest 中的代碼:
public class Log4JTest {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Log4JTest.class);
BasicConfigurator.configure();
HTMLLayout layout = new HTMLLayout();
// SimpleLayout layout = new SimpleLayout();
try {
FileAppender appender = new FileAppender(layout, "D:\\out.html", false);
logger.addAppender(appender);
//設置日誌輸出級別爲info,這將覆蓋配置文件中設置的級別,只有日誌級別高於WARN的日誌才輸出
logger.setLevel(Level.WARN);
logger.debug("這是debug");
logger.info("這是info");
logger.warn("這是warn");
logger.error("這是error");
logger.fatal("這是fatal");
} catch (IOException e) {
e.printStackTrace();
}
}
}
首先創建一個HTML格式的格式化器(HTMLLayout),然後創建文件輸出端(FileAppender)指定輸出端的格式爲 HTML 格式,這裏我指定輸出路徑爲 D 盤下的 out.html 文件。然後通過 logger.addAppender(appender) 將文件輸出端加載到 Logger 中。運行 main 函數,在 D 盤下會生成一個 out.html 文件,打開文件,裏面的信息就是代碼中輸出的日誌信息:
log4j.properties 配置文件的使用
上面使用代碼的方式設置 Logger 的輸出格式,這樣在我們每個要輸出日誌的類上都得設置一遍配置未免也太麻煩了吧。有一種更加方便的方法,我們只需要在項目路徑下新建 log4j.properties 配置文件,並配置日誌的輸出格式等信息,Log4J 框架會自動的加載配置文件,並將配置信息設置到 Logger 中。最簡單的配置文件如下:
#配置根 Loggers控制日誌的輸出級別與日誌是否輸出
log4j.rootLogger=trace,console
#自定義logger對象設置
log4j.logger.LoggerDemo = info,file
#配置輸出到控制檯 Appenders是指定日誌的輸出方式
log4j.appender.console=org.apache.log4j.ConsoleAppender
#指定輸出控制檯
log4j.appender.console.Target = System.out
#指定佈局,輸出日誌的格式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#指定佈局的參數
log4j.appender.console.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#配置輸出到控制檯 Appenders是指定日誌的輸出方式
log4j.appender.file=org.apache.log4j.FileAppender
#指定佈局,輸出日誌的格式
log4j.appender.file.layout=org.apache.log4j.PatternLayout
#指定佈局的參數
log4j.appender.file.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日誌文件保存路徑
log4j.appender.file.file = /logs/log4j.log
#指定日誌文件字符集
log4j.appender.file.encoding = UTF-8
#配置輸出到控制檯 Appenders是指定日誌的輸出方式
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
#指定佈局,輸出日誌的格式
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
#指定佈局的參數
log4j.appender.rollingFile.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日誌文件保存路徑
log4j.appender.rollingFile.file = /logs/log4j.log
#指定日誌文件字符集
log4j.appender.rollingFile.encoding = UTF-8
#指定日誌文件內容的大小
log4j.appender.rollingFile.maxFileSize = 1MB
#指定日誌文件的數量
log4j.appender.rollingFile.maxBackupIndex = 10
#配置輸出到控制檯 Appenders是指定日誌的輸出方式
log4j.appender.dailyRollingFile=org.apache.log4j.DailyRollingFileAppender
#指定佈局,輸出日誌的格式
log4j.appender.dailyRollingFile.layout=org.apache.log4j.PatternLayout
#指定佈局的參數
log4j.appender.dailyRollingFile.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日誌文件保存路徑
log4j.appender.dailyRollingFile.file = /logs/log4j.log
#指定日誌文件字符集
log4j.appender.dailyRollingFile.encoding = UTF-8
#指定日誌輸出規則
log4j.appender.dailyRollingFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss
#mysql
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
#指定佈局,輸出日誌的格式
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver = com.mysql.jdbc.Driver
log4j.appender.logDB.URL = jdbc:mysql://localhost:3306/logs
log4j.appender.logDB.User = root
log4j.appender.logDB.Password = root
log4j.appender.logDB.Sql = INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('itcast','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
使用JDBCAppender導出日誌格式時,數據庫設計如下:
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`log_id` int(11) NOT NULL AUTO_INCREMENT,
`project_name` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '項目名',
`create_date` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '創建時間',
`level` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '優先級',
`category` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '所在類的全名',
`file_name` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '輸出日誌消息產生時所在的文件名稱',
`thread_name` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '日誌事件的線程名',
`line` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '行號',
`all_category` varchar(255) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '日誌事件的發生位置',
`message` varchar(4000) COLLATE utf8_general_mysql500_ci DEFAULT NULL COMMENT '輸出代碼中指定的消息',
PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=30013 DEFAULT CHARSET=utf8 COLLATE=utf8_general_mysql500_ci;