日誌文件是用於記錄系統操做事件的文件集合,可分爲事件日誌和消息日誌。具備處理歷史數據、診斷問題的追蹤以及理解系統的活動等重要做用。java
在計算機中,日誌文件是記錄在操做系統或其餘軟件運行中發生的事件或在通訊軟件的不一樣用戶之間的消息的文件。記錄是保持日誌的行爲。在最簡單的狀況下,消息被寫入單個日誌文件。mysql
許多操做系統,軟件框架和程序包括日誌系統。普遍使用的日誌記錄標準是在因特網工程任務組(IETF)RFC5424中定義的syslog。 syslog標準使專用的標準化子系統可以生成,過濾,記錄和分析日誌消息。sql
軟件開發中,咱們常常須要去調試程序,作一些信息,狀態的輸出便於咱們查詢程序的運行情況。爲了
讓咱們可以更加靈活和方便的控制這些調試的信息,全部咱們須要專業的日誌技術。java中尋找bug會
須要重現。調試也就是debug 能夠在程序運行中暫停程序運行,能夠查看程序在運行中的狀況。日誌主
要是爲了更方便的去重現問題。數據庫
系統日誌是記錄系統中硬件、軟件和系統問題的信息,同時還能夠監視系統中發生的事件。用戶能夠經過它來檢查錯誤發生的緣由,或者尋找受到攻擊時攻擊者留下的痕跡。系統日誌包括系統日誌、應用程序日誌和安全日誌。apache
系統日誌的價值
系統日誌策略能夠在故障剛剛發生時就向你發送警告信息,系統日誌幫助你在最短的時間內發現問題。數組
系統日誌是一種很是關鍵的組件,由於系統日誌可讓你充分了解本身的環境。這種系統日誌信息對於決定故障的根本緣由或者縮小系統攻擊範圍來講是很是關鍵的,由於系統日誌可讓你瞭解故障或者襲擊發生以前的全部事件。爲虛擬化環境制定一套良好的系統日誌策略也是相當重要的,由於系統日誌須要和許多不一樣的外部組件進行關聯。良好的系統日誌能夠防止你從錯誤的角度分析問題,避免浪費寶貴的排錯時間。另一種緣由是藉助於系統日誌,管理員頗有可能會發現一些以前從未意識到的問題,在幾乎全部剛剛部署系統日誌的環境當中。安全
問題:服務器
由於軟件系統發展到今天已經很複雜了,特別是服務器端軟件,涉及到的知識,內容,問題太多。在某些方面使用別人成熟的框架,就至關於讓別人幫你完成一些基礎工做,你只須要集中精力完成系統的業務邏輯設計。並且框架通常是成熟,穩健的,他能夠處理系統不少細節問題,好比,事務處理,安全性,數據流控制等問題。還有框架通常都通過不少人使用,因此結構很好,因此擴展性也很好,並且它是不斷升級的,你能夠直接享受別人升級代碼帶來的好處。網絡
JUL(java util logging)、logback、log4j、log4j2
JCL(Jakarta Commons Logging)、slf4j( Simple Logging Facade for Java)架構
日誌門面
JCL、slf4j
日誌實現
JUL、logback、log4j、log4j2
JUL全稱Java util Logging是java原生的日誌框架,使用時不須要另外引用第三方類庫,相對其餘日誌框架使用方便,學習簡單,可以在小型應用中靈活使用。
總結一下就是:
用戶使用Logger來進行日誌記錄,Logger持有若干個Handler,日誌的輸出操做是由Handler完成的。在Handler在輸出日誌前,會通過Filter的過濾,判斷哪些日誌級別過濾放行哪些攔截,Handler會將日誌內容輸出到指定位置(日誌文件、控制檯等)。Handler在輸出日誌時會使用Layout,將輸出內容進行排版。
public class JULTest { @Test public void testQuick() throws Exception { // 1.建立日誌記錄器對象 Logger logger = Logger.getLogger("com.itheima.log.JULTest"); // 2.日誌記錄輸出 logger.info("hello jul"); logger.log(Level.INFO, "info msg"); String name = "jack"; Integer age = 18; logger.log(Level.INFO, "用戶信息:{0},{1}", new Object[]{name, age}); } }
jul中定義的日誌級別
雖然咱們測試了7個日誌級別可是默認只實現info以上的級別
@Test public void testLogLevel() throws Exception { // 1.獲取日誌對象 Logger logger = Logger.getLogger("com.itheima.log.QuickTest"); // 2.日誌記錄輸出 logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("cofnig"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
自定義日誌級別配置
@Test public void testLogConfig() throws Exception { // 1.建立日誌記錄器對象 Logger logger = Logger.getLogger("com.itheima.log.JULTest"); // 1、自定義日誌級別 // a.關閉系統默認配置 logger.setUseParentHandlers(false); // b.建立handler對象 ConsoleHandler consoleHandler = new ConsoleHandler(); // c.建立formatter對象 SimpleFormatter simpleFormatter = new SimpleFormatter(); // d.進行關聯 consoleHandler.setFormatter(simpleFormatter); logger.addHandler(consoleHandler); // e.設置日誌級別 logger.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); // 2、輸出到日誌文件 FileHandler fileHandler = new FileHandler("d:/logs/jul.log"); fileHandler.setFormatter(simpleFormatter); logger.addHandler(fileHandler); // 2.日誌記錄輸出 logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
JUL中Logger之間存在父子關係,這種父子關係經過樹狀結構存儲,JUL在初始化時會建立一個頂層RootLogger做爲全部Logger父Logger,存儲上做爲樹狀結構的根節點。並父子關係經過路徑來關聯。
@Test public void testLogParent() throws Exception { // 日誌記錄器對象父子關係 Logger logger1 = Logger.getLogger("com.itheima.log"); Logger logger2 = Logger.getLogger("com.itheima"); System.out.println(logger1.getParent() == logger2); // 全部日誌記錄器對象的頂級父元素 class爲java.util.logging.LogManager$RootLogger name爲"" System.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName()); // 1、自定義日誌級別 // a.關閉系統默認配置 logger2.setUseParentHandlers(false); // b.建立handler對象 ConsoleHandler consoleHandler = new ConsoleHandler(); // c.建立formatter對象 SimpleFormatter simpleFormatter = new SimpleFormatter(); // d.進行關聯 consoleHandler.setFormatter(simpleFormatter); logger2.addHandler(consoleHandler); // e.設置日誌級別 logger2.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); // 測試日誌記錄器對象父子關係 logger1.severe("severe"); logger1.warning("warning"); logger1.info("info"); logger1.config("config"); logger1.fine("fine"); logger1.finer("finer"); logger1.finest("finest"); }
默認配置文件路徑$JAVAHOME\jre\lib\logging.properties
@Test public void testProperties() throws Exception { // 讀取自定義配置文件 InputStream in = JULTest.class.getClassLoader().getResourceAsStream("logging.properties"); // 獲取日誌管理器對象 LogManager logManager = LogManager.getLogManager(); // 經過日誌管理器加載配置文件 logManager.readConfiguration(in); Logger logger = Logger.getLogger("com.itheima.log.JULTest"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
配置文件:
## RootLogger使用的處理器(獲取時設置) handlers= java.util.logging.ConsoleHandler # RootLogger日誌等級 .level= INFO ## 自定義Logger com.itheima.handlers= java.util.logging.FileHandler # 自定義Logger日誌等級 com.itheima.level= INFO # 忽略父日誌設置 com.itheima.useParentHandlers=false ## 控制檯處理器 # 輸出日誌級別 java.util.logging.ConsoleHandler.level = INFO # 輸出日誌格式 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter ## 文件處理器 # 輸出日誌級別 java.util.logging.FileHandler.level=INFO # 輸出日誌格式 java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter # 輸出日誌文件路徑 java.util.logging.FileHandler.pattern = /java%u.log # 輸出日誌文件限制大小(50000字節) java.util.logging.FileHandler.limit = 50000 # 輸出日誌文件限制個數 java.util.logging.FileHandler.count = 10 # 輸出日誌文件 是不是追加 java.util.logging.FileHandler.append=true
Log4j是Apache下的一款開源的日誌框架,經過在項目中使用 Log4J,咱們能夠控制日誌信息輸出到控制檯、文件、甚至是數據庫中。咱們能夠控制每一條日誌的輸出格式,經過定義日誌的輸出級別,能夠更靈活的控制日誌的輸出過程。方便項目的調試。
官方網站: http://logging.apache.org/log4j/1.2/
添加依賴
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
java代碼
public class Log4jTest { @Test public void testQuick() throws Exception { // 初始化系統配置,不須要配置文件 BasicConfigurator.configure(); // 建立日誌記錄器對象 Logger logger = Logger.getLogger(Log4jTest.class); // 日誌記錄輸出 logger.info("hello log4j"); // 日誌級別 logger.fatal("fatal"); // 嚴重錯誤,通常會形成系統崩潰和終止運行 logger.error("error"); // 錯誤信息,但不會影響系統運行 logger.warn("warn"); // 警告信息,可能會發生問題 logger.info("info"); // 程序運行信息,數據庫的鏈接、網絡、IO操做等 logger.debug("debug"); // 調試信息,通常在開發階段使用,記錄程序的變量、參數等 logger.trace("trace"); // 追蹤信息,記錄程序的全部流程信息 } }
還有兩個特殊的級別:
OFF,可用來關閉日誌記錄。
ALL,啓用全部消息的日誌記錄。
注:通常只使用4個級別,優先級從高到低爲 ERROR > WARN > INFO > DEBUG
Log4J 主要由 Loggers (日誌記錄器)、Appenders(輸出端)和 Layout(日誌格式化器)組成。其中Loggers 控制日誌的輸出級別與日誌是否輸出;Appenders 指定日誌的輸出方式(輸出到控制檯、文件等);Layout 控制日誌信息的輸出格式。
日誌記錄器,負責收集處理日誌記錄,實例的命名就是類「XX」的full quailied name(類的全限定名),Logger的名字大小寫敏感,其命名有繼承機制:例如:name爲org.apache.commons的logger會繼承name爲org.apache的logger。
Log4J中有一個特殊的logger叫作「root」,他是全部logger的根,也就意味着其餘全部的logger都會直接或者間接地繼承自root。root logger能夠用Logger.getRootLogger()方法獲取。
可是,自log4j 1.2版以來, Logger 類已經取代了 Category 類。對於熟悉早期版本的log4j的人來講,
Logger 類能夠被視爲 Category 類的別名。
Appender 用來指定日誌輸出到哪一個地方,能夠同時指定日誌的輸出目的地。Log4j 經常使用的輸出目的地有如下幾種:
輸出端類型 | 做用 |
---|---|
ConsoleAppender | 將日誌輸出到控制檯 |
FileAppender | 將日誌輸出到文件中 |
DailyRollingFileAppender | 將日誌輸出到一個日誌文件,而且天天輸出到一個新的文件 |
RollingFileAppender | 將日誌信息輸出到一個日誌文件,而且指定文件的尺寸,當文件大小達到指定尺寸時,會自動把文件更名,同時產生一個新的文件 |
JDBCAppender | 把日誌信息保存到數據庫中 |
4.2.3 Layouts
佈局器 Layouts用於控制日誌輸出內容的格式,讓咱們可使用各類須要的格式輸出日誌。Log4j經常使用的Layouts:
格式化器類型 | 做用 |
---|---|
HTMLLayout | 格式化日誌輸出爲HTML表格形式 |
SimpleLayout | 簡單的日誌輸出格式化,打印的日誌格式爲(info - message) |
PatternLayout | 最強大的格式化期,能夠根據自定義格式輸出日誌,若是沒有指定轉換格式,就是用默認的轉換格式 |
4.3 Layout的格式
在 log4j.properties 配置文件中,咱們定義了日誌輸出級別與輸出端,在輸出端中分別配置日誌的輸出
格式。
控制檯,文件,數據庫
#指定日誌的輸出級別與輸出端 log4j.rootLogger=INFO,Console # 控制檯輸出配置 log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n # 文件輸出配置 log4j.appender.A = org.apache.log4j.DailyRollingFileAppender #指定日誌的輸出路徑 log4j.appender.A.File = D:/log.txt log4j.appender.A.Append = true #使用自定義日誌格式化器 log4j.appender.A.layout = org.apache.log4j.PatternLayout #指定日誌的輸出格式 log4j.appender.A.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] -[%p] %m%n #指定日誌的文件編碼 log4j.appender.A.encoding=UTF-8 #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/test 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')
CREATE TABLE `log` ( `log_id` int(11) NOT NULL AUTO_INCREMENT, `project_name` varchar(255) DEFAULT NULL COMMENT '目項名', `create_date` varchar(255) DEFAULT NULL COMMENT '建立時間', `level` varchar(255) DEFAULT NULL COMMENT '優先級', `category` varchar(255) DEFAULT NULL COMMENT '所在類的全名', `file_name` varchar(255) DEFAULT NULL COMMENT '輸出日誌消息產生時所在的文件名稱 ', `thread_name` varchar(255) DEFAULT NULL COMMENT '日誌事件的線程名', `line` varchar(255) DEFAULT NULL COMMENT '號行', `all_category` varchar(255) DEFAULT NULL COMMENT '日誌事件的發生位置', `message` varchar(4000) DEFAULT NULL COMMENT '輸出代碼中指定的消息', PRIMARY KEY (`log_id`) );
# RootLogger配置 log4j.rootLogger = trace,console # 自定義Logger log4j.logger.com.itheima = info,file log4j.logger.org.apache = error
@Test public void testCustomLogger() throws Exception { // 自定義 com.itheima Logger logger1 = Logger.getLogger(Log4jTest.class); logger1.fatal("fatal"); // 嚴重錯誤,通常會形成系統崩潰和終止運行 logger1.error("error"); // 錯誤信息,但不會影響系統運行 logger1.warn("warn"); // 警告信息,可能會發生問題 logger1.info("info"); // 程序運行信息,數據庫的鏈接、網絡、IO操做等 logger1.debug("debug"); // 調試信息,通常在開發階段使用,記錄程序的變量、參數等 logger1.trace("trace"); // 追蹤信息,記錄程序的全部流程信息 // 自定義 org.apache Logger logger2 = Logger.getLogger(Logger.class); logger2.fatal("fatal logger2"); // 嚴重錯誤,通常會形成系統崩潰和終止運行 logger2.error("error logger2"); // 錯誤信息,但不會影響系統運行 logger2.warn("warn logger2"); // 警告信息,可能會發生問題 logger2.info("info logger2"); // 程序運行信息,數據庫的鏈接、網絡、IO操做等 logger2.debug("debug logger2"); // 調試信息,通常在開發階段使用,記錄程序的變量、參數等 logger2.trace("trace logger2"); // 追蹤信息,記錄程序的全部流程信息 }
全稱爲Jakarta Commons Logging,是Apache提供的一個通用日誌API。
它是爲「全部的Java日誌實現」提供一個統一的接口,它自身也提供一個日誌的實現,可是功能很是常弱(SimpleLog)。因此通常不會單獨使用它。他容許開發人員使用不一樣的具體日誌實現工具: Log4j, Jdk自帶的日誌(JUL)
JCL 有兩個基本的抽象類:Log(基本記錄器)和LogFactory(負責建立Log實例)。
添加依賴
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
入門代碼
public class JULTest { @Test public void testQuick() throws Exception { // 建立日誌對象 Log log = LogFactory.getLog(JULTest.class); // 日誌記錄輸出 log.fatal("fatal"); log.error("error"); log.warn("warn"); log.info("info"); log.debug("debug"); } }
咱們爲何要使用日誌門面:
日誌門面支持的日誌實現數組
private static final String[] classesToDiscover = new String[]{"org.apache.commons.logging.impl.Log4JLogger", "org.apache.commons.logging.impl.Jdk14Logger", "org.apache.commons.logging.impl.Jdk13LumberjackLogger", "org.apache.commons.logging.impl.SimpleLog"};
獲取具體的日誌實現
for(int i = 0; i < classesToDiscover.length && result == null; ++i) { result = this.createLogFromClass(classesToDiscover[i], logCategory, true); }