java日志概述
對(duì)于一個(gè)應(yīng)用程序來說日志記錄是必不可少的一部分。線上問題追蹤,基于日志的業(yè)務(wù)邏輯統(tǒng)計(jì)分析等都離不日志。java領(lǐng)域存在多種日志框架,目前常用的日志框架包括Log4j,Log4j 2,Commons Logging,Slf4j,Logback,Jul。
java常用日志框架類別介紹
Log4j Apache Log4j是一個(gè)基于Java的日志記錄工具。它是由Ceki Gülcü首創(chuàng)的,現(xiàn)在則是Apache軟件基金會(huì)的一個(gè)項(xiàng)目。 Log4j是幾種Java日志框架之一。
Log4j 2 Apache Log4j 2是apache開發(fā)的一款Log4j的升級(jí)產(chǎn)品。
Commons Logging Apache基金會(huì)所屬的項(xiàng)目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名為Commons Logging。
Slf4j 類似于Commons Logging,是一套簡(jiǎn)易Java日志門面,本身并無日志的實(shí)現(xiàn)。(Simple Logging Facade for Java,縮寫Slf4j)。
Logback 一套日志組件的實(shí)現(xiàn)(slf4j陣營)。
Jul (Java Util Logging),自Java1.4以來的官方日志實(shí)現(xiàn)。
看了上面的介紹是否會(huì)覺得比較混亂,這些日志框架之間有什么異同,都是由誰在維護(hù)? 下文會(huì)逐一介紹。
Java常用日志框架歷史
1996年早期,歐洲安全電子市場(chǎng)項(xiàng)目組決定編寫它自己的程序跟蹤API(Tracing API)。經(jīng)過不斷的完善,這個(gè)API終于成為一個(gè)十分受歡迎的Java日志軟件包,即Log4j。后來Log4j成為Apache基金會(huì)項(xiàng)目中的一員。
期間Log4j近乎成了Java社區(qū)的日志標(biāo)準(zhǔn)。據(jù)說Apache基金會(huì)還曾經(jīng)建議sun引入Log4j到j(luò)ava的標(biāo)準(zhǔn)庫中,但Sun拒絕了。
2002年Java1.4發(fā)布,Sun推出了自己的日志庫JUL(Java Util Logging),其實(shí)現(xiàn)基本模仿了Log4j的實(shí)現(xiàn)。在JUL出來以前,log4j就已經(jīng)成為一項(xiàng)成熟的技術(shù),使得log4j在選擇上占據(jù)了一定的優(yōu)勢(shì)。
接著,Apache推出了Jakarta Commons Logging,JCL只是定義了一套日志接口(其內(nèi)部也提供一個(gè)Simple Log的簡(jiǎn)單實(shí)現(xiàn)),支持運(yùn)行時(shí)動(dòng)態(tài)加載日志組件的實(shí)現(xiàn),也就是說,在你應(yīng)用代碼里,只需調(diào)用Commons Logging的接口,底層實(shí)現(xiàn)可以是log4j,也可以是Java Util Logging。
后來(2006年),Ceki Gülcü不適應(yīng)Apache的工作方式,離開了Apache。然后先后創(chuàng)建了slf4j(日志門面接口,類似于Commons Logging)和Logback(Slf4j的實(shí)現(xiàn))兩個(gè)項(xiàng)目,并回瑞典創(chuàng)建了QOS公司,QOS官網(wǎng)上是這樣描述Logback的:The Generic,Reliable Fast&Flexible Logging Framework(一個(gè)通用,可靠,快速且靈活的日志框架)。
現(xiàn)今,Java日志領(lǐng)域被劃分為兩大陣營:Commons Logging陣營和SLF4J陣營。
Commons Logging在Apache大樹的籠罩下,有很大的用戶基數(shù)。但有證據(jù)表明,形式正在發(fā)生變化。2013年底有人分析了GitHub上30000個(gè)項(xiàng)目,統(tǒng)計(jì)出了最流行的100個(gè)Libraries,可以看出slf4j的發(fā)展趨勢(shì)更好:
- Apache眼看有被Logback反超的勢(shì)頭,于2012-07重寫了log4j 1.x,成立了新的項(xiàng)目Log4j 2。Log4j 2具有l(wèi)ogback的所有特性。
java常用日志框架之間的關(guān)系
Log4j2與Log4j1發(fā)生了很大的變化,log4j2不兼容log4j1。
Commons Logging和Slf4j是日志門面(門面模式是軟件工程中常用的一種軟件設(shè)計(jì)模式,也被稱為正面模式、外觀模式。它為子系統(tǒng)中的一組接口提供一個(gè)統(tǒng)一的高層接口,使得子系統(tǒng)更容易使用)。log4j和Logback則是具體的日志實(shí)現(xiàn)方案??梢院?jiǎn)單的理解為接口與接口的實(shí)現(xiàn),調(diào)用這只需要關(guān)注接口而無需關(guān)注具體的實(shí)現(xiàn),做到解耦。
比較常用的組合使用方式是Slf4j與Logback組合使用,Commons Logging與Log4j組合使用。
Logback必須配合Slf4j使用。由于Logback和Slf4j是同一個(gè)作者,其兼容性不言而喻。
Commons Logging與Slf4j實(shí)現(xiàn)機(jī)制對(duì)比
Commons logging實(shí)現(xiàn)機(jī)制
Commons logging是通過動(dòng)態(tài)查找機(jī)制,在程序運(yùn)行時(shí),使用自己的ClassLoader尋找和載入本地具體的實(shí)現(xiàn)。詳細(xì)策略可以查看commons-logging-*.jar包中的org.apache.commons.logging.impl.LogFactoryImpl.java文件。由于OSGi不同的插件使用獨(dú)立的ClassLoader,OSGI的這種機(jī)制保證了插件互相獨(dú)立, 其機(jī)制限制了commons logging在OSGi中的正常使用。
Slf4j實(shí)現(xiàn)機(jī)制
Slf4j在編譯期間,靜態(tài)綁定本地的LOG庫,因此可以在OSGi中正常使用。它是通過查找類路徑下org.slf4j.impl.StaticLoggerBinder,然后綁定工作都在這類里面進(jìn)。
如果在項(xiàng)目中如果選擇日志框架
如果是在一個(gè)新的項(xiàng)目中建議使用Slf4j與Logback組合,這樣有如下的幾個(gè)優(yōu)點(diǎn)。
Slf4j實(shí)現(xiàn)機(jī)制決定Slf4j限制較少,使用范圍更廣。由于Slf4j在編譯期間,靜態(tài)綁定本地的LOG庫使得通用性要比Commons logging要好。
Logback擁有更好的性能。Logback聲稱:某些關(guān)鍵操作,比如判定是否記錄一條日志語句的操作,其性能得到了顯著的提高。這個(gè)操作在Logback中需要3納秒,而在Log4J中則需要30納秒。LogBack創(chuàng)建記錄器(logger)的速度也更快:13毫秒,而在Log4J中需要23毫秒。更重要的是,它獲取已存在的記錄器只需94納秒,而Log4J需要2234納秒,時(shí)間減少到了1/23。跟JUL相比的性能提高也是顯著的。
Commons Logging開銷更高 在使Commons Logging時(shí)為了減少構(gòu)建日志信息的開銷,通常的做法是:
if(log.isDebugEnabled()){
log.debug("User name: " +
user.getName() + " buy goods id :" + good.getId());
}
在Slf4j陣營,你只需這么做:
log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());
也就是說,slf4j把構(gòu)建日志的開銷放在了它確認(rèn)需要顯示這條日志之后,減少內(nèi)存和cup的開銷,使用占位符號(hào),代碼也更為簡(jiǎn)潔
Logback文檔免費(fèi)。Logback的所有文檔是全面免費(fèi)提供的,不象Log4J那樣只提供部分免費(fèi)文檔而需要用戶去購買付費(fèi)文檔。
如何在項(xiàng)目中使用Slf4j
Slf4j與其他各種日志組件的橋接
jar包名 |
說明 |
slf4j-log4j12-1.7.13.jar |
log4j1.2版本的橋接器,你需要將log4j.jar加入classpath。 |
slf4j-jdk14-1.7.13.jar |
java.util.logging的橋接器,JDK原生日志框架。 |
slf4j-nop-1.7.13.jar |
NOP橋接器,默默丟棄一切日志。 |
slf4j-simple-1.7.13.jar |
一個(gè)簡(jiǎn)單實(shí)現(xiàn)的橋接器,該實(shí)現(xiàn)輸出所有事件到System.err. 只有INFO以及高于該級(jí)別的消息被打印,在小型應(yīng)用中它也許是有用的。 |
slf4j-jcl-1.7.13.jar |
Jakarta Commons Logging 的橋接器. 這個(gè)橋接器將SLF4j所有日志委派給JCL。 |
logback-classic-1.0.13.jar(requires logback-core-1.0.13.jar) |
slf4j的原生實(shí)現(xiàn),logback直接實(shí)現(xiàn)了slf4j的接口,因此使用slf4j與 logback的結(jié)合使用也意味更小的內(nèi)存與計(jì)算開銷 |
具體的接入方式參見下圖
如何橋接遺留的api
在實(shí)際環(huán)境中我們經(jīng)常會(huì)遇到不同的組件使用的日志框架不同的情況,例如Spring Framework使用的是日志組件是Commons logging,XSocket依賴的則是Java Util Logging。當(dāng)我們?cè)谕豁?xiàng)目中使用不同的組件時(shí)應(yīng)該如果解決不同組件依賴的日志組件不一致的情況呢?現(xiàn)在我們需要統(tǒng)一日志方案,統(tǒng)一使用SLF4J,把他們的日志輸出重定向到SLF4J,然后 SLF4J 又會(huì)根據(jù)綁定器把日志交給具體的日志實(shí)現(xiàn)工具。Slf4j帶有幾個(gè)橋接模塊,可以重定向log4j,JCL和java.util.logging中的API到Slf4j。
遺留的api橋接方案
jar包名 |
作用 |
log4j-over-slf4j-version.jar |
將log4j重定向到slf4j |
jcl-over-slf4j-version.jar |
將commos logging里的Simple Logger重定向到slf4j |
jul-to-slf4j-version.jar |
將Java Util Logging重定向到slf4j |
橋接方式參見下圖
使用slf4j橋接要注意事項(xiàng)
在使用slf4j橋接時(shí)要注意避免形成死循環(huán),在項(xiàng)目依賴的jar包中不要存在以下情況。
多個(gè)日志jar包形成死循環(huán)的條件 |
產(chǎn)生原因 |
log4j-over-slf4j.jar和slf4j-log4j12.jar同時(shí)存在 |
由于slf4j-log4j12.jar的存在會(huì)將所有日志調(diào)用委托給log4j。但由于同時(shí)由于log4j-over-slf4j.jar的存在,會(huì)將所有對(duì)log4j api的調(diào)用委托給相應(yīng)等值的slf4j,所以log4j-over-slf4j.jar和slf4j-log4j12.jar同時(shí)存在會(huì)形成死循環(huán) |
jul-to-slf4j.jar和slf4j-jdk14.jar同時(shí)存在 |
由于slf4j-jdk14.jar的存在會(huì)將所有日志調(diào)用委托給jdk的log。但由于同時(shí)jul-to-slf4j.jar的存在,會(huì)將所有對(duì)jul api的調(diào)用委托給相應(yīng)等值的slf4j,所以jul-to-slf4j.jar和slf4j-jdk14.jar同時(shí)存在會(huì)形成死循環(huán) |
參考鏈接
slf4j官網(wǎng)
slf4j使用手冊(cè)1
slf4j使用手冊(cè)2
logback官網(wǎng)
commons logging官網(wǎng)
|