log4j.properties全配置
###############################log4j.properties###############################
##### Global Log Level(OFF,FATAL,ERROR,WARN,INFO,DEBUG,ALL) #############
log4j.rootLogger=DEBUG,STDOUT,DB
###### STDOUT Logger ###############
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
#輸出目的Appender的日志級(jí)別,Appender的級(jí)別設(shè)置要優(yōu)先于logger的
#級(jí)別設(shè)置,即先使用Appender的,而不管logger的日志級(jí)別是怎樣設(shè)置的
log4j.appender.STDOUT.Threshold=DEBUG
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=[%p] [%l] %10.10c - %m%n
###### File Logger ###############
#開(kāi)發(fā)時(shí),使用DEBUG,發(fā)布時(shí)最好修改成INFO,如果未設(shè)置級(jí)別,則使用
#父日志記錄器的,設(shè)置了就使用logger的,不管父日志怎樣設(shè)置
log4j.logger.com.mypakge=DEBUG,FILELOGER
#開(kāi)發(fā)時(shí)設(shè)為true,表示需要屏幕輸出,發(fā)布時(shí)這里最好設(shè)置為false,表示不繼承父日志記錄器的Appender
log4j.additivity.com.mypakge=true
log4j.appender.FILELOGER=org.apache.log4j.RollingFileAppender
#設(shè)置日志輸出編碼方式為UTF-8,如果不指定,會(huì)以當(dāng)前運(yùn)行操作系統(tǒng)的編碼方式記錄,這樣在有的Linux上會(huì)出面亂碼
log4j.appender.FILELOGER.encoding=UTF-8
#${LOGS_PATH}為JVM環(huán)境變量,我們可以在運(yùn)行里給JVM加上該參數(shù) -DLOGS_PATH=e:/tmp/log
log4j.appender.FILELOGER.File=${LOGS_PATH}/system.log
log4j.appender.FILELOGER.MaxFileSize=1024KB
log4j.appender.FILELOGER.MaxBackupIndex=10
#文件采用追加方式
log4j.appender.FILELOGER.Append=true
log4j.appender.FILELOGER.layout=org.apache.log4j.PatternLayout
log4j.appender.FILELOGER.layout.ConversionPattern=[%d{yyy-MM-dd HH:mm:ss.SSS}] [%p] [%t] [%c] [%l] - [%m]%n
###### THREAD Logger ###############
#線程日志一般記入到另一個(gè)文件,線程日志與主線程日志基本上沒(méi)有什么邏輯關(guān)系
log4j.logger.threadlogger=DEBUG,THREADLOGER
log4j.additivity.threadlogger=true
log4j.appender.THREADLOGER=org.apache.log4j.RollingFileAppender
log4j.appender.THREADLOGER.encoding=UTF-8
log4j.appender.THREADLOGER.File=${LOGS_PATH}/threadLog.log
log4j.appender.THREADLOGER.MaxFileSize=2000KB
log4j.appender.THREADLOGER.MaxBackupIndex=10
log4j.appender.THREADLOGER.layout=org.apache.log4j.PatternLayout
log4j.appender.THREADLOGER.layout.ConversionPattern=[%d{yyy-MM-dd HH:mm:ss.SSS}] [%p] [%t] [%c] [%l] - [%m]%n
###### SOCKET Logger ###############
log4j.addivity.org.apache=true
log4j.appender.SOCKET=org.apache.log4j.net.SocketAppender
#注,SocketAppender沒(méi)有encoding屬性,而接收日志的服務(wù)器端類org.apache.log4j.net.Socke
#tServer也不能設(shè)置編碼方式,這里在考慮他們?cè)谕ㄐ艜r(shí)是不是傳遞的對(duì)象,而不是傳遞的字符串呢?
#log4j.appender.SOCKET.encoding=UTF-8
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=8089
log4j.appender.SOCKET.LocationInfo=true
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
#這里的格式配置不是很中要,好像不是要所這里的格式要輸出那些消息,這里還是這個(gè)疑問(wèn)就是在通信時(shí)是否是
#傳遞的是序列化后的對(duì)象?因?yàn)榉?wù)器接收到消息后能以任何格式輸出,可見(jiàn)傳遞的信息是完整的。~@!@#!哈
#剛跟了一下org.apache.log4j.net.SocketAppender源碼,在獲取輸出流的時(shí)候使用的是對(duì)象流,如下:
#oos = new ObjectOutputStream(socket.getOutputStream());,這樣就進(jìn)一步證了我的想法,在
#通信時(shí)時(shí)傳遞的是對(duì)象,所以就不存在字符編碼的問(wèn)題與客戶端日志格式輸出問(wèn)題。
log4j.appender.SOCKET.layout.ConversionPattern=%m
###### MAIL Logger ###############
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=ERROR
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=junJZ_2008@126.com
log4j.appender.MAIL.SMTPHost=smtp.126.com
#如果含有中文,則需使用native2asii log4j.properties log4jxx.properties 進(jìn)行轉(zhuǎn)換,否則亂碼
log4j.appender.MAIL.Subject=Log4J\u63D0\u9192\u60A8\uFF1A\u7CFB\u7EDF\u53D1\u751F\u4E86\u4E25\u91CD\u9519\u8BEF
log4j.appender.MAIL.To=junJZ_2008@163.com
log4j.appender.MAIL.SMTPUsername=junJZ_2008@126.com
log4j.appender.MAIL.SMTPPassword=XXX
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
###### DB Logger ###############
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB.URL=jdbc:mysql://127.0.0.1/test
log4j.appender.DB.bufferSize=1
log4j.appender.DB.user=root
log4j.appender.DB.password=111111
log4j.appender.DB.sql=insert into oplog (UserName,opttype,createTime,LogLevel,methodinfo,MSG) values ('%X{UserName}','%X{opttype}','%d{yyyy-MM-dd HH:mm:ss.SSS}','%p','%l','%m')
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
配置日志服務(wù)器
日志服務(wù)器的服務(wù)器端由以下類啟動(dòng):
log4j jar包中的org.apache.log4j.net.SocketServer
三個(gè)參數(shù) 【監(jiān)聽(tīng)端口】【日志服務(wù)器配置文件】【客戶端配置文件目錄】
第三個(gè)參數(shù)【配置文件目錄】其實(shí)指的是針對(duì)每個(gè)客戶端的配置文件,名命規(guī)則為 "客戶端IP.lcf"
基本原理
當(dāng)日志保存請(qǐng)求發(fā)過(guò)來(lái)時(shí),服務(wù)器會(huì)根據(jù)客戶端的IP去在指定的目錄(上面第三個(gè)參數(shù))下搜索各自的配置文件,如果沒(méi)有找到的話,再找是否配置了公用的客戶端日志配置文件 generic.lcf,如果也沒(méi)有配置的話,它將日志與服務(wù)器運(yùn)行日志記錄在同一文件中(這里為server.log),如果找到了,會(huì)把收到的日志按照配置文件要求記錄,我在這 里使用的客戶端配置文件與log4j.properties是一樣的,所以這里會(huì)產(chǎn)生與客戶機(jī)保存的日志是一樣的。
在運(yùn)行前還得要修改一下org.apache.log4j.net.SocketServer 這個(gè)類,這個(gè)類在取客戶端時(shí)有問(wèn)題,網(wǎng)上其他人也這么認(rèn)為(我使用的是1.215版本),找到 String key = s.substring(0, i); 這一行,修改成 String key = s.substring(i + 1); 即可,然后把修改好的class放入log4j-1.2.15.jar包中(后面附上修改好的包)。
socketserver.properties
#文件名socketserver.properties
#如果需要顯示日志界面,可以將本行啟用
log4j.rootCategory=, A1
log4j.rootLogger=DEBUG,A3,STDOUT
log4j.category.org.apache.log4j.net=INFO
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=[%p] [%l] %10.10c - %m%n
log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
log4j.appender.A1.MaxNumberOfRecords=700
log4j.appender.A3=org.apache.log4j.RollingFileAppender
log4j.appender.A3.file=${LOGS_PATH}/server.log
log4j.appender.A3.MaxFileSize=1024KB
log4j.appender.A3.MaxBackupIndex=10
log4j.appender.A3.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.layout.ConversionPattern=\n\n[%-5p] %d{yyyy-MM-dd HH\:mm\:ss,SSS} method\:%l%n%m%n
客戶端配置文件 127.0.0.1.lcf
###############################log4j.properties###############################
##### Global Log Level(OFF,FATAL,ERROR,WARN,INFO,DEBUG,ALL) #############
log4j.rootLogger=DEBUG,FILELOGER
###### File Logger ###############
#開(kāi)發(fā)時(shí),使用DEBUG,發(fā)布時(shí)最好修改成INFO,如果未設(shè)置級(jí)別,則使用
#父日志記錄器的,設(shè)置了就使用logger的,不管父日志怎樣設(shè)置
log4j.logger.com.mypakge=DEBUG,FILELOGER
#開(kāi)發(fā)時(shí)設(shè)為true,表示需要屏幕輸出,發(fā)布時(shí)這里最好設(shè)置為false,表示不繼承父日志記錄器的Appender
log4j.additivity.com.mypakge=true
log4j.appender.FILELOGER=org.apache.log4j.RollingFileAppender
#設(shè)置日志輸出編碼方式為UTF-8,如果不指定,會(huì)以當(dāng)前運(yùn)行操作系統(tǒng)的編碼方式記錄,這樣在有的Linux上會(huì)出面亂碼
log4j.appender.FILELOGER.encoding=UTF-8
#${LOGS_PATH}為JVM環(huán)境變量,我們可以在運(yùn)行里給JVM加上該參數(shù) -DLOGS_PATH=e:/tmp/log
log4j.appender.FILELOGER.File=${LOGS_PATH}/client.log
log4j.appender.FILELOGER.MaxFileSize=1024KB
log4j.appender.FILELOGER.MaxBackupIndex=10
#文件采用追加方式
log4j.appender.FILELOGER.Append=true
log4j.appender.FILELOGER.layout=org.apache.log4j.PatternLayout
log4j.appender.FILELOGER.layout.ConversionPattern=[%d{yyy-MM-dd HH:mm:ss.SSS}] [%p] [%t] [%c] [%l] - [%m]%n
啟動(dòng):
java -classpath log4j-1.2.15.jar -DLOGS_PATH=e:/tmp/sverlog o
rg.apache.log4j.net.SocketServer 8089 socketserver.properties .
現(xiàn)在使用一個(gè)測(cè)試類記錄日志時(shí),它會(huì)往日志服務(wù)器發(fā)送日志事件,服務(wù)器會(huì)根據(jù)服務(wù)器端配置的客戶端配置文件記錄日志。
配置郵件日志
由于剛開(kāi)始使用1.2.9版本的包時(shí) org.apache.log4j.net.SMTPAppender 發(fā)送郵件時(shí)不支持用戶鑒權(quán)操作,而有的郵件服務(wù)器在發(fā)送時(shí)需要先登錄后再發(fā)送,所以換用了1.2.15的包,SMTPAppender類支持SMTPUsername與SMTPPassword兩個(gè)鑒權(quán)參數(shù),這樣就可以發(fā)送日志郵件了,具體配置參見(jiàn)文章開(kāi)頭。
配置數(shù)據(jù)庫(kù)日志
創(chuàng)建表:
create table oplog(
UserName varchar(20),
opttype varchar(20),
createTime varchar(30),
LogLevel varchar(20),
methodinfo varchar(100),
MSG varchar(1024),
primary key (createTime)
)
表中的 UserName 與 opttype 表示用戶名與操作類型,插入數(shù)據(jù)時(shí)使用 MDC 類進(jìn)行預(yù)先設(shè)置,且配置文件中使用 %x{XXX} 來(lái)引用, MDC其實(shí)就是Java里的ThreadLocal類的派生類。
測(cè)試代碼:
Java代碼
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.MDC;
public class TestLog {
private static Log log = LogFactory.getLog(TestLog.class);
public void log() {
log.debug("Debug info.");
log.info("Info info");
log.warn("Warn info");
log.error("Error info");
log.fatal("Fatal info");
}
public static void main(String[] args) {
MDC.put("UserName", "jzj");
MDC.put("opttype", "delete");
TestLog test = new TestLog();
test.log();
}
}