【前面的話】
學習的進度應該稍微在快一點。
Java日志到了必須學習怎么使用的時候了,因為在項目中要進行使用。基礎性文章,選擇性閱讀。
【結構】
java日志對調試,記錄運行,問題定位都起到了很重要的作用,一般常用的日志框架有:
- sf4j
- commons-logging
- log4j
- JDK自帶logging
- 其他日志框架
【定義】
記錄日志:一般在最開始寫代碼的時候總是會在代碼中加入一些System.out.println方法的語句來觀察代碼運行的情況。這樣需要反復加入和修改,日志API就是為了解決這個問題。
java.util.logging包就是JDK的日志開發包。
Log4j是Apache的一個開放源代碼項目,通過使用Log4j,我們可以控制日志信息輸送的目的地是控制台、文件、GUI組件,甚至是套接口服務器、NT的事件記錄器、UNIX Syslog守護進程等;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級別,我們能夠更加細致地控制日志的生成過程。最令人感興趣的就是,這些可以通過一個配置文件來靈活地進行配置,而不需要修改應用的代碼。
好處
- 可以很容易的取消全部日志記錄,或者僅僅取消某個級別的日志,而且打開和關閉這個操作也很容易。
- 可以很簡單地禁止日志記錄的輸出,因此,將這些日志代碼留在程序中所付出的代價很小。
- 日志記錄可以被定向到不同的處理器,用於在控制台中顯示,用於存儲在文件中。
- 日志記錄器和處理器都可以對記錄進行過濾。過濾器可以根據過濾實現器制定的標准丟棄那些無用的記錄項。
- 日志記錄可以采用不同的方式格式化。如:純文本或者XML。
- 應用程序可以使用多個日志記錄器,他們使用類似包名的這種具有層次結構的名稱,如:com.mycompany.myapp。
- 在默認情況下,日志系統的配置由配置文件控制,如果需要的話,應用程序可以替換這個配置。
【JDK自帶logging】
一、 日志級別
| 級別 |
意義 |
等級 |
| OFF |
這個日志級別比較特殊,用來關閉日志 |
|
| SEVERE |
系統比較嚴重的錯誤級別,一般是無法恢復的bug |
最高 |
| WARNING |
警告提示 |
|
| INFO |
普通信息輸出 |
|
| CONFIG |
靜態配置信息輸出,如cpu,mem |
|
| FINE |
FINE,FINER,FINEST三個日志級別都是用來跟蹤日志信息,輸出信息的詳細程度依次遞增 |
|
| FINER |
|
|
| FINEST |
最低 |
|
| ALL |
所有的日志信息都輸出 |
|
在默認情況下,只記錄前面三個級別。也可以設置級別如下:
1 logger.setLevel(Level.ALL);
二、例子
1. 代碼
1 import java.util.logging.ConsoleHandler; 2 import java.util.logging.Level; 3 import java.util.logging.Logger; 4 5 public class LoggerTest { 6 public static void main(String []args){ 7 Logger logger =Logger.getLogger("cn.cc.ccc"); 8 /* ConsoleHandler handler=new ConsoleHandler(); 9 handler.setLevel(Level.ALL); 10 logger.addHandler(handler);*/ 11 logger.setLevel(Level.ALL); 12 logger.severe("嚴重錯誤"); 13 logger.warning("警告信息"); 14 logger.info("普通輸出"); 15 logger.config("配置信息"); 16 logger.fine("日志信息"); 17 logger.finer("日志信息"); 18 logger.finest("日志信息"); 19 } 20 }
2. 結果:
1 四月 10, 2014 4:48:55 下午 LoggerTest main 2 嚴重: 嚴重錯誤 3 四月 10, 2014 4:48:55 下午 LoggerTest main 4 警告: 警告信息 5 四月 10, 2014 4:48:55 下午 LoggerTest main 6 信息: 普通輸出
3. 問題:
進行了等級設置以后為什么不能輸出下面的幾個級別的信息?也就是為什么沒有輸出:
1 四月 10, 2014 4:44:43 下午 LoggerTest main 2 配置: 配置信息 3 四月 10, 2014 4:44:43 下午 LoggerTest main 4 詳細: 日志信息 5 四月 10, 2014 4:44:43 下午 LoggerTest main 6 較詳細: 日志信息 7 四月 10, 2014 4:44:43 下午 LoggerTest main 8 非常詳細: 日志信息
4. 原因:
默認規定只能輸出到INFO級別,我們沒有修改配置文件,也就是使用了默認的配置。有兩種修改方式,
一種是修改.properties文件(本文沒有實現),默認情況下配置文件存在於:jre/lib/logging.properties
第二種是安裝一個新的ConsoleHandler,如下代碼:
1 import java.util.logging.ConsoleHandler; 2 import java.util.logging.Level; 3 import java.util.logging.Logger; 4 5 public class LoggerTest { 6 public static void main(String []args){ 7 Logger logger =Logger.getLogger("cn.cc.ccc"); 8 ConsoleHandler handler=new ConsoleHandler(); 9 handler.setLevel(Level.ALL); 10 logger.addHandler(handler); 11 logger.setLevel(Level.ALL); 12 logger.severe("嚴重錯誤"); 13 logger.warning("警告信息"); 14 logger.info("普通輸出"); 15 logger.config("配置信息"); 16 logger.fine("日志信息"); 17 logger.finer("日志信息"); 18 logger.finest("日志信息"); 19 } 20 }
結果
1 四月 10, 2014 4:44:43 下午 LoggerTest main 2 嚴重: 嚴重錯誤 3 四月 10, 2014 4:44:43 下午 LoggerTest main 4 嚴重: 嚴重錯誤 5 四月 10, 2014 4:44:43 下午 LoggerTest main 6 警告: 警告信息 7 四月 10, 2014 4:44:43 下午 LoggerTest main 8 警告: 警告信息 9 四月 10, 2014 4:44:43 下午 LoggerTest main 10 信息: 普通輸出 11 四月 10, 2014 4:44:43 下午 LoggerTest main 12 信息: 普通輸出 13 四月 10, 2014 4:44:43 下午 LoggerTest main 14 配置: 配置信息 15 四月 10, 2014 4:44:43 下午 LoggerTest main 16 詳細: 日志信息 17 四月 10, 2014 4:44:43 下午 LoggerTest main 18 較詳細: 日志信息 19 四月 10, 2014 4:44:43 下午 LoggerTest main 20 非常詳細: 日志信息
【log4j】
再學習一個常見的日志框架,log4j。先看個例子。
一、例子
1. LoggerTest.java
1 import java.util.logging.Level; 2 3 import org.apache.log4j.Logger; 4 5 public class LoggerTest { 6 public static void main(String []args){ 7 //獲取Logger實例,參數為本類 8 Logger logger=Logger.getLogger(LoggerTest.class); 9 logger.debug("debuging");//輸出一段DEBUG信息 10 logger.info("info..."); //輸出一段INFO信息 11 logger.error("error..."); //輸出一段ERROR錯誤信息 12 logger.fatal("fatal"); 13 logger.warn("warn"); 14 } 15 }
2. log4j.properties
1 #此屬性指定日志等級等於或低於INFO的日志信息輸出到名為stdout的目的地 2 log4j.rootCategory=INFO, stdout 3 #此屬性執行stdout這個輸出目的地類型為控制台 4 log4j.appender.stdout=org.apache.log4j.ConsoleAppender 5 #此屬性指定輸出日志的布局類,這里采用LOG4J默認的布局類 6 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
3. 結果
1 info... 2 error... 3 fatal 4 warn
4. 注意事項
需要把log4j-1.2.16.jar導入
二、log4j的結構
(一) log4j的構成
- 根目錄(級別和目的地);
- 目的地(控制台、文件等等);
- 輸出樣式。
(二) log4j包含類的意義
- Logger - 日志寫出器,供程序員輸出日志信息
- Appender - 日志目的地,把格式化好的日志信息輸出到指定的地方去
- ConsoleAppender - 目的地為控制台的Appender
- FileAppender - 目的地為文件的Appender
- RollingFileAppender - 目的地為大小受限的文件的Appender
- Layout - 日志格式化器,用來把程序員的logging request格式化成字符串
- PatternLayout - 用指定的pattern格式化logging request的Layout
三、.properties配置信息
Log4j由三個重要的組件構成:日志信息的優先級,日志信息的輸出目的地,日志信息的輸出格式。日志信息的優先級從高到低有ERROR、WARN、 INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制台還是文件中;而輸出格式則控制了日志信息的顯示內容。
在.properties進行配置的時候,也是針對日志信息的優先級,日志信息的輸出目的地,日志信息的輸出格式進行配置。
1. 配置根Logger
例子中,properties文件中的第一句就是配置這個。
1 log4j.rootLogger = level,appenderName1,appenderName2, ···
其中,level 是日志記錄的優先級,分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個級別,優先級從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級別,您可以控制到應用程序中相應級別的日志信息的開關。比如在這里定義了INFO級別,則應用程序中所有DEBUG級別的日志信息將不被打印出來。 appenderName就是指B日志信息輸出到哪個地方。您可以同時指定多個輸出目的地。優先級:ALL < DEBUG < INFO <WARN < ERROR < FATAL < OFF
2. 配置日志信息輸出目的地Appender
1 log4j.appender.appenderName = Log4j提供的appender類 2 log4j.appender.appenderName.屬性名 = 屬性值 3 ··· 4 log4j.appender.appenderName.屬性名 = 屬性值
其中,Log4j提供的appender有以下幾種:
1 org.apache.log4j.ConsoleAppender(控制台), 2 org.apache.log4j.FileAppender(文件), 3 org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件), 4 org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件), 5 org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
1) ConsoleAppender選項
Threshold=WARN:指定日志消息的輸出最低層次。
ImmediateFlush=true:默認值是true,意謂着所有的消息都會被立即輸出。
Target=System.err:默認情況下是:System.out,指定輸出控制台
2) FileAppender 選項
Threshold=WARN:指定日志消息的輸出最低層次。
ImmediateFlush=true:默認值是true,意謂着所有的消息都會被立即輸出。
File=mylog.txt:指定消息輸出到mylog.txt文件。
Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
3) DailyRollingFileAppender 選項
Threshold=WARN:指定日志消息的輸出最低層次。
ImmediateFlush=true:默認值是true,意謂着所有的消息都會被立即輸出。
File=mylog.txt:指定消息輸出到mylog.txt文件。
Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
DatePattern=''.''yyyy-ww:每周滾動一次文件,即每周產生一個新的文件。
當然也可以指定按月、周、天、時和分。即對應的格式如下:
- ''.''yyyy-MM: 每月
- ''.''yyyy-ww: 每周
- ''.''yyyy-MM-dd: 每天
- ''.''yyyy-MM-dd-a: 每天兩次
- ''.''yyyy-MM-dd-HH: 每小時
- ''.''yyyy-MM-dd-HH-mm: 每分鍾
4) RollingFileAppender 選項
Threshold=WARN:指定日志消息的輸出最低層次。
ImmediateFlush=true:默認值是true,意謂着所有的消息都會被立即輸出。
File=mylog.txt:指定消息輸出到mylog.txt文件。
Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
MaxFileSize=100KB: 后綴可以是KB, MB 或者是 GB. 在日志文件到達該大小時,將會自動滾動,即將原來的內容移到mylog.log.1文件。
MaxBackupIndex=2:指定可以產生的滾動文件的最大數。
3. 配置日志信息的格式(布局)
1 log4j.appender.appenderName.layout = Log4j提供的layout類 2 log4j.appender.appenderName.layout.屬性 = 值 3 ••• 4 log4j.appender.appenderName.layout.屬性 = 值 Log4j
其中,Log4j提供的layout有以下幾種:
1 org.apache.log4j.HTMLLayout(以HTML表格形式布局), 2 org.apache.log4j.PatternLayout(可以靈活地指定布局模式), 3 org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串), 4 org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等等信息)
1) HTMLLayout選項
LocationInfo=true:默認值是false,輸出java文件名稱和行號
Title=my app file: 默認值是 Log4J Log Messages.
2) PatternLayout選項
ConversionPattern=%m%n :指定怎樣格式化指定的消息。
3) XMLLayout選項
LocationInfo=true:默認值是false,輸出java文件和行號
Log4J采用類似C語言中的printf函數的打印格式格式化日志信息,打印參數如下:
1 og4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
這里需要說明的就是日志信息格式中幾個符號所代表的含義:
-X號: X信息輸出時左對齊;
%p: 輸出日志信息優先級,即DEBUG,INFO,WARN,ERROR,FATAL,
%d: 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,
比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
%r: 輸出自應用啟動到輸出該log信息耗費的毫秒數
%c: 輸出日志信息所屬的類目,通常就是所在類的全名
%t: 輸出產生該日志事件的線程名
%l: 輸出日志事件的發生位置,相當於%C.%M(%F:%L)的組合,包括類目名、發生的線程,以及行數。
舉例:Testlog4.main(TestLog4.java:10)
%x: 輸出和當前線程相關聯的NDC(嵌套診斷環境),尤其用到像java servlets這樣的多客戶多線程的應用中。
%%: 輸出一個"%"字符
%F: 輸出日志消息產生時所在的文件名稱
%L: 輸出代碼中的行號
%m: 輸出代碼中指定的消息,產生的日志具體信息
%n: 輸出一個回車換行符,Windows平台為"\r\n",Unix平台為"\n"輸出日志信息換行
可以在%與模式字符之間加上修飾符來控制其最小寬度、最大寬度、和文本的對齊方式。如:
- %20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小於20的話,默認的情況下右對齊。
- %-20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小於20的話,"-"號指定左對齊。
- %.30c:指定輸出category的名稱,最大的寬度是30,如果category的名稱大於30的話,就會將左邊多出的字符截掉,但小於30的話也不會有空格。
- %20.30c:如果category的名稱小於20就補空格,並且右對齊,如果其名稱長於30字符,就從左邊交遠銷出的字符截掉
四、xml配置信息
詳細內容見例子:
1. LoggerTest.java
1 import org.apache.log4j.Logger; 2 3 public class LoggerTest { 4 private static final Logger log = Logger.getLogger(LoggerTest.class); 5 public static void main(String[] args) { 6 log.info("Enter the main()...."); 7 log.debug("Enter the main()...."); 8 log.warn("Enter the main()...."); 9 log.info("Enter the main()...."); 10 System.out.println("this is a log4j test."); 11 log.info("log end."); 12 } 13 }
2. log4j.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> 3 <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> 4 5 <!-- ========================== 自定義輸出格式說明================================ --> 6 <!-- %p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL --> 7 <!-- %r 輸出自應用啟動到輸出該log信息耗費的毫秒數 --> 8 <!-- %c 輸出所屬的類目,通常就是所在類的全名 --> 9 <!-- %t 輸出產生該日志事件的線程名 --> 10 <!-- %n 輸出一個回車換行符,Windows平台為“/r/n”,Unix平台為“/n” --> 11 <!-- %d 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921 --> 12 <!-- %l 輸出日志事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main(TestLog4.java:10) --> 13 <!-- ========================================================================== --> 14 15 <!-- ========================== 輸出方式說明================================ --> 16 <!-- Log4j提供的appender有以下幾種: --> 17 <!-- org.apache.log4j.ConsoleAppender(控制台), --> 18 <!-- org.apache.log4j.FileAppender(文件), --> 19 <!-- org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件), --> 20 <!-- org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件), --> 21 <!-- org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方) --> 22 <!-- ========================================================================== --> 23 <!-- 輸出到日志文件 --> 24 <!-- 設置通道file和輸出方式:org.apache.log4j.RollingFileAppender --> 25 <appender name="FILE" class="org.apache.log4j.RollingFileAppender"> 26 <!-- 設置File參數:日志輸出文件名 --> 27 <param name="File" value="D:/logxml/test_log4j_debug.log"/> 28 <!-- 設置是否在重新啟動服務時,在原有日志的基礎添加新日志 --> 29 <param name="Append" value="true"/> 30 <param name="MaxFileSize" value="5KB"/> 31 <param name="MaxBackupIndex" value="2"/> 32 <layout class="org.apache.log4j.PatternLayout"> 33 <!-- 設置輸出文件項目和格式 --> 34 <param name="ConversionPattern" value="%c %d{ISO8601}-- %p -- %m%n"/> 35 </layout> 36 <filter class="org.apache.log4j.varia.LevelRangeFilter"> 37 <param name="LevelMin" value="DEBUG"/> 38 <param name="LevelMax" value="DEBUG"/> 39 </filter> 40 </appender> 41 <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> 42 <layout class="org.apache.log4j.PatternLayout"> 43 <param name="ConversionPattern" value="%c %d{ISO8601}-- %p -- %m%n"/> 44 </layout> 45 <filter class="org.apache.log4j.varia.LevelRangeFilter"> 46 <param name="LevelMin" value="INFO"/> 47 <param name="LevelMax" value="INFO"/> 48 </filter> 49 </appender> 50 <root> 51 <priority value="debug"/> 52 <appender-ref ref="FILE" /><!-- 與前面的通道id相對應 --> 53 <appender-ref ref="STDOUT" /> 54 </root> 55 </log4j:configuration>
3. 運行結果:
在控制台中輸出結果:
1 LoggerTest 2014-04-11 16:20:17,683-- INFO -- Enter the main().... 2 LoggerTest 2014-04-11 16:20:17,684-- INFO -- Enter the main().... 3 this is a log4j test. 4 LoggerTest 2014-04-11 16:20:17,684-- INFO -- log end.
在D:/logxml/test_log4j_debug.log輸出結果:
1 LoggerTest 2014-04-11 16:20:17,684-- DEBUG -- Enter the main()....
【參考資料】
1. java日志詳解
2. JAVA應用開發日志解決方案
3. log4j入門、詳解
【后面的話】
好好學習。
——TT
