From: Polin Wei
簡介 Introduction Log4j 是一套開放源碼的工具,方便編程人員在程式中加入 log 機制,並輸出到各種目標上。Log4j 能夠透過外部的設定檔(properites 或 XML)進行設定。Log4j 能夠將 log message 寫到 console, 檔案,串流,TCP 協定的伺服器, Unix Syslog daemon 等。詳細的說明可以參考官方網
log4j組成 Log4j 的三大元件(Loggers, Appenders and Layouts) :- Logger - 由編程人員在程式中使用,進行 logging 的元件
- Appender - 負責將 log message 輸出到各種裝置上
- Layout - 決定 log message 的格式
Loggers: Logger 可以被指派等級。能夠指派給 Logger 的等級有 : DEBUG, INFO, WARN, ERROR, FATAL 5 種,定義在 org.apache.log4j.Level 類別中。這 5 種等級的高低順序為 FATAL > ERROR > WARN > DEBUG > INFO 。
Logger 的等級決定它產生 log message 的數量 : Logger 只寫"出高於或等於本身等級"的 log message。例如某個 Logger 的等級被設定為 WARN,那麼它只會寫出等級為 WARN, ERROR, FATAL 的 log message,對於 DEBUG, INFO 的 log message 則不予理會。
若是 Logger 的等級未被設定,則會自動使用 parent(上一層) 的等級。如果程式中所有的 Logger 都未設定等級,則由 root logger 決定。
Logger 之間以名稱區分,所以在程式中任何地方,呼叫 Logger.getLogger(),並傳入同一個 Logger 名稱,則會得到同一個 Logger 的 reference。
Logger 之間以名稱區分出階層。即使父階層在程式中出現的時機比子階層晚,例如 "com.foo" logger 比 "com.foo.bar" 被取得的時間來得晚,"com.foo" 仍然是 "com.foo.bar" 的父階層(會影響到子階層 logger 未被定義的屬性, log 等級, appender, layout )。
Appenders: 透過 Appender, Logger 能夠將 log message 輸出到指定的裝置上。一個 Logger 能夠擁有多個 Appender,所以 Logger 能夠同時將 log message 輸出到多個個裝置上。
Appender 的設定亦會反映在 Logger 的階層中。當 Logger 輸出一筆 log message 時,父階層的 Appender 和自己的 Appender(如果有的話)都會記錄到這筆 log message;
例如 "com.foo" Logger 有一個 Appender 將 log message 輸出到 console,而 "com.foo.bar" 有一個 Appender 將 log message 輸出到檔案;當 "com.foo.bar" Logger 輸出一筆 log message 時, console 和檔案都會出現這筆 log message。
而最簡單的例子,就是當 root logger 擁有一個輸出到 console 的 Appender 時,則程式中所有的 logger 所產生的 log message 都會輸出到 console。唯一個例外的情況,就是當某個 logger 將自己的 additivity 屬性設為 false(Logger.setAdditivity(false)),則此 logger 與隸屬於它的子 logger 都不會將 log message 寫到 console。
Layouts: 可以透過 Layout 的配置,自由改變 Logger 寫出 log message 的格式。例如,為 Logger 加入一個 conversion pattern 為 "%r [%t] %-5p %c - %m%n" 的 PatternLayout,則輸出的 log message 就可能會像下列這樣:
176 [main] INFO org.foo.Bar - Located nearest gas station.PatternLayout 的 格式字元列表如下:
# %c 輸出日誌訊息所屬的類別的全名
# %d 輸出日誌時間點的日期或時間,指定格式的方式:%d{yyy-MM-dd HH:mm:ss }。
# %l 輸出日誌事件的發生位置,即輸出日誌訊息的語句處於它所在的類別的第幾行。
# %m 輸出訊息,如log(message)中的message。
# %n 輸出一個列尾符號。
# %p 輸出優先階層,即DEBUG,INFO,WARN,ERROR,FATAL。如果是調用debug()輸出的,則為DEBUG,依此類推。
# %r 輸出自應用啟動到輸出該日誌訊息所耗費的毫秒數。
# %t 輸出產生該日誌事件的線程名。
# %r 輸出自應用啟動到輸出該日誌訊息所耗費的毫秒數。
# %f 輸出日誌訊息所屬的類別的類別名。
Layout 亦會反映在 Logger 的階層上。
實作:
1. 修改 log4j.xml 檔
在JBOSS(version:4.0.3SP1) 上的 log4j.xml 實作,可以分兩個層次來看:
- 一是修改 Server 端的 log4j.xml ,檔案在:$JBOSS_HOME/server/default/conf/log4j.xml
- 一是修改每個Prjoject中的 $Java Resource/src 程式原始檔目錄下的 log4j.xml
這兩個檔案內容大致相同,差異只在 Project 端的 logger 參數在 Server 端要改成 category
Server 端的 log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!-- ============================================================ -->
<!-- Log4j Configuration -->
<!-- ============================================================ -->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- ======================== -->
<!-- Preserve messages in a local file -->
<!-- ======================== -->
<!-- A time/date based rolling appender 定義 log message 輸出FILE檔案 -->
<appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.home.dir}/log/server.log"/>
<param name="Append" value="false"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<!-- 定義 log message 的格式 -->
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- ===================================================== -->
<!-- Append messages to the console 定義 log message 輸出 Console -->
<!-- ===================================================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<!-- 定義 log message 的格式 -->
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<!-- ========================================= -->
<!-- Limit categories 對 class: com.demos 作偵錯觀察 -->
<!-- ========================================= -->
<category name="com.demos">
<priority value="DEBUG"/>
</category>
<!-- ============================ -->
<!-- Setup the Root category 設定 log 要在那裡產生 -->
<!-- ============================ -->
<root>
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</log4j:configuration>
Project 端的 log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- ===================================================== -->
<!-- Append messages to the console 定義 log message 輸出至 Console 及 log 內容格式 -->
<!-- ===================================================== -->
<appender name="default" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%p] %d{dd MMM hh:mm:ss.SSS aa} %t [%C-%M]%n%m%n%n" />
</layout>
</appender>
<!-- 設定要偵錯的 calss: com.demos 及 log 要輸出到那一個裝置-->
<logger name="com.demos">
<level value="debug" />
<appender-ref ref="default" />
</logger>
</log4j:configuration>
2. 在 java 程式 com.demos.LookupFormF.java 中放入偵錯點
package com.demos;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.log4j.Logger;
public class LookupFormF extends ActionForm{
static Logger loger = Logger.getLogger(LookupFormF.class.getName());
private String symbol = null;
public String getSymbol() {
return (symbol);
}
public void setSymbol(String symbol) {
this.symbol = symbol;
loger.debug(symbol);
}
}
3. 成果如下
16:54:23,733 INFO [STDOUT] [DEBUG] 24 十月 04:54:23.733 下午 http-0.0.0.0-8043-
1 [com.demos.LookupFormF-setSymbol]
polinwei