log4j配置詳解

polalisi發表於2007-08-31

一:配置
A:)
Web Application 中使用log4j
Step 1:
配置log4j配置檔案

=========================
# Set root logger level to DEBUG and its only appender to A1
#log4j
中有五級logger
#FATAL0
#ERROR3
#WARN4
#INFO6
#DEBUG7
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
#log4j
Appender有幾層

#ConsoleAppender
輸出到控制檯
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#
輸出格式 具體檢視log4j javadoc org.apache.log4j.PatternLayout
#d
時間
....
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

================================另外一種配置
log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
#R
輸出到檔案

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

Step 2:寫啟動的Servlet

public class InitServlet extends HttpServlet {

public void init() {
ServletContext sct = getServletContext();
String prefix = sct.getRealPath("/");
//log4j
配置檔案存放目錄

System.out.println("[....Log4j]: The Root Path: " + prefix);
System.out.println("[....Log4j]: InitServlet init start...");
String file = getInitParameter("log4j");
//log4j
配置檔案
if (file != null) {
PropertyConfigurator.configure(prefix + file);
//
根據配置初始化log4j
}

System.out.println("[....Log4j]: InitServlet Init Sucess...");

}

public void doGet(HttpServletRequest req, HttpServletResponse res) {

}

public void doPost(HttpServletRequest req, HttpServletResponse res) {

}
}

B:在一般的IDE中使用log4j,因為使用log4j需要做一些初始化,在Web Application中這一部分初始化是有AppServer 啟動是載入的。在IDE中,則我們在使用log4j之前需要自己配置一下。如下檔案:
public final class Lo4jTest {
private static String CLASS_NAME = "com.bingo.test.Lo4jTest";
private static Logger log = Logger.getLogger(CLASS_NAME);
//
Web Application 中下面的pattern是在log4j的配置檔案中配置的。
//
現在我們手動配置
private static String pattern="%-4r [%-t] [%p] [%c] [%x] - [%m]%n";
private static String pattern2="%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n";
//
設定輸出層
//
private static ConsoleAppender consAppender =
new ConsoleAppender(
new PatternLayout(pattern2));
public static void main(String[] args) {
//
配置log4j
BasicConfigurator.configure(consAppender);
// void configure(Appender appender);
// void configure();
//
配置時log4j提供了兩種方式

//
後一種比較簡單,輸出的資訊不夠詳細
//
我們可以使用前一種輸出我們希望的格式
log.debug("Log4j Debug.");
log.error("Log4j Error.");
log.info("Log4j Info.");
log.fatal("Log4j Fatal.");
}
}
//
使用pattern2上面的輸出結果如下
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[DEBUG] Log4j Debug.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[ERROR] Log4j Error.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[INFO] Log4j Info.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[FATAL] Log4j Fatal.
//
假如我們使用pattern輸出如下:
0 [main] [DEBUG] [com.bingo.test.Lo4jTest] [] - [Log4j Debug.]
0 [main] [ERROR] [com.bingo.test.Lo4jTest] [] - [Log4j Error.]
0 [main] [INFO] [com.bingo.test.Lo4jTest] [] - [Log4j Info.]
0 [main] [FATAL] [com.bingo.test.Lo4jTest] [] - [Log4j Fatal.]

二:使用log4j在實際使用過程中其實非常簡單

1:)如下定義log,log4j1.2以前使用Category,log4j1.2以後使用Logger代替
private static String CLASS_NAME = "com.bingo.test.Lo4jTest";
//log4j1.2
private static Logger log = Logger.getLogger(CLASS_NAME);
//lo4j1.2
以前
private static Category log =Category.getInstance(CLASS_NAME);
//
取得一個Category or Logger有幾種方式,根據自己需要使用

2:)寫日誌
log.debug("Log4j Debug.");
log.error("Log4j Error.");
log.info("Log4j Info.");
log.fatal("Log4j Fatal.");
//void debug(Object message)
//Log a message object with the DEBUG level.
//void debug(Object message, Throwable t)
//Log a message object with the DEBUG level including the
//stack trace of the Throwable t passed as parameter.

三:注意事項
1:
在具體使用中注意不同的資訊使用不同的log方式,選擇debug,error,
info,fatal
中的一種,以後可以根據需要遮蔽部分輸出

2:
開發過程中儘量輸出到控制檯,執行過程中則修改配置使其輸出到檔案.
3:
定義log儘量使用檔名作為引數,這樣容易查詢錯誤.

出處:


==============================================================
以下是與Tomcat互動的:
log4j
的介紹(一)——log4jtomcat結合的簡單配置

log4japacheibm聯合弄得一個應用系統日誌管理工具,利用它的api可以方便的管理和操縱日誌。在除錯程式的時候,是一個非常不錯的除錯幫手。有關log4j的一些介紹,大家可以參考apache的網站(

下面在開始介紹以前,首先推薦一點資料,大家看看,有助於瞭解。
(1)
Log4j delivers control over logging
http://www-106.ibm.com/developerworks/java/library/jw-log4j/
(2)
這裡面介紹了有關layout.ConversionPattern中的轉意字元的含義。

(一)與tomcat結合的簡單配置
首先到 下載一
log4j,目前版本是1.2.5。下載的檔案中有詳細的介紹和例項、apidoc,可以參考一下。
log4j-1.2.5.jar的放到系統classpath中。最好在%tomca_home%/lib/也方一份更好哦。(在此注意一個問題,據說log4j-1.2.5.jar這個檔案的檔名,weblogic6.1不能識別,需要改一個名字)

1.1描寫properties檔案。
這個描述檔案一般放在可以放在兩個地方:(1WEB-INF/classes目錄下,或者放在在/project_root/,也就是你的web_app的根目錄下。利用這個控制日誌紀錄的配置,當然也可以透過xml檔案配置,這裡我們暫且說說properties的配置。

建立檔名log4j.properties檔案。放在%tomca_home%/web_app/fcxtest/目錄下。
檔案內容如下:(fcxtest為自己建立的web app目錄)

#--------------------------------
#
設定loggerroot levelDEBUG,指定的輸出目的地(appender)為
A1
log4j.rootLogger=DEBUG, A1

# 設定除錯資訊的輸出位置,此處設定輸出為控制檯
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# 設定除錯資訊的輸出位置,此處設定輸出為fcxtest.log檔案
# log4j.appender.A1=org.apache.log4j.RollingFileAppender
# log4j.appender.A1.File=fcxtest.log
# log4j.appender.A1.MaxFileSize=1000KB

# 設定製定的A1使用的PatternLayout.
#
有關ConversionPattern中的轉意字元的含義參考說明

log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
#--------------------------------


1.2
建立測試用的Servlet
這個測試的com.fcxlog.LogShow類主要是顯示如何使用log4j

package com.fcxlog;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

public class LogShow extends javax.servlet.http.HttpServlet{

protected String configfile = "log4j.properties";

public void init() throws ServletException{
ServletContext sct = getServletContext();
System.out.println("[Log4j]: The Root Path: " + sct.getRealPath("/"));
//
指定自己的properties檔案

//
以前使用的是BasicConfigurator.configure(),現在使用PropertyConfigurator替代

org.apache.log4j.PropertyConfigurator.configure(sct.getRealPath("/") + configfile);
}

public void service(javax.servlet.http.HttpServletRequest req,javax.servlet.http.HttpServletResponse res){

//
初始化Logger,以前使用Category,現在改用Logger替代

//org.apache.log4j.Category log = org.apache.log4j.Category.getInstance(LogShow.class);
org.apache.log4j.Logger log = ora.apache.log4j.Logger.getLogger(LogShow.class);
log.info("
除錯資訊
");

}
}


1.3
測試了
至於如何測試,釋出,就不說了。

在此說明: 1)本篇可能錯誤不少,一方面是參考《Short introduction to log4j》著翻譯了一點,有諸多言辭不妥之處,還望指正。一方面,憑藉自己的理解,所以難免有不全的地方,還望各位補充。 2)因為時間有限,每天只能寫一點,本文主要是介紹有關LoggerLogger level相關概念的 3)有關Log4j介紹(一),請參閱:

概述:
本文主要是簡要的介紹了Log4japi,以及其一些特徵和設計原理。它本身是一個開源的軟體,允許開發者任意的操縱應用系統日誌資訊。Log4j的使用透過外部配置檔案進行配置。

任何大型應用系統都有其自己的系統日誌管理或跟蹤的API,所以在1996年的時候,E.U. SEMPER專案組()也開發其自己的日誌管理API,後來經過無數次的修改和補充,發展成了現在的log4j,一個給予java的日誌管理工具包。有關最新的版本資訊和原始碼,請訪問 把紀錄語句放在程式碼之中,是一種低端的除錯方法,不過有時卻不得不說是很有效,也是必需的。畢竟很多時候,偵錯程式並不見得很適用。特別是在多執行緒應用程式(multithread application)或分散式應用程式(distributed application

經驗告訴我們,在軟體開發生命週期中,日誌系統是一個非常重要的元件。當然,日誌系統也有其自身的問題,過多的日誌紀錄會降低系統執行的速度。

(一)Log4j的三個重要元件—— Loggers, Appenders, Layouts

這三個元件協同的工作,使得開發者能夠依據資訊類別和級別去紀錄資訊,並能夠執行期間,控制資訊記錄的方式已經日誌存放地點。

(二)記錄器層次(Logger hierarchy

幾乎任何紀錄日誌的API得功能都超越了簡單的System.out.print語句。允許有選擇控制的輸出日誌資訊,也就是說,某的時候,一些日誌資訊允許輸出,而另一些則不允許輸出。這就假設日誌紀錄資訊之間是有分別的,根據開發者自己定義的選擇標準,可以對日誌資訊加以分類。


紀錄器的命名是依據實體的。下面有一段有點繞口的解釋,我就直抄了,各位可以看看:(Name Hierarchy
A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.
(形象的解釋,比如存在記錄器 a.b.c,記錄器a.b,記錄器a。那麼a就是a.bancestor,而a.b就是a.b.cparent,而a.b.c就是a.bchild


根紀錄器(root logger)是記錄器層次的頂端。它有兩個獨特點:(1)總是存在的(2)能夠被重新找回。可以透過訪問類的靜態方法 Logger.getRootLogger 重新得到。其他的紀錄器透過訪問靜態方法 Logger.getLogger 被例項話或被得到,這個方法將希望獲得的記錄器的名稱作為引數。一些Logger類的方法描述如下:

public class Logger {
// Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name);
// printing methods:
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);

// generic printing method:
public void log(Level l, Object message);
}

記錄器被賦予級別,這裡有一套預定的級別標準:DEBUG, INFO, WARN, ERROR and FATAL ,這些是在 org.apache.log4j.Level 定義的。你可以透過繼承Level類定義自己的級別標準,雖然並不鼓勵這麼做。
如果給定的記錄器沒有被賦予級別,則其會從離其最近的擁有級別的ancestor處繼承得到。如果ancestor也沒有被賦予級別,那麼就從根記錄器繼承。所以通常情況下,為了讓所有的記錄器最終都能夠被賦予級別,跟記錄器都會被預先設定級別的。比如我們在操作properties檔案中,會寫這麼一句:log4j.rootLogger=DEBUG, A1 。實際上就這就指定了root Loggerroot Logger level

Appenders
Log4j
允許記錄資訊被列印到多個輸出目的地,一個輸出目的地叫做Appender。目前的Log4j存在的輸出目的地包括:控制檯(Console,檔案(File),GUI ComponenntRemote Socket ServerJMSNT Event Loggerand Remote Unix Syslog daemons

多個Appender可以繫結到一個記錄器上(Logger)。

透過方法 addAppenderLogger.addAppender)可以將一個Appender附加到一個記錄器上。每一個有效的傳送到特定的記錄器的記錄請求都被轉送到那個與當前記錄器所繫結的Appender上。(Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy),換句話說,Appender的繼承層次是附加在記錄器繼承層次上的。舉個例子:如果一個Console Appender被繫結到根記錄器(root Logger),那麼所有的記錄請求都可以至少被列印到Console。另外,把一個file Appender繫結到記錄器C,那麼針對記錄器C(或C的子孫)的記錄請求都可以至少傳送到Console Appenderfile Appender。當然這種預設的行為方式可以跟改,透過設定記錄器的additivity flagLogger.setAdditivity)為false,從而可以使得Appender的不再具有可加性(Additivity)。

下面簡要介紹一下Appender Additivity

Appender Additivity
:記錄器C所記錄的日誌資訊將被髮送到與記錄器C以及其祖先(ancestor)所繫結的所有Appender

但是,如果記錄器C的祖先,叫做P,它的additivity flag被設定為false。那麼,記錄資訊仍然被髮送到與記錄器C及其祖先,但只到達P這一層次,包括P在內的記錄器的所有Appender。但不包括P祖先的。

通常,記錄器的additivity flag的被設定為true


Layouts
這一塊主要是介紹輸出格式的。PatternLayoutLog4j標準的分配器,可以讓開發者依照conversion patterns去定義輸出格式。Conversion patterns有點像c語言的列印函式。
參看配置檔案的java properties,如下面的兩行:

log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
第一行就指定了分配器,第二行則指定了輸出的格式。

有關輸出格式的定義可以參考/org/apache/log4j/PatternLayout.html

============================================================

再貼一篇例項:使用Log4j進行日誌操作

1. 概述

1.1. 背景

在應用程式中新增日誌記錄總的來說基於三個目的:監視程式碼中變數的變化情況,週期性的記錄到檔案中供其他應用進行統計分析工作;跟蹤程式碼執行時軌跡,作為日後審計的依據;擔當整合開發環境中的偵錯程式的作用,向檔案或控制檯列印程式碼的除錯資訊。

最普通的做法就是在程式碼中嵌入許多的列印語句,這些列印語句可以輸出到控制檯或檔案中,比較好的做法就是構造一個日誌操作類來封裝此類操作,而不是讓一系列的列印語句充斥了程式碼的主體。

1.2. Log4j簡介

在強調可重用元件開發的今天,除了自己從頭到尾開發一個可重用的日誌操作類外,Apache為我們提供了一個強有力的日誌操作包-Log4j

Log4jApache的一個開放原始碼專案,透過使用Log4j,我們可以控制日誌資訊輸送的目的地是控制檯、檔案、GUI元件、甚至是套介面伺服器、NT的事件記錄器、UNIX Syslog守護程式等;我們也可以控制每一條日誌的輸出格式;透過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程。最令人感興趣的就是,這些可以透過一個配置檔案來靈活地進行配置,而不需要修改應用的程式碼。

此外,透過Log4j其他語言介面,您可以在CC++.NetPL/SQL程式中使用Log4j,其語法和用法與在Java程式中一樣,使得多語言分散式系統得到一個統一一致的日誌元件模組。而且,透過使用各種第三方擴充套件,您可以很方便地將Log4j整合到J2EEJINI甚至是SNMP應用中。

本文介紹的Log4j版本是1.2.3。作者試圖透過一個簡單的客戶/伺服器Java程式例子對比使用與不使用Log4j 1.2.3的差別,並詳細講解了在實踐中最常使用Log4j的方法和步驟。在強調可重用元件開發的今天,相信Log4j將會給廣大的設計開發人員帶來方便。加入到Log4j的隊伍來吧!

2. 一個簡單的例子

我們先來看一個簡單的例子,它是一個用Java實現的客戶/伺服器網路程式。剛開始我們不使用Log4j,而是使用了一系列的列印語句,然後我們將使用Log4j來實現它的日誌功能。這樣,大家就可以清楚地比較出前後兩個程式碼的差別。

2.1. 不使用Log4j

2.1.1. 客戶程式

package log4j ;

import java.io.* ;
import java.net.* ;

/**
*
*

Client Without Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ClientWithoutLog4j {

/**
*
* @param args
*/
public static void main ( String args [] ) {

String welcome = null;
String response = null;
BufferedReader reader = null;
PrintWriter writer = null;
InputStream in = null;
OutputStream out = null;
Socket client = null;

try {
client = new Socket ( "localhost", 8001 ) ;
System.out.println ( "info: Client socket: " + client ) ;
in = client.getInputStream () ;
out = client.getOutputStream () ;
} catch ( IOException e ) {
System.out.println ( "error: IOException : " + e ) ;
System.exit ( 0 ) ;
}

try{
reader = new BufferedReader( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

welcome = reader.readLine () ;
System.out.println ( "debug: Server says: '" + welcome + "'" ) ;

System.out.println ( "debug: HELLO" ) ;
writer.println ( "HELLO" ) ;
response = reader.readLine () ;
System.out.println ( "debug: Server responds: '" + response + "'") ;

System.out.println ( "debug: HELP" ) ;
writer.println ( "HELP" ) ;
response = reader.readLine () ;
System.out.println ( "debug: Server responds: '" + response + "'" ) ;

System.out.println ( "debug: QUIT" ) ;
writer.println ( "QUIT" ) ;
} catch ( IOException e ) {
System.out.println ( "warn: IOException in client.in.readln()" ) ;
System.out.println ( e ) ;
}
try{
Thread.sleep ( 2000 ) ;
} catch ( Exception ignored ) {}
}
}

2.1.2. 伺服器程式

package log4j ;

import java.util.* ;
import java.io.* ;
import java.net.* ;

/**
*
*

Server Without Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ServerWithoutLog4j {

final static int SERVER_PORT = 8001 ; // this server's port

/**
*
* @param args
*/
public static void main ( String args [] ) {
String clientRequest = null;
BufferedReader reader = null;
PrintWriter writer = null;
ServerSocket server = null;
Socket socket = null;
InputStream in = null;
OutputStream out = null;

try {
server = new ServerSocket ( SERVER_PORT ) ;
System.out.println ( "info: ServerSocket before accept: " + server ) ;
System.out.println ( "info: Java server without log4j, on-line!" ) ;

// wait for client's connection
socket = server.accept () ;
System.out.println ( "info: ServerSocket after accept: " + server ) ;

in = socket.getInputStream () ;
out = socket.getOutputStream () ;

} catch ( IOException e ) {
System.out.println( "error: Server constructor IOException: " + e ) ;
System.exit ( 0 ) ;
}
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ) , true ) ;

// send welcome string to client
writer.println ( "Java server without log4j, " + new Date () ) ;

while ( true ) {
try {
// read from client
clientRequest = reader.readLine () ;
System.out.println ( "debug: Client says: " + clientRequest ) ;
if ( clientRequest.startsWith ( "HELP" ) ) {
System.out.println ( "debug: OK!" ) ;
writer.println ( "Vocabulary: HELP QUIT" ) ;
}
else {
if ( clientRequest.startsWith ( "QUIT" ) ) {
System.out.println ( "debug: OK!" ) ;
System.exit ( 0 ) ;
}
else{
System.out.println ( "warn: Command '" +
clientRequest + "' not understood." ) ;
writer.println ( "Command '" + clientRequest
+ "' not understood." ) ;
}
}
} catch ( IOException e ) {
System.out.println ( "error: IOException in Server " + e ) ;
System.exit ( 0 ) ;
}
}
}
}

2.2. 遷移到Log4j

2.2.1. 客戶程式

package log4j ;

import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
*
*

Client With Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ClientWithLog4j {

/*
add for log4j: class Logger is the central class in the log4j package.
we can do most logging operations by Logger except configuration.
getLogger(...): retrieve a logger by name, if not then create for it.
*/
static Logger logger = Logger.getLogger
( ClientWithLog4j.class.getName () ) ;

/**
*
* @param args : configuration file name
*/
public static void main ( String args [] ) {

String welcome = null ;
String response = null ;
BufferedReader reader = null ;
PrintWriter writer = null ;
InputStream in = null ;
OutputStream out = null ;
Socket client = null ;

/*
add for log4j: class BasicConfigurator can quickly configure the package.
print the information to console.
*/
PropertyConfigurator.configure ( "ClientWithLog4j.properties" ) ;

// add for log4j: set the level
// logger.setLevel ( ( Level ) Level.DEBUG ) ;

try{
client = new Socket( "localhost" , 8001 ) ;

// add for log4j: log a message with the info level
logger.info ( "Client socket: " + client ) ;

in = client.getInputStream () ;
out = client.getOutputStream () ;
} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error ( "IOException : " + e ) ;

System.exit ( 0 ) ;
}

try{
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

welcome = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server says: '" + welcome + "'" ) ;

// add for log4j: log a message with the debug level
logger.debug ( "HELLO" ) ;

writer.println ( "HELLO" ) ;
response = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server responds: '" + response + "'" ) ;

// add for log4j: log a message with the debug level
logger.debug ( "HELP" ) ;

writer.println ( "HELP" ) ;
response = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server responds: '" + response + "'") ;

// add for log4j: log a message with the debug level
logger.debug ( "QUIT" ) ;

writer.println ( "QUIT" ) ;
} catch ( IOException e ) {

// add for log4j: log a message with the warn level
logger.warn ( "IOException in client.in.readln()" ) ;

System.out.println ( e ) ;
}
try {
Thread.sleep ( 2000 ) ;
} catch ( Exception ignored ) {}
}
}

2.2.2. 伺服器程式

package log4j;

import java.util.* ;
import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
*
*

Server With Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ServerWithLog4j {

final static int SERVER_PORT = 8001 ; // this server's port

/*
add for log4j: class Logger is the central class in the log4j package.
we can do most logging operations by Logger except configuration.
getLogger(...): retrieve a logger by name, if not then create for it.
*/
static Logger logger = Logger.getLogger
( ServerWithLog4j.class.getName () ) ;

/**
*
* @param args
*/
public static void main ( String args[]) {
String clientRequest = null ;
BufferedReader reader = null ;
PrintWriter writer = null ;
ServerSocket server = null ;
Socket socket = null ;

InputStream in = null ;
OutputStream out = null ;

/*
add for log4j: class BasicConfigurator can quickly configure the package.
print the information to console.
*/
PropertyConfigurator.configure ( "ServerWithLog4j.properties" ) ;

// add for log4j: set the level
// logger.setLevel ( ( Level ) Level.DEBUG ) ;

try{
server = new ServerSocket ( SERVER_PORT ) ;

// add for log4j: log a message with the info level
logger.info ( "ServerSocket before accept: " + server ) ;

// add for log4j: log a message with the info level
logger.info ( "Java server with log4j, on-line!" ) ;

// wait for client's connection
socket = server.accept() ;

// add for log4j: log a message with the info level
logger.info ( "ServerSocket after accept: " + server ) ;

in = socket.getInputStream() ;
out = socket.getOutputStream() ;

} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error ( "Server constructor IOException: " + e ) ;
System.exit ( 0 ) ;
}
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

// send welcome string to client
writer.println ( "Java server with log4j, " + new Date () ) ;

while ( true ) {
try {
// read from client
clientRequest = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Client says: " + clientRequest ) ;

if ( clientRequest.startsWith ( "HELP" ) ) {

// add for log4j: log a message with the debug level
logger.debug ( "OK!" ) ;

writer.println ( "Vocabulary: HELP QUIT" ) ;
}
else {
if ( clientRequest.startsWith ( "QUIT" ) ) {

// add for log4j: log a message with the debug level
logger.debug ( "OK!" ) ;

System.exit ( 0 ) ;
}
else {

// add for log4j: log a message with the warn level
logger.warn ( "Command '"
+ clientRequest + "' not understood." ) ;

writer.println ( "Command '"
+ clientRequest + "' not understood." ) ;
}
}
} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error( "IOException in Server " + e ) ;

System.exit ( 0 ) ;
}
}
}
}

2.2.3. 配置檔案

2.2.3.1. 客戶程式配置檔案

log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

2.2.3.2. 伺服器程式配置檔案

log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

2.3. 比較

比較這兩個應用可以看出,採用Log4j進行日誌操作的整個過程相當簡單明瞭,與直接使用System.out.println語句進行日誌資訊輸出的方式相比,基本上沒有增加程式碼量,同時能夠清楚地理解每一條日誌資訊的重要程度。透過控制配置檔案,我們還可以靈活地修改日誌資訊的格式,輸出目的地等等方面,而單純依靠System.out.println語句,顯然需要做更多的工作。

下面我們將以前面使用Log4j的應用作為例子,詳細講解使用Log4j的主要步驟。

3. Log4j基本使用方法

Log4j由三個重要的元件構成:日誌資訊的優先順序,日誌資訊的輸出目的地,日誌資訊的輸出格式。日誌資訊的優先順序從高到低有ERRORWARNINFODEBUG,分別用來指定這條日誌資訊的重要程度;日誌資訊的輸出目的地指定了日誌將列印到控制檯還是檔案中;而輸出格式則控制了日誌資訊的顯示內容。

3.1.定義配置檔案

其實您也可以完全不使用配置檔案,而是在程式碼中配置Log4j環境。但是,使用配置檔案將使您的應用程式更加靈活。

Log4j支援兩種配置檔案格式,一種是XML格式的檔案,一種是Java特性檔案(鍵=值)。下面我們介紹使用Java特性檔案做為配置檔案的方法:

配置根Logger,其語法為:

log4j.rootLogger = [ level ] , appenderName, appenderName, …其中,level 是日誌記錄的優先順序,分為OFFFATALERRORWARNINFODEBUGALL或者您定義的級別。Log4j建議只使用四個級別,優先順序從高到低分別是ERRORWARNINFODEBUG。透過在這裡定義的級別,您可以控制到應用程式中相應級別的日誌資訊的開關。比如在這裡定義了INFO級別,則應用程式中所有DEBUG級別的日誌資訊將不被列印出來。
appenderName
就是指定日誌資訊輸出到哪個地方。您可以同時指定多個輸出目的地。

配置日誌資訊輸出目的地Appender,其語法為

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1

log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下幾種:

org.apache.log4j.ConsoleAppender
(控制檯),
org.apache.log4j.FileAppender
(檔案),
org.apache.log4j.DailyRollingFileAppender
(每天產生一個日誌檔案),org.apache.log4j.RollingFileAppender(檔案大小到達指定尺寸的時候產生一個新的檔案),
org.apache.log4j.WriterAppender
(將日誌資訊以流格式傳送到任意指定的地方)

配置日誌資訊的格式(佈局),其語法為:

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1

log4j.appender.appenderName.layout.option = valueN
其中,Log4j提供的layout有以下幾種:

org.apache.log4j.HTMLLayout
(以HTML表格形式佈局),
org.apache.log4j.PatternLayout
(可以靈活地指定佈局模式),
org.apache.log4j.SimpleLayout
(包含日誌資訊的級別和資訊字串),
org.apache.log4j.TTCCLayout
(包含日誌產生的時間、執行緒、類別等等資訊)

3.2.在程式碼中使用Log4j

下面將講述在程式程式碼中怎樣使用Log4j

3.2.1.得到記錄器

使用Log4j,第一步就是獲取日誌記錄器,這個記錄器將負責控制日誌資訊。其語法為:


public static Logger getLogger( String name)
透過指定的名字獲得記錄器,如果必要的話,則為這個名字建立一個新的記錄器。Name一般取本類的名字,比如:

static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
3.2.2.
讀取配置檔案

當獲得了日誌記錄器之後,第二步將配置Log4j環境,其語法為:
BasicConfigurator.configure ()
: 自動快速地使用預設Log4j環境。
PropertyConfigurator.configure ( String configFilename)
:讀取使用Java的特性檔案編寫的配置檔案。
DOMConfigurator.configure ( String filename )
:讀取XML形式的配置檔案。

3.2.3.插入記錄資訊(格式化日誌資訊)

當上兩個必要步驟執行完畢,您就可以輕鬆地使用不同優先順序別的日誌記錄語句插入到您想記錄日誌的任何地方,其語法如下:

Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;

4. 參考資料

如果您想更深入地瞭解Log4j,請經常訪問下面提及的相關連結。
Log4j
專案主頁------------------------------------------------------
Log4j FAQ -------------------------------------------------------/log4j/faq.html

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10455649/viewspace-967240/,如需轉載,請註明出處,否則將追究法律責任。