不知道看到這篇文章的Java工程師有沒有考慮過這個(gè)問題:為什么在企業(yè)開發(fā)中會選擇logback來記錄日志,而不是log4j呢?
如果你以前沒有考慮過這個(gè)問題,那么現(xiàn)在如果讓你考慮一下,你可能覺的會是因?yàn)槭裁丛蚰??本文就來為你回答這個(gè)問題。
無論從設(shè)計(jì)上還是實(shí)現(xiàn)上,Logback相對log4j而言有了相對多的改進(jìn)。不過盡管難以一一細(xì)數(shù),這里還是列舉部分理由為什么選擇logback而不是log4j。牢記logback與log4j在概念上面是很相似的,它們都是有同一群開發(fā)者建立。所以如果你已經(jīng)對log4j很熟悉,你也可以很快上手logback。如果你喜歡使用log4j,你也許會迷上使用logback。
1. 更快的執(zhí)行速度
基于我們先前在log4j上的工作,logback 重寫了內(nèi)部的實(shí)現(xiàn),在某些特定的場景上面,甚至可以比之前的速度快上10倍。在保證logback的組件更加快速的同時(shí),同時(shí)所需的內(nèi)存更加少。
2.更充足的測試
Logback 歷經(jīng)了幾年,數(shù)不清小時(shí)數(shù)的測試。盡管log4j也是測試過的,但是Logback的測試更加充分,跟log4j不在同一個(gè)級別。我們認(rèn)為,這正是人們選擇Logback而不是log4j的最重要的原因。人們都希望即使在惡劣的條件下,你的日記框架依然穩(wěn)定而可靠。
3. logback-classic 非常自然的實(shí)現(xiàn)了SLF4J
logback-classic中的登陸類自然的實(shí)現(xiàn)了SLF4J。當(dāng)你使用 logback-classic作為底層實(shí)現(xiàn)時(shí),涉及到LF4J日記系統(tǒng)的問題你完全不需要考慮。更進(jìn)一步來說,由于 logback-classic強(qiáng)烈建議使用SLF4J作為客戶端日記系統(tǒng)實(shí)現(xiàn),如果需要切換到log4j或者其他,你只需要替換一個(gè)jar包即可,不需要去改變那些通過SLF4J API 實(shí)現(xiàn)的代碼。這可以大大減少更換日記系統(tǒng)的工作量。
4. 擴(kuò)展文檔
Logback附帶詳細(xì)的和不斷更新的文檔。
5.使用XML配置文件或者Groovy
配置logback的傳統(tǒng)方法是通過XML文件。在文檔中,大部分例子都是是用XML語法。但是,對于logback版本0.9.22,通過Groovy編寫的配置文件也得到支持。相比于XML,Groovy風(fēng)格的配置文件更加直觀,連貫和簡短的語法。
現(xiàn)在, 已經(jīng)有一個(gè)工具自動把logback.xml文件遷移至logback.groovy。
6.自動重新載入配置文件
Logback-classic可以在配置文件被修改后,自動重新載入。這個(gè)掃描過程很快,無資源爭用,并且可以動態(tài)擴(kuò)展支持在上百個(gè)線程之間每秒上百萬個(gè)調(diào)用。它和應(yīng)用服務(wù)器結(jié)合良好,并且在JEE環(huán)境通用,因?yàn)樗粫{(diào)用創(chuàng)建一個(gè)單獨(dú)的線程來做掃描。
7.優(yōu)雅地從I/O錯誤中恢復(fù)
FileAppender和它的子類,包括RollingFileAppender,可以優(yōu)雅的從I/O錯誤中恢復(fù)。所以,如果一個(gè)文件服務(wù)器臨時(shí)宕機(jī),你再也不需要重啟你的應(yīng)用,而日志功能就能正常工作。當(dāng)文件服務(wù)器恢復(fù)工作,logback相關(guān)的appender就會透明地和快速的從上一個(gè)錯誤中恢復(fù)。
8.自動清除舊的日志歸檔文件
通過設(shè)置TimeBasedRollingPolicy 或者 SizeAndTimeBasedFNATP的 maxHistory 屬性,你就可以控制日志歸檔文件的最大數(shù)量。如果你的回滾策略是每月回滾的,并且你希望保存一年的日志,那么只需簡單的設(shè)置maxHistory屬性為12。對于12個(gè)月之前的歸檔日志文件將被自動清除。
9. 自動壓縮歸檔日志文件
RollingFileAppender可以在回滾操作中,自動壓縮歸檔日志文件。壓縮通常是異步執(zhí)行的,所以即使是很大的日志文件,你的應(yīng)用都不會因此而被阻塞。
10. 謹(jǐn)慎模式
在謹(jǐn)慎模式中,在多個(gè)JVM中運(yùn)行的多個(gè)FileAppender實(shí)例,可以安全的寫入統(tǒng)一個(gè)日志文件。謹(jǐn)慎模式可以在一定的限制條件下應(yīng)用于RollingFileAppender。
11.Lilith
Lilith是logback的一個(gè)記錄和訪問事件查看器。它相當(dāng)于log4j的 chainsaw,但是Lilith設(shè)計(jì)的目的是處理大量的日志記錄。
12. 配置文件中的條件處理
開發(fā)者通常需要在不同的目標(biāo)環(huán)境中變換logback的配置文件,例如開發(fā)環(huán)境,測試環(huán)境和生產(chǎn)環(huán)境。這些配置文件大體是一樣的,除了某部分會有不同。為了避免重復(fù),logback支持配置文件中的條件處理,只需使用<if>,<then>和<else>,那么同一個(gè)配置文件就可以在不同的環(huán)境中使用了。
13.過濾
Logback擁有遠(yuǎn)比log4j更豐富的過濾能力。例如,讓我們假設(shè),有一個(gè)相當(dāng)重要的商業(yè)應(yīng)用部署在生產(chǎn)環(huán)境。考慮到大量的交易數(shù)據(jù)需要處理,記錄級別被設(shè)置為WARN,那么只有警告和錯誤信息才會被記錄?,F(xiàn)在,想象一下,你在開發(fā)環(huán)境遇到了一個(gè)臭蟲,但是在測試平臺中卻很難發(fā)現(xiàn),因?yàn)橐恍┉h(huán)境之間(生產(chǎn)環(huán)境/測試環(huán)境)的未知差異。
使用log4j,你只能選擇在生產(chǎn)系統(tǒng)中降低記錄的級別到DEBUG,來嘗試發(fā)現(xiàn)問題。但是很不幸,這會生成大量的日志記錄,讓分析變得困難。更重要的是,多余的日志記錄會影響到生產(chǎn)環(huán)境的性能。
使用logback,你可以選擇保留只所有用戶的WARN級別的日志,而除了某個(gè)用戶,例如Alice,而她就是問題的相關(guān)用戶。當(dāng)Alice登錄系統(tǒng),她就會以DEBUG級別被記錄,而其他用戶仍然是以WARN級別來記錄日志。這個(gè)功能,可以通過在配置文件的XML中添加4行。請?jiān)谙嚓P(guān)章節(jié)中查找MDCFilter
14. SiftingAppender
SiftingAppender是一個(gè)全能的追加器。它可以基于任何給定的實(shí)時(shí)屬性分開(或者篩選)日志。例如,SiftingAppender可以基于用戶會話分開日志事件,這樣,可以為每一個(gè)用戶建立一個(gè)獨(dú)立的日志文件。
15. 堆棧軌跡信息包含包的數(shù)據(jù)
當(dāng)logback打印一個(gè)異常,堆棧軌跡信息將包含包的相關(guān)數(shù)據(jù)。下面是一個(gè)通過 logback-demo 生成的堆棧信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 14 : 28 : 48.835 [btpool0- 7 ] INFO c.q.l.demo.prime.PrimeAction - 99 is not a valid value java.lang.Exception: 99 is invalid at ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java: 28 ) [classes/:na] at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java: 431 ) [struts- 1.2 . 9 .jar: 1.2 . 9 ] at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java: 236 ) [struts- 1.2 . 9 .jar: 1.2 . 9 ] at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java: 432 ) [struts- 1.2 . 9 .jar: 1.2 . 9 ] at javax.servlet.http.HttpServlet.service(HttpServlet.java: 820 ) [servlet-api- 2.5 - 6.1 . 12 .jar: 6.1 . 12 ] at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java: 502 ) [jetty- 6.1 . 12 .jar: 6.1 . 12 ] at ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java: 44 ) [classes/:na] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java: 1115 ) [jetty- 6.1 . 12 .jar: 6.1 . 12 ] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java: 361 ) [jetty- 6.1 . 12 .jar: 6.1 . 12 ] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java: 417 ) [jetty- 6.1 . 12 .jar: 6.1 . 12 ] at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java: 230 ) [jetty- 6.1 . 12 .jar: 6.1 . 12 ] |
從上面的信息,你可以發(fā)現(xiàn)這個(gè)應(yīng)用使用Struts 1.2.9 而且是使用 jetty 6.1.12部署的。所以,堆棧軌跡信息將快速的告訴讀者,關(guān)于異常發(fā)生的類還有包和包的版本。當(dāng)你的客戶發(fā)送一個(gè)堆棧軌跡信息給你,作為一個(gè)開發(fā)人員,你就不需要讓他們告訴你他們正在使用的包的版本。這項(xiàng)信息已經(jīng)包括在堆棧軌跡信息中。詳細(xì)請參考 "%xThrowable" conversion word.
這項(xiàng)功能可以非常有幫助的說明,有些用戶誤以為這是IDE的功能。
16. Logback-access模塊,提供了通過HTTP訪問日志的能力,是logback不可或缺的組成部分
最后但絕非最不重要的是,作為logback發(fā)布包的一部分,logback-access模塊可與Jetty或者Tomcat進(jìn)行集成,提供了非常豐富而強(qiáng)大的通過HTTP訪問日志的功能。因?yàn)閘ogback-access模塊是logback初期設(shè)計(jì)方案中的一部分,因此,所有你所喜歡的logback-classic模塊所提供的全部特性logback-access同樣也具備。
我們給出了許多選擇logback而不選擇log4j的理由。簡而言之,既然logback構(gòu)建于我們先前所構(gòu)建的log4j之上,logback可以說就是一個(gè)更好的log4j。