利用Log4j將不同Package的日志輸出到不同文件的方法
前言
隨著項(xiàng)目規(guī)模的越來(lái)越大,會(huì)不斷的引入新的模塊,不同的模塊都會(huì)打印自己的日志,最后就造成日志根本沒法查看,比如我自己的項(xiàng)目中,就存在以下這些日志:
- 接收外界消息的日志、對(duì)外發(fā)送消息的日志;
- 后臺(tái)常駐線程的處理日志;
- 外部接口訪問(wèn)的參數(shù)、返回結(jié)果等接口日志;
- Service訪問(wèn)數(shù)據(jù)庫(kù)產(chǎn)生的SQL日志;
這其中,消息日志和后臺(tái)線程的日志數(shù)據(jù)量非常龐大,如果所有日志打印在一個(gè)文件中,使用tail -f log.log文件,會(huì)發(fā)現(xiàn)日志在快速的滾動(dòng),根本無(wú)法查看甚至定位某一個(gè)具體的SQL或者Service訪問(wèn)日志。
解決方法就是可以將不同的日志加以分類輸出,這樣相互的日志不影響,尤其重要的接口訪問(wèn)日志,能夠很方便的定位和排查問(wèn)題。
步驟1:在log4j.properties中配置
先貼一下我自己所有的log4j.properties配置:
log4j.rootLogger=INFO, console, file
log4j.appender.console=net.czt.log.AsyncConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p crazyant-web %-17c{2} (%13F:%L) %X{USER_ID}|%X{USER_IP}|%X{SERVER_ADDRESS}|%X{SERVER_NAME}|%X{REQUEST_URI}|%X{SESSION_ID} - %m%n
log4j.appender.console.bufferSize=10000
log4j.appender.console.encoding=UTF-8
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.file=/home/work/apache-tomcat-6.0.39/logs/crazyant.log
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.MaxFileSize=1GB
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%-5p] crazyant-web %d{yyyy-MM-dd HH:mm:ss,SSS} %X{USER_ID}|%X{USER_IP}|%X{SERVER_ADDRESS}|%X{SERVER_NAME}|%X{REQUEST_URI}|%X{SESSION_ID} method:%l%n%m%n
log4j.appender.file.bufferSize=10000
log4j.appender.file.encoding=UTF-8
log4j.logger.net.czt.crazyant.msg=DEBUG, message
log4j.additivity.net.czt.crazyant.msg=false
log4j.appender.message=org.apache.log4j.RollingFileAppender
log4j.appender.message.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_message.log
log4j.appender.message.Append=true
log4j.appender.message.MaxFileSize=1GB
log4j.appender.message.MaxBackupIndex=5
log4j.appender.message.layout=org.apache.log4j.PatternLayout
log4j.appender.message.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n
log4j.appender.message.encoding=UTF-8
log4j.logger.net.czt.crazyant.async.service=DEBUG, async
log4j.additivity.net.czt.crazyant.async.service=false
log4j.appender.async=org.apache.log4j.RollingFileAppender
log4j.appender.async.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_async.log
log4j.appender.async.Append=true
log4j.appender.async.MaxFileSize=1GB
log4j.appender.async.MaxBackupIndex=5
log4j.appender.async.layout=org.apache.log4j.PatternLayout
log4j.appender.async.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n
log4j.appender.async.encoding=UTF-8
log4j.logger.net.czt.orm.mybatis.SqlMonitorManager=DEBUG, showsql
log4j.additivity.net.czt.orm.mybatis.SqlMonitorManager=false
log4j.logger.net.czt.transaction.interceptor.SmartTransactionInterceptor=DEBUG, showsql
log4j.additivity.net.czt.transaction.interceptor.SmartTransactionInterceptor=false
log4j.appender.showsql=org.apache.log4j.RollingFileAppender
log4j.appender.showsql.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_sql.log
log4j.appender.showsql.Append=true
log4j.appender.showsql.MaxFileSize=1GB
log4j.appender.showsql.MaxBackupIndex=5
log4j.appender.showsql.layout=org.apache.log4j.PatternLayout
log4j.appender.showsql.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n
log4j.appender.showsql.encoding=UTF-8
log4j.logger.net.czt.crazyant.service=DEBUG, service
log4j.additivity.net.czt.crazyant.service=false
log4j.appender.service=org.apache.log4j.RollingFileAppender
log4j.appender.service.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_service.log
log4j.appender.service.Append=true
log4j.appender.service.MaxFileSize=1GB
log4j.appender.service.MaxBackupIndex=5
log4j.appender.service.layout=org.apache.log4j.PatternLayout
log4j.appender.service.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n
log4j.appender.service.encoding=UTF-8
在配置文件的下方,可以方便的看到,我將message(消息)、async(后端線程)、showsql(數(shù)據(jù)庫(kù)日志)、service(接口調(diào)用)分別輸出到了不同的日志文件。
其中的一些解釋:
log4j.rootLogger=INFO, console, file
log4j有一個(gè)rootLogger和普通Logger的概念,默認(rèn)情況下我們只需要一個(gè)rootLogger,就是所有的日志只會(huì)輸出到這一個(gè)日志文件中。
看一下普通Logger的配置(以接口日志service為例):
1、log4j.logger.net.czt.crazyant.service=DEBUG, service
這句中的”net.czt.crazyant.service”,表示該普通logger日志配置生效的package的完全路徑
其中色service,表示該普通logger的名字
2、log4j.additivity.net.czt.crazyant.service=false
其中的”net.czt.crazyant.service”,和上面的相同,表示該配置項(xiàng)針對(duì)的package
該句配置的意思,是不要將該package的日志輸出到rootLogger日志中,只輸出到自己配置的日志就行了;
3、log4j.appender.service=org.apache.log4j.RollingFileAppender,以及該配置段下面的配置項(xiàng)
這里的”service”字符串,和上面的第一個(gè)配置項(xiàng)的”service”相同,表示對(duì)該普通Logger的配置;
下方的配置項(xiàng)和rootLogger相同,表示每天輸出文件、編碼UTF8、分片規(guī)則、每行的輸出模式等等
我自己遇到的問(wèn)題,是上面的log4j.properties配置好以后,發(fā)現(xiàn)各個(gè)日志文件創(chuàng)建了,但是里面都沒有內(nèi)容,這是為啥呢?來(lái)看下面第二個(gè)注意的地方;
步驟2、輸出日志時(shí)需要設(shè)定日志對(duì)象對(duì)應(yīng)的具體Class
什么意思呢?上面的配置項(xiàng)中,有一個(gè)”net.czt.crazyant.service”的package字符串,那么我們自己想一下,log4j是怎樣將不同package中的logger日志輸出到不同文件呢,想一下會(huì)有兩種方法:
1、采用intercepter或者aop的方式,log4j自己檢測(cè)日志輸出,檢測(cè)到日志產(chǎn)生于哪個(gè)package,就將其輸出到對(duì)應(yīng)文件中;
2、由用戶傳一個(gè)Class參數(shù),log4j獲取該Class對(duì)應(yīng)的Package,以此為準(zhǔn),來(lái)定位不同的日志文件;
看一下代碼,顯然log4j用的是后一種簡(jiǎn)單直接的方式:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MyClassImpl implements MyClass {
/**
* loger
*/
private static final Log logger = LogFactory.getLog(MyClassImpl.class);
/**
* my func
*/
public void myfunc() {
logger.info("call method myfunc.");
}
}
在logger = LogFactory.getLog(MyClassImpl.class)中,傳入了使用該logger的Class參數(shù),而該Class被反射取到的package地址,就是log4j用來(lái)輸出日志的package地址。
這種做法也有強(qiáng)大的地方,方便邏輯上的日志歸類,比如很多代碼不屬于一個(gè)package,但是它們邏輯上屬于一起的,舉個(gè)例子,消息的處理不只是接口調(diào)用Service這個(gè)package,可能還會(huì)調(diào)用發(fā)送msg的操作,如果想把msg的package中一些日志也輸出到Service,那么在這個(gè)msg的logger初始化的時(shí)候,傳入一個(gè)Serivice的Class就行了。
或者對(duì)于某一類的所有日志來(lái)說(shuō),它們所有的logger對(duì)象,都來(lái)自封裝好的單個(gè)對(duì)象實(shí)例即可,而這個(gè)單個(gè)對(duì)象實(shí)例傳入的參數(shù)只有一個(gè),用于標(biāo)識(shí)這個(gè)邏輯歸類即可。
總結(jié)
在Log4j.properties中,支持package或者具體class的日志單獨(dú)輸出,但是也需要代碼中l(wèi)ogger初始化的時(shí)候,能和日志配置中的package對(duì)應(yīng)上。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
- java自定義日志輸出文件(log4j日志文件輸出多個(gè)自定義日志文件)
- 可替代log4j日志的c#簡(jiǎn)單日志類隊(duì)列實(shí)現(xiàn)類代碼分享
- Java日志軟件Log4j的基本使用教程
- 使用Log4j為項(xiàng)目配置日志輸出應(yīng)用詳解以及示例演示的實(shí)現(xiàn)分析
- Node.js 日志處理模塊log4js
- Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例
- 在Java下利用log4j記錄日志的方法
- Log4j按級(jí)別輸出日志到不同文件的實(shí)現(xiàn)方法
- 很詳細(xì)的Log4j配置步驟
- log4j使用教程詳解(怎么使用log4j2)
相關(guān)文章
eclipse啟動(dòng)出現(xiàn)“failed to load the jni shared library”問(wèn)題解決
這篇文章主要介紹了eclipse啟動(dòng)出現(xiàn)“failed to load the jni shared library”問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringBoot結(jié)合FreeMarker視圖渲染的實(shí)現(xiàn)
FreeMarker它允許開發(fā)人員使用模板和數(shù)據(jù)來(lái)生成輸出文本,如HTML網(wǎng)頁(yè)、電子郵件、配置文件和源代碼等,本文主要介紹了SpringBoot結(jié)合FreeMarker視圖渲染的實(shí)現(xiàn),感興趣的可以了解一下2024-03-03
mybatis mybatis-plus-generator+clickhouse自動(dòng)生成代碼案例詳解
這篇文章主要介紹了mybatis mybatis-plus-generator+clickhouse自動(dòng)生成代碼案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
淺談Java中Unicode的編碼和實(shí)現(xiàn)
這篇文章向大家介紹了Java編程中Unicode編碼及實(shí)現(xiàn)的相關(guān)內(nèi)容,列舉了幾個(gè)字符不同表達(dá)式的比較,以及Unicode平面映射的知識(shí),具有一點(diǎn)點(diǎn)參考價(jià)值,需要的朋友可以了解下。2017-10-10
IDEA引MAVEN項(xiàng)目jar包依賴導(dǎo)入問(wèn)題解決方法
這篇文章主要介紹了IDEA引MAVEN項(xiàng)目jar包依賴導(dǎo)入問(wèn)題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
Java中ThreadLocal?導(dǎo)致內(nèi)存?OOM?的原因分析
這篇文章主要介紹了Java中ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,文章基于Java的相關(guān)內(nèi)容展開ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,需要的小伙v阿布可以參考一下2022-05-05
使用springboot跳轉(zhuǎn)到指定頁(yè)面和(重定向,請(qǐng)求轉(zhuǎn)發(fā)的實(shí)例)
這篇文章主要介紹了使用springboot跳轉(zhuǎn)到指定頁(yè)面和(重定向,請(qǐng)求轉(zhuǎn)發(fā)的實(shí)例),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Spring RabbitMQ死信機(jī)制原理實(shí)例詳解
這篇文章主要介紹了Spring RabbitMQ死信機(jī)制原理實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

