log4j配置詳解(非常詳細轉載)
Log4J的配置檔案(Configuration File)就是用來設定記錄器的級別、存放器和佈局的,它可接key=value格式的設定或xml格式的設定資訊。通過配置,可以創建出Log4J的執行環境。
- 配置檔案
Log4J配置檔案的基本格式如下:
#配置根Logger
log4j.rootLogger = [ level ] , appenderName1 , appenderName2 , …
#配置日誌資訊輸出目的地Appender
log4j.appender.appenderName = fully.qualified.name.of.appender .class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.optionN = valueN
#配置日誌資訊的格式(佈局)
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout .optionN = valueN
其中 [level] 是日誌輸出級別,共有5級:
FATAL 0
ERROR 3
WARN 4
INFO 6
DEBUG 7
Appender 為日誌輸出目的地,Log4j提供的appender有以下幾種:
org.apache.log4j.ConsoleAppender(控制檯),
org.apache.log4j.FileAppender(檔案),
org.apache.log4j.DailyRollingFileAppender(每天產生一個日誌檔案),
org.apache .log4j.RollingFileAppender(檔案大小到達指定尺寸的時候產生一個新的檔案),
org.apache.log4j.WriterAppender(將日誌資訊以流格式傳送到任意指定的地方)
Layout:日誌輸出格式,Log4j提供的layout有以下幾種:
org.apache.log4j.HTMLLayout(以HTML表格形式佈局),
org.apache.log4j.PatternLayout(可以靈活地指定佈局模式),
org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串),
org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等等資訊)
列印引數: Log4J採用類似C語言中的printf函式的列印格式格式化日誌資訊,如下:
%m 輸出程式碼中指定的訊息
%p 輸出優先順序,即DEBUG,INFO,WARN,ERROR,FATAL
%r 輸出自應用啟動到輸出該log資訊耗費的毫秒數
%c 輸出所屬的類目,通常就是所在類的全名
%t 輸出產生該日誌事件的執行緒名
%n 輸出一個回車換行符,Windows平臺為“\r\n”,Unix平臺為“\n”
%d 輸出日誌時間點的日期或時間,預設格式為ISO8601,也可以在其後指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},輸出類似:2002年10月18日 22 : 10 : 28 , 921
%l 輸出日誌事件的發生位置,包括類目名、發生的執行緒,以及在程式碼中的行數。舉例:Testlog4.main(TestLog4.java: 10 )
2.在程式碼中初始化Logger:
1)在程式中呼叫BasicConfigurator.configure()方法:給根記錄器增加一個ConsoleAppender,輸出格式通過PatternLayout設為”%-4r [%t] %-5p %c %x - %m%n”,還有根記錄器的預設級別是Level.DEBUG.
2)配置放在檔案裡,通過命令列引數傳遞檔名字,通過PropertyConfigurator.configure(args[x])解析並配置;
3)配置放在檔案裡,通過環境變數傳遞檔名等資訊,利用log4j預設的初始化過程解析並配置;
4)配置放在檔案裡,通過應用伺服器配置傳遞檔名等資訊,利用一個特殊的servlet來完成配置。
3.為不同的 Appender 設定日誌輸出級別:
當除錯系統時,我們往往注意的只是異常級別的日誌輸出,但是通常所有級別的輸出都是放在一個檔案裡的,如果日誌輸出的級別是BUG!?那就慢慢去找吧。
這時我們也許會想要是能把異常資訊單獨輸出到一個檔案裡該多好啊。當然可以,Log4j已經提供了這樣的功能,我們只需要在配置中修改Appender的Threshold 就能實現,比如下面的例子:
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 輸出到控制檯 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
### 輸出到日誌檔案 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG ## 輸出DEBUG級別以上的日誌
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 儲存異常資訊到單獨檔案 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/error.log ## 異常日誌檔名
log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR ## 只輸出ERROR級別以上的日誌!!!
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
public class TestLog4j {
public static void main(String[] args) {
PropertyConfigurator.configure( " D:/Code/conf/log4j.properties " );
Logger logger = Logger.getLogger(TestLog4j. class );
logger.debug( " debug " );
logger.error( " error " );
}
執行一下,看看異常資訊是不是儲存在了一個單獨的檔案error.log中。
=====================================================================
資料:
- log4j.properties檔案例子,這個檔案就是本文的重點,也就是log4j的配置檔案:
# Set root logger level to DEBUG and its only appender to A1
#log4j中有五級logger
#FATAL 0
#ERROR 3
#WARN 4
#INFO 6
#DEBUG 7
#配置根Logger,其語法為:
#log4j.rootLogger = [ level ] , appenderName, appenderName, …
log4j.rootLogger=INFO, A1 ,R
#這一句設定以為著所有的log都輸出
#如果為log4j.rootLogger=WARN, 則意味著只有WARN,ERROR,FATAL
#被輸出,DEBUG,INFO將被遮蔽掉.
# A1 is set to be a ConsoleAppender.
#log4j中Appender有幾層如控制檯、檔案、GUI元件、甚至是套介面伺服器、NT的事件記錄器、UNIX Syslog守護程序等
#ConsoleAppender輸出到控制檯
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 使用的輸出佈局,其中log4j提供4種佈局. org.apache.log4j.HTMLLayout(以HTML表格形式佈局)
#org.apache.log4j.PatternLayout(可以靈活地指定佈局模式),
#org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串),
#org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等等資訊)
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#靈活定義輸出格式 具體檢視log4j javadoc org.apache.log4j.PatternLayout
#d 時間 ....
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
#R 輸出到檔案 RollingFileAppender的擴充套件,可以提供一種日誌的備份功能。
log4j.appender.R=org.apache.log4j.RollingFileAppender
#日誌檔案的名稱
log4j.appender.R.File=log4j.log
#日誌檔案的大小
log4j.appender.R.MaxFileSize=100KB
# 儲存一個備份檔案
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.TTCCLayout
#log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
2.下面我給出一個在weblogic下使用log4j的配置過程,首先給出這個配置檔案的完整資訊。
#log4j.rootLogger=INFO,A1,R //這一句指定了日誌輸出的級別為info,A1和R分別代表日誌輸出到什麼地方。
log4j.category.hybl_wshabcm=debug,A1,R //這一句指定了日誌具體輸出哪個包的資訊,以及輸出位置
log4j.appender.A1=org.apache.log4j.ConsoleAppender //這裡指定了日誌輸出的第一個位置A1是控制檯ConsoleAppender
/*
*其中,Log4j提供的appender有以下幾種:
*org.apache.log4j.ConsoleAppender(控制檯),
*org.apache.log4j.FileAppender(檔案),
*org.apache.log4j.DailyRollingFileAppender(每天產生一個日誌檔案),
*org.apache.log4j.RollingFileAppender(檔案大小到達指定尺寸的時候產生一個新的檔案),
*org.apache.log4j.WriterAppender(將日誌資訊以流格式傳送到任意指定的地方)
*
*/
log4j.appender.A1.layout=org.apache.log4j.PatternLayout //指定A1的佈局模式
/*
*其中,Log4j提供的layout有以下幾種:
×org.apache.log4j.HTMLLayout(以HTML表格形式佈局),
*org.apache.log4j.PatternLayout(可以靈活地指定佈局模式),
*org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串),
*org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等等資訊)
*/
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n //指定日誌的輸出格式
log4j.appender.R=org.apache.log4j.RollingFileAppender //指定以檔案的方式輸出日誌
log4j.appender.R.File=c:/sys.html //檔案位置
log4j.appender.R.MaxFileSize=500KB //檔案最大尺寸
log4j.appender.R.MaxBackupIndex=1 //備份數
log4j.appender.R.layout=org.apache.log4j.HTMLLayout //檔案的格式為Html格式
#log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n
============================================================
錯誤日誌傳送email
- 開啟log4j.properties檔案
- rootLogger加上一個Appender, 即MAIL, 如log4j.rootLogger=ERROR,A1,MAIL
- 配置Appender資訊,在檔案的末尾加上以下部分
# Configuration for receiving e-mails when ERROR messages occur.
#自定義的Appender
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
#日誌的錯誤級別
log4j.appender.MAIL.Threshold=ERROR
#快取檔案大小,日誌達到512K時傳送Email
log4j.appender.MAIL.BufferSize=512
#發件人
log4j.appender.MAIL.From=test@163.com
#傳送郵件的伺服器
log4j.appender.MAIL.SMTPHost=smtp.163.com
#郵件的標題
log4j.appender.MAIL.Subject=Log4J Message
#日誌郵件的接收者
log4j.appender.MAIL.To=test@163.com
#日誌PatternLayout
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
#日誌的格式
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
以上檔案皆測試通過,如不通過請檢視自己的email傳送環境.
==============================================================================================
查看了SMTPAppender.java的原始碼,才發現Log4J預設提供的SMTPAppender並不支援SMTP的認證功能。難道現在匿名的SMTP郵件伺服器很多嗎?我手頭的是Log4J的 1.2.8版本,去logging.apache.org看,發現已經有新的版本了: 1.2.11,呵呵,竊喜。這樣的簡單、基本的需求Log4J開發組應該已經新增上了吧。
下載、檢視,再次失望之極!
看來只有自己動手添加了。本來應該重新定義一個名字,算做一個自定義Appender吧,但為了使我很多應用中的log4j.properties不用修改過多,就直接在原來的SMTPAppender.java上做了修改。另外一個更重要的原因是:
我認為:這是一個基本的、必須的SMTPAppender應該具有的功能。
主要在SMTPAppender.java中添加了如下程式碼:
a. 新增例項變數
private String smtpUsername;
private String smtpPassword;
b. 將 activateOptions() 方法中的
Session session = Session.getInstance(props, null);
修改為:
if(smtpPassword != null && smtpUsername != null) {
// Setup mail server authentication
props.put("mail.smtp.auth", "true");
// props.put("mail.transport.protocol", "smtp");
authenticator = new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(smtpUsername, smtpPassword);
}
};
}
// Get session
Session session = Session.getDefaultInstance(props,authenticator);
c. 新增Set方法
public void setSMTPPassword(String smtpPassword) {
this.smtpPassword = smtpPassword;
}
public void setSMTPUsername(String smtpUsername) {
this.smtpUsername = smtpUsername;
}
編譯,並重新打包log4j-1.2.8.jar。在應用中替換原log4j-1.2.8.jar包,並修改log4j.properties檔案,在SMTPAppender的配置中新增如下兩行:
log4j.appender.MAIL.SMTPUsername=
log4j.appender.MAIL.SMTPPassword=
OK,現在這個SMTPAppender就可以使用需要使用者名稱、密碼驗證的SMTP伺服器(現在絕大多數SMTP伺服器)進行Email報警傳送了。
log4j詳解
根據網路資料整理
- 概述<<<<
1.1. 背景
在應用程式中新增日誌記錄總的來說基於三個目的:監視程式碼中變數的變化情況,週期性的記錄到檔案中供其他應用進行統計分析工作;跟蹤程式碼執行時軌跡,作為日後審計的依據;擔當整合開發環境中的偵錯程式的作用,向檔案或控制檯列印程式碼的除錯資訊。
最普通的做法就是在程式碼中嵌入許多的列印語句,這些列印語句可以輸出到控制檯或檔案中,比較好的做法就是構造一個日誌操作類來封裝此類操作,而不是讓一系列的列印語句充斥了程式碼的主體。
1.2. Log4j簡介
在強調可重用元件開發的今天,除了自己從頭到尾開發一個可重用的日誌操作類外,Apache為我們提供了一個強有力的日誌操作包-Log4j。
Log4j是Apache的一個開放原始碼專案,通過使用Log4j,我們可以控制日誌資訊輸送的目的地是控制檯、檔案、GUI元件、甚至是套介面服務 器、NT的事件記錄器、UNIX Syslog守護程序等;我們也可以控制每一條日誌的輸出格式;通過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程。最令人感興趣的就 是,這些可以通過一個配置檔案來靈活地進行配置,而不需要修改應用的程式碼。
此外,通過Log4j其他語言介面,您可以在C、C+ +、.Net、PL/SQL程式中使用Log4j,其語法和用法與在Java程式中一樣,使得多語言分散式系統得到一個統一一致的日誌元件模組。而且,通 過使用各種第三方擴充套件,您可以很方便地將Log4j整合到J2EE、JINI甚至是SNMP應用中。
本文介紹的Log4j版本是 1.2.3。作者試圖通過一個簡單的客戶/伺服器Java程式例子對比使用與不使用Log4j 1.2.3的差別,並詳細講解了在實踐中最常使用Log4j的方法和步驟。在強調可重用元件開發的今天,相信Log4j將會給廣大的設計開發人員帶來方 便。加入到Log4j的隊伍來吧!
- 一個簡單的例子 <<<<
我們先來看一個簡單的例子,它是一個用Java實現的客戶/伺服器網路程式。剛開始我們不使用Log4j,而是使用了一系列的列印語句,然後我們將使用Log4j來實現它的日誌功能。這樣,大家就可以清楚地比較出前後兩個程式碼的差別。
2.1. 不使用Log4j
2.1.1. 客戶程式
package log4j ;
import java.io.* ;
import java.net.* ;
/**
*
* <p> Client Without Log4j </p>
* <p> Description: a sample with log4j</p>
* @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.* ;
/**
*
* <p> Server Without Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ;
/**
*
* <p> Client With Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ;
/**
*
* <p> Server With Log4j </p>
* <p> Description: a sample with log4j</p>
* @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語句,顯然需要做更多的工作。
3 . Log4j日誌管理系統簡單使用說明 <<<<
通常,我們都提供一個名為 log4j.properties的檔案,在第一次呼叫到Log4J時,Log4J會在類路徑(../web-inf/class/當然也可以放到其它任何目錄,只要該目錄被包含到類路徑中即可)中定位這個檔案,並讀入這個檔案完成的配置。這個配置檔案告 訴Log4J以什麼樣的格式、把什麼樣的資訊、輸出到什麼地方。
Log4j有三個主要的元件:Loggers(記錄器),Appenders(輸出源)和Layouts(佈局),這裡可簡單理解為日誌類別,日誌要輸出的地方和日誌以何種形式輸出。綜合使用這三個元件可以輕鬆的記錄資訊的型別和級別,並可以在執行時控制日誌輸出的樣式和位置。下面對三個元件分別進行說明:
1、 Loggers
Loggers元件在此係統中被分為五個級別:DEBUG、INFO、WARN、ERROR和FATAL。這五個級別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,分別用來指定這條日誌資訊的重要程度,明白這一點很重要,這裡Log4j有一個規則:假設Loggers級別為P,如果在Loggers中發生了一個級別Q比P高,則可以啟動,否則遮蔽掉。
假設你定義的級別是info,那麼error和warn的日誌可以顯示而比他低的debug資訊就不顯示了。
Java程式舉例來說:
//建立Logger的一個例項,命名為“com.foo”
Logger logger = Logger.getLogger(“com.foo”); //”com.foo”是例項進行命名,也可以任意
//設定logger的級別。通常不在程式中設定logger的級別。一般在配置檔案中設定。
logger.setLevel(Level.INFO);
Logger barlogger = Logger.getLogger("com.foo.Bar");
//下面這個請求可用,因為WARN >= INFO
logger.warn("Low fuel level.");
//下面這個請求不可用,因為DEBUG < INFO
logger.debug("Starting search for nearest gas station.");
//命名為“com.foo.bar”的例項barlogger會繼承例項“com.foo”的級別。因此,下面這個請求可用,因為INFO >= INFO
barlogger.info("Located nearest gas station.");
//下面這個請求不可用,因為DEBUG < INFO
barlogger.debug("Exiting gas station search");
這裡“是否可用”的意思是能否輸出Logger資訊。
在對Logger例項進行命名時,沒有限制,可以取任意自己感興趣的名字。一般情況下建議以類的所在位置來命名Logger例項,這是目前來講比較有效的Logger命名方式。這樣可以使得每個類建立自己的日誌資訊,便於管理。比如:
static Logger logger = Logger.getLogger(ClientWithLog4j.class.getName());
2、Appenders
禁用與使用日誌請求只是Log4j其中的一個小小的地方,Log4j日誌系統允許把日誌輸出到不同的地方,如控制檯(Console)、檔案(Files)、根據天數或者檔案大小產生新的檔案、以流的形式傳送到其它地方等等。
其語法表示為:
org.apache.log4j.ConsoleAppender(控制檯)
org.apache.log4j.FileAppender(檔案)
org.apache.log4j.DailyRollingFileAppender(每天產生一個日誌檔案)
org.apache.log4j.RollingFileAppender(檔案大小到達指定尺寸的時候產生一個新的檔案)
org.apache.log4j.WriterAppender(將日誌資訊以流格式傳送到任意指定的地方)
配置時使用方式為:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueN
這樣就為日誌的輸出提供了相當大的便利。
3、Layouts
有時使用者希望根據自己的喜好格式化自己的日誌輸出。Log4j可以在Appenders的後面附加Layouts來完成這個功能。Layouts提供了 四種日誌輸出樣式,如根據HTML樣式、自由指定樣式、包含日誌級別與資訊的樣式和包含日誌時間、執行緒、類別等資訊的樣式等等。
其語法表示為:
org.apache.log4j.HTMLLayout(以HTML表格形式佈局),
org.apache.log4j.PatternLayout(可以靈活地指定佈局模式),
org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串),
org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等等資訊)
配置時使用方式為:
log4j.appender.appenderName.layout =fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.option = valueN
4 . Log4j