空間站

          北極心空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks
          log4j的FAQ


          Frequently Asked Questions about log4j
                                                  ---------------------------轉載
          譯者聲明:
          1.       這是根據log4j(jakarta-log4j-1.2.8)的開發包自帶文檔的FAQ翻譯的
          2.       譯者盡力保持原文格式,以便于讀者查找原文
          3.       粉紅色的標題代表原文只有標題,而沒有相應的內容
          4.       對一些關鍵詞都帶有原文單詞,便于閱讀
          5.       原文中比較生僻的單詞,譯者都是參考金山詞霸,對找不到的組合詞都是保持原文。
          6.       對比較拗口的說法,譯者盡量采用意譯的方法,同時保持原文。
          ·         什么是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-effort和fail-stop的日志系統
          提到fail-stop,我們意思是log4j運行在有導致系統崩潰的潛在錯誤的運行狀態,它不會拋出意料之外的異常。假如由于某些原因,導致log4j拋出一個未被捕捉的異常,請發email到log4j-user@jakarta.apache.org郵件列表
          還有,當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.)
          Log4j是fail-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"的轉換格式
          176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.225 [main] INFO examples.SortAlgo - Entered the sort method.262 [main] DEBUG SortAlgo.OUTER i=1 - Outer loop.276 [main] DEBUG SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0290 [main] DEBUG SortAlgo.OUTER i=0 - Outer loop.304 [main] INFO SortAlgo.DUMP - Dump of interger array:317 [main] INFO SortAlgo.DUMP - Element [0] = 0331 [main] INFO SortAlgo.DUMP - Element [1] = 1343 [main] INFO examples.Sort - The next log statement should be an error message.346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.        at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)        at org.log4j.examples.Sort.main(Sort.java:64)467 [main] INFO examples.Sort - Exiting main method.第一個字段是從程序開始運行到該行日志輸出的毫秒數。第二個字段是輸出日志的線程。第三個是日志描述的級別。第四個字段是發出日志請求的記錄器(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,內容如下,
           l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));導致構造信息參數開銷的是:轉化整型i值和數組entry[i]為字符串;連接字符串的媒介。不管是否記錄信息都會發生這些事情。
          假如你擔心速度,可以這樣些,
             if(l.isDebugEnabled()) {     l.debug("Entry number: " + i + " is " + String.valueOf(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的實例
          這是一個建議的用例模板:
          package a.b.c; public class Foo { static Logger logger = Logger.getLogger(Foo.class); ... other code }日志輸出可以自定義嗎?
          是的。從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.1的API
          Log4j的重要的優點是它和JDK 1.1.x完全兼容的。
          4.       保持代碼簡潔,小巧和快速。
          這是和應用程序有關的,而和日志無關。
          5.       在相關的文件中的開頭,辨別你自己是否是捐助者。
          6.       對你代碼要付責任
          創作軟件和馬拉松賽跑非常相似,它需要時間和耐力
          7.       我提及要堅持縮進風格了嗎?
          8.       我提及要寫測試用例了嗎?
          在哪可以找到最新的log4j發行版?
          Log4j的項目被放置在http://jakarta.apache.org/log4j/



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1561604

          posted on 2007-10-09 08:46 蘆葦 閱讀(776) 評論(0)  編輯  收藏 所屬分類: JAVA
          主站蜘蛛池模板: 米脂县| 德化县| 盐池县| 福安市| 潼关县| 丹阳市| 承德市| 靖江市| 英德市| 阜平县| 呼图壁县| 郯城县| 密云县| 溧阳市| 兴海县| 大田县| 南和县| 汨罗市| 建瓯市| 手机| 肇源县| 西峡县| 电白县| 二连浩特市| 左云县| 苍梧县| 红桥区| 清徐县| 大余县| 鲁甸县| 内丘县| 玉环县| 碌曲县| 龙门县| 郓城县| 临海市| 青阳县| 西贡区| 察雅县| 曲周县| 双牌县|