?
摘要
?
你的Java程序是否被很多隨即放置的System.out.println語(yǔ)句和stack traces(例如:ex.printStackTrace())弄亂呢?當(dāng)你加入調(diào)試信息到工程中的類中,你的信息輸出是否穿插于其他開發(fā)者的很多信息中,使得您的信息很難辨認(rèn)和讀取呢?你是否使用簡(jiǎn)單的日志API,并擔(dān)心它可能不能提供您需要的足夠的彈性和能力,當(dāng)您的程序已存在于產(chǎn)品中時(shí)呢?如果以上的問(wèn)題的答案都是Yes,到了你該選擇一個(gè)工業(yè)級(jí)和強(qiáng)大的日志API和使用它的時(shí)候了!
?
這篇文章將通過(guò)評(píng)估兩種廣為使用的Java日志庫(kù):the Apache Group's Log4j和java.util.logging包(使用JUL代替),來(lái)幫助您選擇日志API。這個(gè)文章調(diào)查了每一個(gè)庫(kù)如何實(shí)現(xiàn)日志,評(píng)價(jià)他們的區(qū)別和相似點(diǎn),并提供一些簡(jiǎn)單的指導(dǎo)路線,可以幫助您決定選擇哪一個(gè)庫(kù)。
?
Log4j的介紹
Log4j是一個(gè)開源日志庫(kù),被開發(fā)為Apache Software Foundation's日志服務(wù)項(xiàng)目的一個(gè)子項(xiàng)目。基于IBM開發(fā)的日志庫(kù)早在1990年,它的第一個(gè)版本出現(xiàn)在1999。Log4j是一個(gè)廣為使用在開源社區(qū),包括一些大型項(xiàng)目比如JBoss和Hibernate。
?
Log4j的架構(gòu)建立于三個(gè)大的概念上面:loggers,appenders,和layouts.(日志子,追加器,布局器)。這些概念允許開發(fā)者記錄信息根據(jù)他們的類型和優(yōu)先級(jí),和來(lái)控制信息在哪結(jié)束以及他們的形式。loggers是你的應(yīng)用程序首先調(diào)用的對(duì)象,用來(lái)初始化信息的日志記錄。當(dāng)loggers被給與一條信息來(lái)記錄,loggers生成了Logging-Event對(duì)象來(lái)進(jìn)行封裝給定信息。該loggers此時(shí)交接LoggingEvents給它們關(guān)聯(lián)的appender。Appenders發(fā)送LoggingEvents包含的信息到指定的輸出目的地。例如,一個(gè)ConsoleAppender將信息寫到System.out或者一個(gè)FileAppender將它附加于一個(gè)文件中。在發(fā)送LoggingEvent信息到最后輸出目的地之前,一些appender使用布局器來(lái)創(chuàng)建以預(yù)期格式格式化的對(duì)于信息的文本表達(dá)。例如,Log4j包括了XMLLayout類來(lái)用于格式化loggingEvents以XML的字符串。
?
在Log4j中,LoggingEvent被賦予一個(gè)級(jí)別來(lái)指定他們的優(yōu)先級(jí)。在Log4j中的默認(rèn)級(jí)別(從高到低):OFF,FATAL,ERROR,WARN,INFO,DEBUG,和ALL.
Loggers和appenders也被分配到一個(gè)級(jí)別,并且只有當(dāng)logging請(qǐng)求的級(jí)別比他們的級(jí)別相等并且更大時(shí),才會(huì)執(zhí)行。例如,如果一個(gè)appender他的級(jí)別是ERROR,它被請(qǐng)求輸出一個(gè)有著WARN的級(jí)別的LoggingEvent,appender將不會(huì)寫出被給與的logEvent。
?
Log4j中的所有l(wèi)oggers有一個(gè)名字。Log4j組織logger實(shí)例到一個(gè)樹型的結(jié)構(gòu)中,根據(jù)他們名字,同Java語(yǔ)言中的包的組織一樣。正如Log4j的文檔簡(jiǎn)潔的表述:“一個(gè)logger被認(rèn)為是另外的logger的祖先,如果它的名字緊跟著一個(gè)點(diǎn)是后代的這個(gè)logger名字的前綴。”例如,一個(gè)名為"org.nrdc"被認(rèn)為是"org"logger的子代。"org.nrdc.logging"logger是"org.nrdc" logger的子代,并且是"org" logger的重子代。如果logger的沒(méi)有明確的指定級(jí)別,它會(huì)使用已經(jīng)賦予級(jí)別的最近的父輩的級(jí)別。Loggers繼承appenders從他們的父類,盡管他們也能被配置只使用直接賦給他們的appender。
?
當(dāng)一個(gè)logger被請(qǐng)求來(lái)記錄信息,它首先檢查請(qǐng)求的級(jí)別是否比它的有效級(jí)別相同或者更大。如果是,它就創(chuàng)建LoggingEvent根據(jù)給定的信息,并傳送LoggingEvent到它的appenders,格式它,并發(fā)送它到輸出目的地。
?
JUL的介紹
?
java.util.logging包,Sun在2002年 Java SDK 1.4中介紹了它,作為JSR 47到來(lái)的,Logging API 規(guī)范。JUL非常類似于Log4j - 它多多少少的正確的使用了同樣的概念,但是對(duì)他們重新命名了。例如,appenders 叫 “handlers”,layout 叫 “formatters”,并且LoggingEvent叫做“LogRecords”。圖片1,匯總了Log4j和JUL的名稱和概念。JUL使用級(jí)別與Log4j使用級(jí)別是一樣的,并且JUL日志繼承屬性properties從他們父loggers中,有點(diǎn)像Log4j繼承屬性從父層次中。從Log4j到JUL概念幾乎是一對(duì)一的;雖然兩個(gè)庫(kù)在細(xì)節(jié)上有所不同,任何熟悉Log4j的開發(fā)者只需要調(diào)整他們的詞庫(kù)就可以理解JUL。
?
功能不同點(diǎn)
?
雖然Log4j和JUL幾乎有同樣的概念,他們?cè)诠δ苌喜煌K麄兊目梢詺w納為,“無(wú)論JUL能不能做成什么,Log4j都能做 - 并且做得更多。”他們主要在幾個(gè)領(lǐng)域不同,appender/handler的實(shí)現(xiàn),有用的格式化器/布局實(shí)現(xiàn)器,和配置靈活性上。
?
JUL包含4種具體的handler的實(shí)現(xiàn),而Log4j則包括超過(guò)12個(gè)的appender實(shí)現(xiàn)。JUL的handler足夠用來(lái)進(jìn)行基本的日志記錄 - 他們?cè)试S你寫入到一個(gè)buffer,一個(gè)console,一個(gè)socket,和一個(gè)file中。Log4j的appenders,另一方面,大概覆蓋了所有l(wèi)ogging輸出目的地你可以想到的。他們可以寫到NT日志或者Unix syslog中,或者甚至發(fā)送Email。圖片2提供了JUL的handler和Log4j的appenders的匯總。
?
JUL包含了兩個(gè)格式化類:XMLFormatter和SimpleFormatter。Log4j包含了對(duì)應(yīng)的布局器:XMLLayout和SimpleLayout.Log4j還提供了TTCCLayout,它格式化LoggingEvents到富內(nèi)容字符串,和HTMLLayout,它可格式化LoggingEvent到HMTL表格中。
?
TTCCLayout和HTMLLayout都很有用,Log4j的確領(lǐng)先于JUL,在formatter/handler方面,由于PatternLayout。PatternLayout實(shí)例能夠采用一個(gè)通過(guò)字符轉(zhuǎn)換式模式而帶來(lái)具有大量有彈性的被配置,類似于在C中的printf函數(shù)的表達(dá)式類型。在PatternLayout轉(zhuǎn)換式模式中,特定轉(zhuǎn)化字符被用來(lái)指定在布局格式化輸出的信息。例如,"%t"被用來(lái)指定開始記錄信息的線程;"%C"被用于開始記錄信息的對(duì)象的類的名稱;并且"%m"指定了信息。"%t: %m"將導(dǎo)致輸出類似于這樣"main thread:This is my message." "%C - %t:%m"會(huì)導(dǎo)致輸出類似于"org.nrdc.My-Class - main thread:This is my message." Pattern-Layout非常有用,然而JUL的兩個(gè)formatter類沒(méi)有任何地方來(lái)匹配這樣的多功能性。對(duì)于JUL使用者,自行定制formatter類是很少見,反之大多數(shù)Log4j用戶通常需要學(xué)會(huì)如何使用PatternLayout轉(zhuǎn)換式模式。
?
Log4j和JUL同時(shí)都能夠使用配置文件進(jìn)行配置,Log4j允許更廣范圍內(nèi)的配置的可能性相對(duì)于JUL使用的配置文件。JUL能夠使用.properties文件配置,但是到了J2SE5.0之前,handlers的配置只能是對(duì)于每一個(gè)類的而不是對(duì)于每一個(gè)實(shí)例。這就意味著如果你將使用Tiger版本的SDK,你將遺漏有用的配置選擇,例如可以設(shè)置不同的FileHandler實(shí)例發(fā)送他們的輸出到不同的文件中。
?
非常重要的,注意Tiger版的JUL能夠很容易的被配置為寫到多個(gè)文件,通過(guò)編寫代碼,而不是通過(guò)默認(rèn)的配置機(jī)制。Log4j能夠通過(guò).properties文件或者XML文件配置,并且appenders能夠以每一個(gè)實(shí)例為基礎(chǔ)進(jìn)行配置。同時(shí),Log4j允許開發(fā)者關(guān)聯(lián)布局實(shí)例和appender實(shí)例,并以每一個(gè)實(shí)例為基礎(chǔ)進(jìn)行配置布局。這包括PatternLayout實(shí)例 - 你能夠設(shè)置轉(zhuǎn)換式每一個(gè)模式的使用,在配置文件中。在開發(fā)過(guò)程中,通過(guò)重新編譯來(lái)調(diào)整日志配置不是問(wèn)題,開發(fā)結(jié)束后,然而,你或許不想通過(guò)重新編譯來(lái)改變或者完全重新配置應(yīng)用中的日志。這時(shí),Log4j提供了更多的彈性,尤其使用Tiger。
?
Log4j提供了很多JUL缺少的功能,雖然JUL正在趕上。JUL可以完全擴(kuò)展后,來(lái)做Log4j做的事情 - 你可以寫更多的handlers,重新實(shí)現(xiàn)PatternLayout來(lái)為JUL,并且更新JUL配置機(jī)制,這些都不是很難。但是要在Log4j已存在這些特色數(shù)年時(shí),為什么還做這些事呢?
?
你要選擇哪一個(gè)庫(kù)呢?
?
類似于這樣的重要決定經(jīng)常使得leaders失眠或者過(guò)早衰老。幸運(yùn)的是,這個(gè)決定可以通過(guò)檢測(cè)對(duì)于簡(jiǎn)單的問(wèn)題后,容易的做出。
?
問(wèn)題1
你過(guò)早需要那些JUL沒(méi)有而Log4j有的handlers,例如SMTPHandler,NTEventLogHandler,或者其他任何非常便利的FileHandlers么?
?
問(wèn)題2
你是否想頻繁的切換你日志輸出的格式?你是否需要簡(jiǎn)單的方式這樣做?另外,你是否需要Log4j的PatternLayout?
?
問(wèn)題3
你是否明確的需要在您的應(yīng)用中有這種能力,來(lái)改變復(fù)雜的日志配置在您的應(yīng)用中,即使他們已經(jīng)被編譯了并且部署到產(chǎn)品環(huán)境了?你的配置是不是聽起來(lái)像:“來(lái)自這個(gè)類的幾條信息通過(guò)郵件發(fā)送給技術(shù)支持工作者;類子集的幾條信息被記錄于我們服務(wù)器的syslog中;類子集的警告信息以一個(gè)文件記錄于網(wǎng)絡(luò)磁盤A中;并且各處所有信息以文件記錄于網(wǎng)絡(luò)磁盤B”?你是否沒(méi)過(guò)10幾天,就會(huì)改變一下?
?
如果你對(duì)上面的問(wèn)題都回答Yes,使用Log4j。如果你的回答全是明確的No,JUL足夠了,它已存在SDK中了。
?
結(jié)論
Log4j和JUL是非常相似的API。他們只在一些細(xì)節(jié)上不同,最后做的是同樣的事情,除了Log4j有了更多的特色,但也許你用不到。
?
緊記,當(dāng)你移植到你選擇的日志庫(kù),那么日志將影響應(yīng)用的性能。使得影響最小化的方法,就是盡量的重用loggers的引用;保存靜態(tài)或者引用指針到loggers,而不是每次你需要一個(gè)logger時(shí),調(diào)用Logger.getLogger("loggerName")。log表達(dá)式放置于公有區(qū)域,而不是循環(huán)中。
?
這篇文章不是深入研究如何使用Log4j或者JUL的教程,并且,實(shí)際上,演示了兩個(gè)庫(kù)很多的有用的特點(diǎn),例如MBeans支持(J2SE5.0,你能夠設(shè)置JUL記錄級(jí)別遠(yuǎn)程的通過(guò)JMX),和ResourceBundle支持。還有很多Log4j的高級(jí)特點(diǎn),例如filter鏈和Object-Renderers。因特網(wǎng)有很多如何使用他們的教程,JDJ中也有;在編碼之前,一定找到并學(xué)習(xí)他們。
?
?
?
資源
?
posted on 2005-10-27 12:37
北國(guó)狼人的BloG 閱讀(4311)
評(píng)論(1) 編輯 收藏 所屬分類:
翻譯Java文章