002_Java日志
1. Level對象
1.1. Level類定義了一組可用來控制日志輸出的標準日志級別。日志Level對象是有序的, 并且是通過有序的整數來指定。在給定的級別上啟用日志記錄也就啟用了所有較高級別的日志記錄。
1.2. 各級別按降序排列如下:
- SEVERE(最高值)
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST(最低值)
1.3. 此外, 還有一個級別OFF, 可用來關閉日志記錄, 使用級別ALL啟用所有消息的日志記錄。
1.4. public static final Level OFF是一個可用于關閉日志記錄的特殊級別。此級別初始化為Integer.MAX_VALUE。
1.5. public static final Level SEVERE是指示嚴重失敗的消息級別。通常, SEVERE消息應該描述相當重要的事件, 這些事件會阻止正常程序的執行。它們對于最終用戶和系統管理員來說應該是很容易理解的。此級別初始化為1000。
1.6. public static final Level WARNING是指示潛在問題的消息級別。通常, WARNING消息應該描述最終用戶或系統管理員感興趣的事件或者那些指示潛在問題的事件。此級別初始化為900。
1.7. public static final Level INFO是報告消息的消息級別。通常, INFO消息被寫入到控制臺或與之相當的地方。因此, INFO 級別應該只用于相當重要的, 對于最終用戶和系統管理員有意義的消息。此級別初始化為800。
1.8. public static final Level CONFIG是用于靜態配置消息的消息級別。CONFIG消息提供各種靜態配置信息, 并協助調試那些與特定配置有關的問題。例如, CONFIG消息可能包括CPU類型、圖形色深、GUI外觀等等。此級別初始化為700。
1.9. public static final Level FINE是提供跟蹤信息的消息級別。FINE、FINER和FINEST都適合用于相對詳細的跟蹤。三個級別的準確意義在不同子系統間有所不同, 但是通常來說, FINEST 應該用于最為詳細的輸出, FINER 用于不太詳細的輸出, FINE用于極少量(且非常重要)的消息。通常, FINE級別應該用于開發人員比較感興趣的信息, 而這些開發人員對特定子系統則沒有特別的興趣。
FINE消息可能包括諸如次要的(可恢復的)失敗之類的信息。指示潛在性能問題的信息也可以作為FINE記錄到日志。此級別初始化為500。
1.10. public static final Level FINER指示一條相當詳細的跟蹤消息。在默認情況下, 對于輸入、返回或拋出異常的日志記錄調用在此級別進行跟蹤。此級別初始化為400。
1.11. public static final Level FINEST指示一條最詳細的跟蹤消息。此級別初始化為300。
1.12. public static final Level ALL指示應該記錄所有消息。此級別初始化為Integer.MAX_VALUE。
2. Logger對象
2.1. Logger對象用來記錄特定系統或應用程序組件的日志消息。一般使用圓點分隔的層次名稱空間來命名Logger。如java.net或javax.swing。
2.2. public static Logger getLogger(String name)方法, 為指定子系統查找或創建一個logger。如果已經創建了具有給定名稱的logger, 則返回該logger。否則創建一個新的logger。
Logger logger1 = Logger.getLogger(MyLogger.class.getName()); // 第一次是創建 Logger logger2 = Logger.getLogger(MyLogger.class.getName()); // 第二次是查找 System.out.println(logger1 == logger2); // 輸入true2.3. public void setLevel(Level newLevel) throws SecurityException方法, 設置日志級別, 指定此logger記錄的消息級別。將級別低于此值的消息丟棄??梢允褂眉墑e值Level.OFF來關閉日志記錄。如果將Logger的級別設置為null, 那么它的有效級別繼承自父Logger, 這可以通過其父Logger一直沿樹向上遞歸得到。
2.4. 日志消息被轉發到已注冊的Handler對象, 該對象可以將消息轉發到各種目的地, 包括控制臺、文件、OS日志等等。
2.5. public void severe(String msg)記錄一條SEVERE消息。如果當前對于SEVERE消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.6. public void warning(String msg)記錄一條WARNING消息。如果當前對于WARNING消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.7. public void info(String msg)記錄一條INFO消息。如果當前對于INFO消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.8. public void config(String msg)記錄一條CONFIG消息。如果當前對于CONFIG消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.9. public void fine(String msg)記錄一條FINE消息。如果當前對于FINE消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.10. public void finer(String msg)記錄一條FINER消息。如果當前對于FINER消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
2.11. public void finest(String msg)記錄一條FINEST消息。如果當前對于FINEST消息級別而言logger是啟用的, 那么將給定的消息轉發到所有已注冊的輸出Handler對象。
3. 簡單例子
3.1. 代碼
package com.rjbd.loggerjvm;import java.util.logging.Level; import java.util.logging.Logger;public class MyLogger {public static void main(String[] args) {Logger logger1 = Logger.getLogger(MyLogger.class.getName());Logger logger2 = Logger.getLogger(MyLogger.class.getName());System.out.println(logger1 == logger2); // 輸入truelogger1.setLevel(Level.ALL);logger1.severe("severe level in java util logging Logger");logger1.warning("warning level in java util logging Logger");logger1.info("info level in java util logging Logger");logger1.config("config level in java util logging Logger");logger1.fine("fine level in java util logging Logger");logger1.finer("finer level in java util logging Logger");logger1.finest("finest level in java util logging Logger");} }3.2. 運行結果
4. Handler對象
4.1. Handler繼承結構, 常用的ConsoleHandler和FileHandler
4.2. 在我們的MyLogger例子中, 我們并沒有為logger1對象設置Handler對象, 然而控制臺卻打印了日志, 這是因為默認的創建了一個最頂層的日志RootLogger, 而且RootLogger的日志級別是INFO, 同時RootLogger的處理器是ConsoleHandler, 這就是為什么控制臺打印出了info及其更高級別的日志。
4.3. 創建Logger對象的時候設置了它的parent為RootLogger對象
4.4. RootLogger的ConsoleHandler創建過程
4.5. 讀取配置文件
5. FileHandler例子
5.1. 代碼
package com.rjbd.loggerjvm;import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.Logger;public class MyHandler {public static void main(String[] args) {Logger logger = Logger.getLogger(MyHandler.class.getName());logger.setLevel(Level.ALL);logger.getParent().getHandlers()[0].setLevel(Level.ALL);try {FileHandler fileHandler = new FileHandler("MyLogger.log");logger.addHandler(fileHandler);} catch (SecurityException | IOException e) {e.printStackTrace();}logger.severe("severe level in java util logging Logger");logger.warning("warning level in java util logging Logger");logger.info("info level in java util logging Logger");logger.config("config level in java util logging Logger");logger.fine("fine level in java util logging Logger");logger.finer("finer level in java util logging Logger");logger.finest("finest level in java util logging Logger");} }5.2. 運行結果
5.3. 生成MyLogger.log文件
6. Formatter對象
6.1. Formatter為格式化LogRecords提供支持。
6.2. Formatter繼承結構, 自帶了XMLFormatter和SimpleFormatter
6.3. 一般來說, 每個日志記錄Handler都有關聯的Formatter。Formatter接受LogRecord, 并將它轉換為一個字符串。FileHandler默認使用XMLFormatter, ConsoleHandler默認使用SimpleFormatter。我們也可以自定義Formatter。
7. 自定義Formatter例子
7.1. 代碼
package com.rjbd.loggerjvm;import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EnumSet; import java.util.Iterator; import java.util.logging.FileHandler; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger;public class MyFormatter {public static void main(String[] args) {Logger logger = Logger.getLogger(MyFormatter.class.getName());logger.setLevel(Level.ALL);try {FileHandler fh = new FileHandler("MyFormatterLogger.log");logger.addHandler(fh);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");String lineSperator = System.getProperty("line.separator");fh.setFormatter(new Formatter() {@Overridepublic String format(LogRecord record) {String time = "[" + sdf.format(new Date(record.getMillis())) + "]";String qualifiedMethod = "[" + record.getLoggerName() + ":" + record.getSourceMethodName() + "]";String levelNameMsg = "[" + LevelToLocalName.get(record.getLevel().intValue()) + ": " + record.getMessage() + "]";return "[" + time + " " + qualifiedMethod + " " + levelNameMsg + "]" + lineSperator;}});} catch (SecurityException | IOException e) {e.printStackTrace();}logger.severe("severe level in java util logging Logger");logger.warning("warning level in java util logging Logger");logger.info("info level in java util logging Logger");logger.config("config level in java util logging Logger");logger.fine("fine level in java util logging Logger");logger.finer("finer level in java util logging Logger");logger.finest("finest level in java util logging Logger");} }enum LevelToLocalName {SEVERE(Level.SEVERE.intValue(), "嚴重"),WARNING(Level.WARNING.intValue(), "警告"),INFO(Level.INFO.intValue(), "信息"),CONFIG(Level.CONFIG.intValue(), "配置"),FINE(Level.FINE.intValue(), "詳細"),FINER(Level.FINER.intValue(), "較詳細"),FINEST(Level.FINEST.intValue(), "非常詳細");private int level;private String name;LevelToLocalName(int level, String name) {this.level = level;this.name = name;}public int getLevel() {return level;}public String getName() {return name;}public static String get(int level) {EnumSet<LevelToLocalName> es = EnumSet.allOf(LevelToLocalName.class);Iterator<LevelToLocalName> it = es.iterator();while (it.hasNext()) {LevelToLocalName type = it.next();if (level == type.getLevel()) {return type.getName();}}return "";}}7.2. 運行結果
總結
以上是生活随笔為你收集整理的002_Java日志的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 001_日志系统的架构模型
- 下一篇: 004-SLF4J的简单使用