FAQ about log4j

譯者聲明:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

1.       這是根據最新的log4j(jakarta-log4j-1.2.8)的開發包自帶文檔的FAQ翻譯的

2.       譯者盡力保持原文格式,以便於讀者查找原文

3.       粉紅色的標題代表原文只有標題,而沒有相應的內容

4.       對一些關鍵詞都帶有原文單詞,便於閱讀

5.       原文中比較生僻的單詞,譯者都是參考金山詞霸,對找不到的組合詞都是保持原文。

6.       對比較拗口的說法,譯者儘量採用意譯的方法,同時保持原文。

王建

2004616

·         什麼是log4j?

·         Log4j是一個可靠的日誌系統嗎?

·         什麼是log4j的先決條件?

·         log4j有javadoc文檔嗎?(Is there javadoc documentation for log4j? )

·         有其他的日誌包嗎?(What other logging packages are there? )

·         有使用log4j的實例代碼嗎?

·         log4j有那些特性呢?

·         log4j是線程安全的嗎?

·         日誌輸出看起來是什麼樣子?

·         什麼是記錄器?

·         怎樣才能改變日誌運行時的行爲?

·         日誌記錄(或者不記錄)最快的方法是什麼?

·         除了把字符串數組作爲參數之一輸出,調試方法還有其他作用嗎?(What is the use of the debug method expecting a String array as one of its parameters?)

·         爲什麼要介紹記錄器(Logger)類,並且我怎樣才能從基於以前實現(implementation)的字符串移植?(Why was the Logger class introduced and how do I migrate from the previous String based implementation?)

·         在記錄器的命名方面,有什麼建議嗎?

·         我怎樣才能用靜態模式(in a static block)的方式得到一個高質量(fully-qualified)的類名

·         日誌輸出可以自定義嗎?

·         什麼是ForBarAppender的配置選項?

·         多客戶端請求的輸出可以對應不同的日誌文件嗎?

·         記錄器實例好像僅僅可以被創建,爲什麼沒有一個方法可以移除記錄器實例?

·         按照不同的等級,可以把日誌輸出定向到不動的輸出源(appender)嗎?

·         我怎樣才能對同一個文件獲得多個處理進程?

·         假如我有許多跨越多個主機(可能跨越多個時區)的處理進程用上述方法記錄日誌到相同的文件,時間戳會發生什麼事情?

·         爲什麼在J2EE或者WAR應用程序中log4j不能發現我的屬性文件?

·         假如屬性文件改變,是否有方法讓log4j自動加載?

·         當我使用NTEventLogAppender類時,Windows NT事件觀察器(Windows NT Event Viewer)對丟失我的事件信息描述行爲會有什麼樣的反應?

·         當我使用NTEventLogAppender類時,爲什麼我不能映射我的記錄器名到顯示在NT事件記錄器(NT Event Log)中的記錄器

·         我爲什麼要把我的log4j擴展捐贈(donate)給項目呢?

·         當捐贈代碼時,我應該緊記什麼?

·         在哪可以找到最新的log4j發行版?

什麼是log4j?

Log4j是一款幫助程序員輸出日誌信息到輸出目的地的工具

在一個帶有問題的應用程序中,使用日誌來定位錯誤使很有幫助的。在運行情況下,不修改二進制應用程序使用log4j是可以使日誌起作用的。Log4j包被設計用來使日誌信息可以用漂碼(shipped code)的形式保存,並且不會導致高性能開銷。它遵循記錄速度(即使沒有記錄行爲)第一的原則

同時,日誌輸出可能是那麼的龐大以至於無法記錄。Log4j中獨一無二的特色之一是分級記錄器(Logger)的概念。使用記錄器,使有選擇的按任意粒度控制輸出日誌成爲可能。

Log4j是按兩個特殊目來設計的:速度和靈活性。在這兩個必備要求中間,很難找到一個平衡點。不過,我相信log4j達到最好的平衡點

log4j是可靠的日誌系統嗎?

Log4j是不可靠的,它是一個best-effortfail-stop的日誌系統

提到fail-stop,我們意思是log4j運行在有導致系統崩潰的潛在錯誤的運行狀態,它不會拋出意料之外的異常。假如由於某些原因,導致log4j拋出一個未被捕捉的異常,請發email到[email protected]郵件列表

還有,當log4j指定的輸出流(output stream)處於未打開、不可寫或者已滿的狀態時,它不會轉向輸出到System.out和System.err。這就避免了由於日誌記錄失敗,使用戶的終端充滿錯誤信息,因而導致另一個正在運行的程序一團槽。然而,log4j將輸出一個單條信息到System.err表明日誌不能正常運行。

log4j的先決條件是什麼?

·         Log4j是和JDK 1.1.x 兼容的。

·         DOMConfigurator是基於the DOM Level 1 API。DOMConfigurator.configure(Element)方法將和任何可以把XML文件解析成DOM書(DOM tree)的XML解析器很好工作,DOMConfigurator.configure(String filename)方法和它的變量需要一個和JAXP兼容的XML解析器,例如Xerces(譯註:這也是Apache下面的一個開源項目)或者SUN公司的解析器。編譯DOMConfigurator時要求JAXP解析器要在classpath環境變量的路徑下面

·         org.apache.log4j.net.SMTPAppender類依賴於JavaMail API。它已經和JavaMail API的1.2版本測試過了。JavaMail API需要JavaBeans Activation Framework

·         org.apache.log4j.net.JMSAppender類需要JMS API和JNDI的存在

·         log4j的測試代碼(test code)依賴於JUnit測試框架

有使用log4j的實例代碼嗎?

參見examples/路徑。

log4j有那些特性?

·         Log4j在速度方面已經被優化過了

  • Log4j是基於記錄器層次命名的(log4j is based on a named logger hierarchy.)
  • Log4jfail-stop但是沒有依賴性(log4j is fail-stop but not reliable.)
  • Log4j是線程安全的
  • Log4j是不受預先確定一套工具限制的
  • 運行時,日誌行爲可以被放置在一個配置文件中配置文件可以是屬性文件或者XML格式的
  • 剛開始時,Log4j被設計處理java異常(Exceptions)
  • Log4j可以定向它的的輸出到一個文件,控制檯,輸出流(java.io.OutputStream) ,輸出器(java.io. Writer) ,一個套接字遠程服務器(a remote server using TCP),一個遠程的UNIX Syslog守護線程(Unix Syslog daemon),一個遠程的JMS的監聽線程,NT事件的記錄器,甚至發email
  • Log4j使用了5個級別,名稱分別爲DEBUG, INFO, WARN, ERROR and FATAL
  • 日誌的輸出格式通過擴張Layout類可以很簡單的被改變
  • 日誌輸出的目標和寫策略(the writing strategy)一樣可以工作實現Appender接口被改變。
  • Log4j支持每個記錄器可以有多個輸出源(multiple output appenders per logger)
  • Log4j支持國際化。

log4j是線程安全的嗎?

對,log4j是線程安全的

日誌輸出看起來是什麼樣子?

可以用多種方式定製日誌輸出。而且,可以通過實現一個自己的佈局器(Layout)來完全覆蓋輸出格式

這是一個使用PatternLayout佈局器的輸出實例,這個佈局器帶"%r [%t] %-5p %c{2} %x - %m%n"的轉換格式

第一個字段是從程序開始運行到該行日誌輸出的毫秒數。第二個字段是輸出日誌的線程。第三個是日誌描述的級別。第四個字段是發出日誌請求的記錄器(logger making the log request)的最右面兩個部分的組成。第五個字段(恰好在‘-’的前面)是嵌套診斷環境(nested diagnostic context (NDC)).注意嵌套診斷環境(NDC)可以是空的,就像剛開始的兩個描述。緊跟在‘-’後面的是描述信息

什麼是記錄器(Loggers)?

記錄器處於log4j的核心地位。記錄器定義了一個層次(hierarchy),並且給程序員運行時的控制是否打印控制的描述信息

記錄器被分配級別。一個日誌描述的打印依賴於他的級別和記錄器

閱讀log4j的使用手冊(log4j manual)獲取更多信息

怎樣才能改變日誌運行時的行爲?

日誌行爲可以被設置在一個配置文件中,在運行時可以解析這個文件。使用配置文件,程序員可以定義一個記錄器並且設置它的級別

PropertyConfigurator類定義了一個特殊的配置文件的格式。也可以參考examples/Sort.java實例的配置文件。

配置文件可以是XML文件。參考log4j.dtd和org.log4j.xml.DOMConfigurator類獲取更多信息

參考各種爲實現特別配置選項的佈局(Layout)和輸出源(Appender)組件。

包括配置文件,使用者可以使附屬於一套級別的所有信息無效,參考下一條。

日誌記錄(或者不記錄)最快的方法是什麼?

例如記錄器l,內容如下,

導致構造信息參數開銷的是:轉化整型i值和數組entry[i]爲字符串;連接字符串的媒介。不管是否記錄信息都會發生這些事情。

假如你擔心速度,可以這樣些,

使用這種方法,假如你在調試時不輸出日誌,就不會導致參數構造的開銷。另一方面,若記錄器是需要調試的,無論記錄器是否可調試,都將導致檢測的開銷(cost of evaluating),這包括兩個地方:一個是debugEnabled,一個是debug(譯註:就是l.isDebugEnabled()和l.debug(“”)的這兩個方法的開銷)。這是無關緊要的日常開銷,因爲檢測一個記錄器的花費還不到它記錄一個日誌信息的1%時間。

在記錄器的命名方面,有什麼建議嗎?

是,有的

你可以通過位置(locality)來命名記錄器(loggers).這證明了用單個類的類名去實例化一個記錄器等同於用完整的記錄器名,這是一個直截了當地定義記錄器的方法。

這種方法有如下好處:

  • 它可以很容易的實現
  • 它可以很容易的對新的開發人員解釋
  • 它自動映射你的應用程序的模塊設計
  • 它可以被很隨意的優化
  • 自動打印日誌記錄器給出的本地日誌描述的信息

然而,這不是日誌命名的唯一方法。一個普通的替代方法是通過功能區域來命名記錄器。例如,“數據庫”(database)記錄器,“遠程方法調用”(RMI) 記錄器,“安全”(security) 記錄器,“XML”記錄器。

你可以在功能和本地子範疇(by functionality and subcategorize by locality)兩者中選擇一個命名記錄器,就像"DATABASE.com.foo.some.package.someClass"或者"DATABASE.com.foo.some.other.package.someOtherClass"。

在選擇你自己的記錄器的名稱時,你是完全自由的。Log4j包僅僅允許你按照一個層次來管理你的名稱。無論如何,定義這個層次是你的責任

注意,本地化地命名記錄器往往通過功能來命名(Note by naming loggers by locality one tends to name things by functionality),因爲在大多數的情況下,本地化和功能聯繫更緊密。

我怎樣才能用靜態模式(in a static block)的方式得到一個高質量(fully-qualified)的類名?

你可能很容易按靜態模式(in a static block,譯註:我沒有找到最佳譯法,以後再修改吧J)的方式用X.class.getName()方法獲得類X的高質量的名稱,。注意,X是類名而不是實例。X.class不會創建一個新的類X的實例

這是一個建議的用例模板:

日誌輸出可以自定義嗎?

是的。從0.7.0版本,你就可以擴展Layout類來創建你自己的日誌格式。輸出源(Appenders)也通過你自己選擇的佈局器(layout)來達到參數化

多客戶端請求的輸出可以對應不同的日誌文件嗎?

許多開發者都面臨這樣問題,面對不同的客戶端請求,在相同的類(class)中辨別除日誌輸出的類別。他們給log4j的愛好者提出了一個獨具匠心的機制輸出日誌到不同的文件。在大多數情況下,這不是一個好的方法。

使用嵌套診斷環境(NDC)來實現很簡單的。特別是,當處理一個客戶端請求時, 使用NDC.push()將獲得客戶端的特殊信息,例如主機名、ID或者任何其它區分信息。從這以後,日誌輸出將自動包括嵌套診斷環境,即使日誌被輸出到同一個文件你也能區分出不同客戶端的請求。

參考NDC和PatternLayout類獲得更多信息。NumberCruncher例子展示了怎樣用NDC從多個客戶端區分出日誌輸出信息,即使他們共享同一個日誌文件

對應用程序,例如虛擬主機web服務器(virtual hosting web-servers),NDC的解決方案是行不通的。到log4j的0.9.0版本,log4j開始支持多層次樹(multiple hierarchy trees).因此,依賴當前環境,在相同的記錄器中記錄不同目標是可能的。

什麼是ForBarAppender的配置選項?

Log4j使用JavaBean的方式來配置。

因此,在FooBarAppender類中任何一個賦值方法(setter method)對應一個配置選項。例如,RollingFileAppender類的setMaxBackupIndex(int maxBackups)方法對應maxBackupIndex選項。選項的第一個字母可以是大寫,也就是說(i.e.) MaxBackupIndex和maxBackupIndex是相同的,但是MAXBACKUPIndex和mAXBackupIndex是不同的。

佈局器選項也可以通過賦值方法(setter methods)來定義。其他的log4j組件大多數也是這樣做的。

記錄器實例好像僅僅可以被創建(譯註:這是與不能刪除對應的,就是說爲什麼記錄器只能創建,不能刪除),爲什麼沒有一個方法可以移除記錄器實例?

定義一個“removed”記錄器不是一件簡單的事情,該記錄器還要可以被使用者引用。未來的版本可能會包含一個刪除方法(remove method)在Logger類中

按照不同的等級,可以把日誌輸出定向到不同的輸出源(appender)嗎?

是的,可以這樣。從AppenderSkeleton類擴展一個輸出源(大多數的log4j輸出源都是擴展AppenderSkeleton類),設置該輸出源的入口選項(Threshold option)來過濾所有的日誌事件,這些日誌事件的入口選項(Threshold option)的值比已經設置的級別低。

例如,設置一個輸出源的入口選項值爲DEBUG,這就允許INFO, WARN, ERROR 和FATAL級別的信息可以連同DEBUG級別的信息一起記錄。這是可接受的,因爲沒有周圍的INFO, WARN, ERROR 和 FATAL的信息,DEBUG信息就沒有什麼作用

這種規則通常是使用者想要的最好封裝,因爲這是和他(她)心中已有的解決案是相反的(as opposed to her mind-projected solution,譯註:這句話感覺很拗口,原文意思好像有誤)。

參考examples/sort4.lcf查找一個入口(threshold)配置的實例

假如你必須使用精確級別匹配過濾事件,那麼你可以讓任何輸出源都繼承LevelMatchFilter類來過濾日誌事件。

我怎樣才能對同一個文件獲得多個處理進程?

你可以讓每個SocketAppender類都有一個進程日誌。接受方的套接字服務器(SocketServer)(或者簡單套接字服務器(SimpleSocketServer))可以接受所有的事件並把它們發給一個獨立的日誌文件。

假如我有許多跨越多個主機(可能跨越多個時區)的處理進程用上述方法記錄日誌到相同的文件,時間戳會發生什麼事情?

當日志事件被創建的時候,這個時間戳也被創建,也就是在debug, info, warn, error or fatal方法被調用的時候。這是不受他們(譯註:此處代表日誌記錄)到達遠程服務器的時間影響的。由於時間戳是以UTC的格式保存在事件中的,所以他們可以顯示在相同的時區,這個時區是創建這個日誌文件的服務器所處的時區。由於不同機器的時鐘是不可以同步的,所以在不同服務器上產生的事件之間,這會導致時間間隔(time interval)的衝突。

雖然這是一個有目的的行爲,但它最近變的太依賴於版本1.0.4和版本1.1b1之間的bug發現。1.0.4以前的版本可以在轉換器中產生他們自己的時間戳。在這種情況下,日誌文件裏的時間戳會按順序全部顯示,這個時間戳是當他們到達日誌服務器主機時,服務器依賴於本地時鐘產生的。

爲什麼在J2EE或者WAR應用程序中log4j不能發現我的屬性文件?

簡單的回答是:log4j的類和屬性文件沒有被包含在類裝載器(classloader)的範圍內。

詳細的答案是(並且講解這是怎麼回事):J2EE或者Servlet容器利用java的類裝載系統(class loading system)。Sun公司在Java2的版本中改變類裝載的策略,在Java2中類裝載器是按照層次的父子關係(hierarchial parent-child relationship)來設計。但一個子類裝載器(譯註:子類裝載器的意思是子-類裝載器,而不是子類-裝載器,這是兩個不同的概念,注意讀法,這是漢語的語義誤解導致的)需要發現一個類或者資源是,它第一步會把請求委託給父類裝載器(譯註:見子類裝載器的譯註)

Log4j僅僅使用默認的Class.forName()機制來裝載類,資源也被按照這樣處理。參考java.lang.ClassLoader的文檔獲得更詳細信息

因此,假如你有問題,試着自己裝載類和資源。假如你沒有發現,log4j也不會發現。:)

假如屬性文件改變,是否有方法讓log4j自動加載?

Yes. Both the DOMConfigurator and the PropertyConfigurator support automatic reloading through the configureAndWatch APIs. See the API documentation for more details.

是的。DOMConfigurator類和PropertyConfigurator類通過configureAndWatch接口支持自動加載。參考API文檔獲得更詳細信息

當我使用NTEventLogAppender類時,Windows NT事件觀察器(Windows NT Event Viewer)對丟失我的事件信息描述行爲會有什麼樣的反應?

NT事件觀察器依賴於消息資源動態鏈接庫(message resource DLLs)來正確顯示事件消息. NTEventLogAppender.dll包含了這些消息資源,但是DLL必須要拷貝到%SYSTEMROOT%/SYSTEM32目錄纔可以正確工作

當我使用NTEventLogAppender類時,爲什麼我不能映射我的記錄器名到顯示在NT事件記錄器(NT Event Log)中的記錄器

不幸的是,記錄器名是被硬編碼在消息資源DLL中的(參考前面關於NTEventLogAppender類的問題),因此沒有任何簡易的辦法覆蓋那些動態的東西… 事實上,我認爲這是不可能的,因爲你不得不爲每個應用程序修改DLL資源。無論如何,以前大多數的本地應用程序都沒有使用記錄器的專有特性…

我爲什麼要把我的log4j擴展捐贈(donate)給項目呢?

相對於GNU的公共許可證(GPL),Apache軟件許可證並沒有對你的擴展設置更多的要求。通過擴展,我們得到了完全新的代碼,用這些代碼調用log4j的類。根據你的需要,你有權力來自由地擴展log4j。注意,你不可以把你擴展過的代碼分發到太廣的人羣

我們非常注重不修改log4j的客戶端代碼,因此log4j的新版本是向後兼容以前版本的。我們是不太關心log4j內部的API(We are a lot less scrupulous with the internal log4j API, 譯註:我沒有理解這句話的意思,我認爲這句話有誤,他的原意可能是不注重log4j內部相互之間的接口調用,但對開放的外部接口不是如此)。因此,假如你設計你的擴展與版本n恰好吻合,然後log4j的版本n+1出來了,你將很可能需要修改擴展的部分來與新版本相適應。因此,你將被迫花費寶貴的時間來與新版本兼容。這就是經常提到的“愚蠢稅收”(stupid-tax)。通過捐贈代碼,並讓其成爲標準的一部分,你將節省不必要的維護工作。

假如你的擴展是有用的,最終會有人寫一個擴展來提供相同或者相似的功能。你的開發工作將是浪費的。除非你的log4j擴展是關鍵業務,否則沒有任何理由不捐贈你的代碼項目(譯註:此處的項目是指apache的log4j項目)

當捐獻代碼時,我應該緊記(keep in mind)什麼?

1.       給你捐獻的代碼寫一個測試用例

沒有什麼比在調試(也就是日誌)代碼時發現bug更刺激了。寫測試用例要花費一定的時間,但是對於一個被廣泛使用的庫是至關重要的,例如log4j。寫一個讓你受追隨者尊敬的測試用例需要花費很大的努力和很長的時間。

2.       堅持現有的縮進風格,即使你討厭這種方法。

改變現有的縮進風格會讓代碼很難理解。讓你自己辛苦,但是別人會因此而很輕鬆。Log4j遵循java語言的代碼風格(Code Conventions for the JavaTM Programming Language)

3.       努力讓代碼支持JDK1.1API

Log4j的重要的優點是它和JDK 1.1.x完全兼容的。

4.       保持代碼簡潔,小巧和快速。

這是和應用程序有關的,而和日誌無關。

5.       在相關的文件中的開頭,辨別你自己是否是捐助者。

6.       對你代碼要付責任

創作軟件和馬拉松賽跑非常相似,它需要時間和耐力

7.       我提及要堅持縮進風格了嗎?

8.       我提及要寫測試用例了嗎?

在哪可以找到最新的log4j發行版?

Log4j的項目被放置在http://jakarta.apache.org/log4j/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章