權威支援: WebSphere Application Server 日誌記錄開發人員指南

CloudSpace發表於2008-07-25
日誌訊息和跟蹤資訊在問題診斷的初始階段可以作為非常重要的節省時間元素加以利用,並且通常能夠減少重現問題來進行故障排除的需求。本文將討論 IBM® WebSphere® Application Server 中的日誌和跟蹤工具,介紹二者之間的差別,並說明如何在您的應用程式中對其加以利用。

好的程式會在自身情況不對的時候讓您知道

作為開發人員,我們瞭解的第一件事是將訊息列印到控制檯。後來,我們瞭解到了此類列印語句在除錯程式碼時的寶貴价值,特別是在找到喜歡的開發工作臺之前更是如此。獲得瞭解程式碼流和確定變數值變化的能力後,我們就能夠充分理解清楚的除錯語句在快速確定程式碼中的問題方面的價值。對每個方法進行了除錯後,我們將從中剔除列印語句,從而更容易將重點放在程式碼的下一部分內容上。一切就緒後,在知道程式碼可供正常使用後,我們很高興地刪除了最後的列印語句。

對於任何重要的程式,診斷程式碼在單元測試之外都具有很大的價值。隨後在某些情況下,可以在不用診斷程式碼輔助就能診斷問題,但使用程式碼和跟蹤語句也能極大地縮短診斷時間。日誌記錄程式碼是第一手故障診斷資訊中非常重要的部分,通常能夠減少重現問題來進行診斷的需求。IBM WebSphere Application Server 提供了非常有價值的日誌和跟蹤工具,可供在您自己的應用程式中使用。作為開發人員,您要將有效的日誌記錄和跟蹤程式碼寫入到將與 WebSphere Application Server 一起執行的應用程式,本文將說明所需瞭解的資訊。

日誌記錄和跟蹤基礎知識

日誌記錄和跟蹤之間的區別何在?

  • 日誌記錄通常用於希望在日誌檔案中記錄的重要事件。日誌記錄用於指示狀態的重要更改(例如,服務啟動或停止時)、指示警告(例如,當所寫入的磁碟空間不足時)或指示錯誤(例如,當程式碼由於預期服務不可用而無法再繼續)。日誌記錄通常是始終啟用,因此日誌記錄程式碼必須體積相當小,通常為您應該注意的重要事項。另一個重要的特徵是,日誌記錄對應用程式管理員非常有用。由於所記錄的訊息旨在供管理員使用,因此應用伺服器所記錄的訊息將轉換為伺服器程式的其餘部分所配置的語言並寫入日誌(應用程式還可以利用訊息本地化的優勢,但這通常並不是必需的)。建立日誌訊息時必須謹慎,要確保任何使用此程式碼的人都能夠容易地瞭解其含義。因此,通常新增日誌記錄語句所需的時間比新增跟蹤語句的時間更長。

  • 跟蹤通常用於記錄在除錯程式碼問題時可能有用的任何資訊。跟蹤通常用於指示呼叫了哪些方法、向方法傳入了哪些資料(或從方法返回了什麼值)以及從對程式碼邊界之外的其他方法的呼叫返回了什麼資料。跟蹤事件體積可能比較大,因此只有在診斷問題時啟用。由於跟蹤事件的內容極為詳細,而且是技術資訊,因此經常只對編寫應用程式的人有價值。開啟跟蹤的情況下,應該能夠了解在程式碼中可能出現的任何問題。如果跟蹤檢測未成功完成,則可能需要使用者遇到問題時將程式碼的除錯版本(包含更多的跟蹤檢測)傳送給他們;這可能不可行(或者不希望這樣做),通常最好通過在向終端使用者提供程式碼前謹慎處理跟蹤來加以避免。

哪些內容對日誌和跟蹤重要?

在日誌和跟蹤檔案中包含正確的內容,可幫助更快地診斷問題。日誌和跟蹤內容至少應該明確以下資訊:

  • 指示訊息生成時間的準確時間戳。
  • 作為訊息源的類名稱和方法名稱。
  • 訊息發出者的執行緒 ID。
  • 訊息反映的事件的嚴重級。
  • 標識負責發出訊息的記錄器的名稱,用於設定日誌/跟蹤級別,以控制啟用或禁用哪些訊息。
  • 明確的訊息。

哪些功能對日誌記錄和跟蹤執行時物件重要?

除了在日誌和跟蹤事件中包含正確的內容外,日誌記錄和跟蹤執行時物件還必須滿足以下要求:

  • 支援對啟用或禁用哪些訊息的足夠細粒度的控制。
  • 支援在不需要伺服器重啟的情況下控制日誌和跟蹤級別。
  • 提供自動歸檔或截斷日誌和跟蹤的方法(不用伺服器重啟),從而防止檔案過大。
  • 提供遠端監視日誌的方法。

選擇正確的日誌和跟蹤 API

最常見的日誌記錄 API 有哪些?

有多個日誌記錄 API 選項可以在 WebSphere Application Server 應用程式中使用。最常見候選選項如表 1 中所示。


表 1. 日誌記錄 API
日誌記錄 API 是否與 WebSphere Application Server 日誌整合 是否建議在 WebSphere Application Server 應用程式中使用
java.util.logging (JUL) 是(從 V6.0 起) 是(V6.0 或更高版本)
JRAS 是(僅僅適用於 V6.0 之前的版本)
Log4J
Jakarta Commons Logging (JCL)
System.out.println and System.err.println
  • java.util.logging (JUL)

    JUL 從 2002 年 J2SE 1.4 釋出之後一直是 Java SDK 的標準組成部分。從體系結構的角度而言,它與 Log4J 類似。JUL API 包含五個主要概念:記錄器、處理器、篩選器、格式設定器和日誌記錄。JUL 的主要優勢是,基於 J2SE 1.4(或更高版本)的所有執行時都將其包含在其中,提供了支援日誌記錄設定控制的靈活體系結構,而且能夠方便地進行自定義。

    JUL 是 WebSphere Application Server 中的首選日誌記錄實現,而且在 WebSphere Application Server 自己的實現中使用。JUL 的日誌記錄使用非常簡單,而且具有足夠的自定義能力,能滿足大部分日誌記錄需求。JUL 與 WebSphere Application Server 實現了很好的整合,任何對 JUL 記錄器 API 的任何請求(甚至包括來自應用程式程式碼的請求)都將由 WebSphere Application Server 日誌記錄基礎設施進行處理。對於任何將在 WebSphere Application Server 內操作的新應用程式程式碼,都強烈建議使用 JUL。

  • JRAS

    JRAS 是從 V3.5 之後隨 WebSphere Application Server 提供的公用 API。JRAS API 及其所基於的 API 是 Log4J 和 JUL 的前身。JRAS API 已在 WebSphere Application Server V6.0 棄用,應用伺服器將轉而利用 JUL API。因此,不要對任何新程式碼使用 JRAS。

  • Log4J

    Log4J 是一個 Apache 專案,旨在提供靈活而強大的日誌記錄實現。Log4J 最初在 1999 年釋出,其體系結構與 JUL 類似。JUL 具有記錄器、處理器、格式設定器和日誌記錄,而與此對應,Log4J 具有記錄器、追加器、佈局和日誌記錄事件。Log4J 的標準配置中包含很多追加器和佈局。

    Log4J 作為 Apache 的開源專案提供,但並不屬於 Java 語言標準。Log4J 的主要優勢在於,它提供與 JUL 類似的功能,而且具有大量的預先構建的追加器和佈局實現。

    雖然體系結構與 JUL 類似,但 Log4J 並未與 WebSphere Application Server 日誌記錄基礎設施整合。通常,除非迫切需要 Log4J 的追加器或佈局的高階功能,否則請不要將 Log4J 與 WebSphere Application Server 一起使用。您可能決定將 Log4J 和 WebSphere Application Server 結合使用,然後發現能夠正常工作,但您並不能獲得 JUL 所利用的整合所帶來的好處。

  • Jakarta Commons Logging (JCL)

    JCL 是旨在提供可編寫的包裝 API 的 Apache 專案。與其他日誌記錄 API 不同,JCL 在執行時就將日誌記錄呼叫委派給適合包含環境的具體日誌記錄實現。例如,在 WebSphere Application Server 中,JCL 的事件將傳送到 WebSphere Application Server 日誌和跟蹤工具。在其他環境中,將 JCL 輸出傳送到 Log4J 的做法並不常見。這裡的要點是,JCL 並不是基於標準的 API,而是讓開發人員“不必擔心”其跟蹤輸出的輸出位置的框架。JCL 在標準 API 之前就存在。

    JCL 的主要優勢是,它允許程式碼使用日誌記錄呼叫進行檢測,而且不用考慮在執行時存在哪些日誌記錄工具,或程式碼將最終在哪些執行時上執行。

    JCL 與 WebSphere Application Server 整合並打包在一起。繫結自己的 JCL JAR 副本並希望將輸出傳送到不是 IBM 提供預設項的目的地的應用程式需要特別謹慎,以避免與應用伺服器執行時中包括的 JCL 版本出現類載入衝突。這通常很難很好地完成,因此不建議這樣做。

    由於在所有 J2SE 1.4 和較高版本的 JVM 都提供 JUL,就減少了將 JCL 作為可移植日誌記錄包裝的需求。因此,不要在任何新的應用程式程式碼中使用 JCL。

  • System.out.println and System.err.println

    雖然這不是真正的日誌或跟蹤 API,但很多開發人員都喜歡使用 System.out.println 檢測其程式碼。WebSphere Application Server 將對傳遞給 System.out 和 System.err 的資料進行充實。WebSphere Application Server 不會將 System.out 和 System.err 寫到控制檯,而會:

    • 將傳遞到每個流的資料轉換為日誌事件(不精確程式)。
    • 確定事件的建立時間。
    • 確定事件發出者的執行緒 ID。
    • 將事件連同上述資訊寫入托管日誌檔案。

    不過,應用伺服器並不能使用 System.out 和 System.err 確定訊息的準確來源(類或方法),無法確定訊息的嚴重程度,而且無法提供比基本的開/關功能(伺服器範圍內)更強的功能來控制這些訊息的輸出。或許最重要的是,將大量跟蹤輸出傳送到 System.out 開銷非常大,而且將導致大量的效能問題(並需要面臨減少輸出量的壓力)。這些差異使 System.out 和 System.err 不適合大規模使用。因此,不要在應用程式程式碼中使用 System.out.println 和 System.err.println。

應該將哪個日誌記錄 API 用於 WebSphere Application Server?

正如上面所述,有各種日誌記錄可供選擇。以下是 WebSphere Application Server 服務能力團隊針對應用程式程式碼的建議:

  1. 將 JUL 用於將在 WebSphere Application Server V6.0 或更高版本上執行的新程式碼。
    由於 JUL 的普遍性及與應用伺服器日誌和跟蹤工具的緊密整合,因此 JUL 是最適合用於新 WebSphere Application Server 應用程式程式碼的 API。只有在應用程式所需的所有執行時中都不提供 JUL 時才應考慮其他日誌記錄 API。

  2. 如果(且僅在此情況下)需要支援不能正確支援 JUL 的環境,則請對新程式碼繼續使用現有日誌記錄框架。
    通常,如果繼續部署到 J2SE 1.4 之前的環境,則您已經具有其他應用程式和已經建立的日誌記錄 API。您有兩個選擇,一個是繼續使用現有日誌記錄 API,另一個是尋找其他 API。既然 JUL 中有日誌記錄標準,則投資新的日誌記錄基礎設施就不那麼急迫了,因為任何投資都將只是暫時性的。

  3. 不要出於日誌記錄 API 純淨度的原因替換數千行經過測試的日誌記錄和跟蹤檢測的程式碼行。
    對於遷移到支援 JUL 的應用伺服器的情況,可能很想對現有日誌和跟蹤檢測進行重新設計。由於要在一個日誌記錄 API 進行標準化而重寫數千行跟蹤程式碼(而且必須進行重新測試),這樣的做法通常並不能很好地利用開發資源。在可能的情況下,請考慮將現有的日誌記錄 API 過渡到採用 JUL 編寫程式碼。如果您無法通過 JUL 整合日誌事件,則可以使用 Log Analyzer 之類的工具在檢視時將日誌與應用伺服器日誌合併。

使用 JUL 檢測程式碼

  • 記錄器在需要日誌記錄和跟蹤的程式碼中使用。記錄器通常基於所在的 Java 類或包分配名稱(例如,com.acme.birdtrap.PurchaseOrder)。記錄器由獨立日誌管理器儲存採用層次結構方式儲存,允許記錄器從其父級記錄器繼承特徵。每個記錄器的名稱確定記錄器所屬的層次結構,每個記錄器的父項具有與子項相同的名稱,不過減少了子項名稱中最後一個英文句點之後的部分(例如,com.acme 是 com.acme.birdtrap 的父級記錄器,而後者是 com.acme.birdtrap.PurchaseOrder 的父級記錄器)。每個記錄器都具有對應的級別,這是一個可設定的閾值,控制必須記錄的事件(稱為日誌記錄)的嚴重級別,以免被丟棄。如果不明確設定記錄器級別,則該記錄器將從其父項繼承級別。記錄器可以具有篩選器,篩選器是記錄器用於根據日誌記錄的內容決定是否丟棄日誌記錄請求的類。

  • 處理器是記錄器用於將日誌記錄寫入輸出裝置的類。處理器可以自行設定日誌記錄的格式,或使用格式設定器來將日誌記錄轉換為字串。處理器還具有級別設定,級別的用途與記錄器中的級別相同。處理器也可以具有篩選器,其用途與記錄器的篩選器相同。處理器通常將日誌記錄的格式化結果寫入日誌檔案,但可以設計為輸出到記憶體內的緩衝區、套接字、即時訊息傳遞目的地或任何其他認為有用的位置。JUL 以標準形式提供,包含一系列處理器和格式設定器來滿足您的基本需求。



    圖 1. JUL 日誌請求處理中的關鍵元件
    圖 1. JUL 日誌請求處理中的關鍵元件

清單 1 包含演示使用 JUL 時的編碼最佳實踐的程式碼示例。將在示例後對這些最佳實踐進行說明。


清單 1. 演示 JUL 使用的示例程式碼
                
1  package com.acme;

2  import java.util.logging.Level;
3  import java.util.logging.Logger;

4  public class JULExample {

5  	// define a Logger for use by this class
6  	static String className = JULExample.class.getName();
7  	public static Logger logger = Logger.getLogger(className);

8  	public String lookupContactPhoneNumber(String contactName) {
9  		String methodName = "lookupContactPhoneNumber";
10  		logger.entering(className, methodName);

11  		// connect to contact repository
12  		ContactRepository cr = ContactRepository.connect();

13  		if (cr == null) {
14  			// LOGGING
15  			logger.logp(Level.WARNING, className, methodName,
16  						"Contact repository not available");
17  			return "";
18  		}

19  		// lookup the contact phone number
20  		String contactPhoneNumber = cr.getContactPhoneNumber(contactName);

21  		// TRACE
22  		if (logger.isLoggable(Level.FINEST)) {
23  			// use isLoggable so we don't concatenate strings
24  			// below unless trace is enabled
25  			String traceString = "name    " + contactName + "number: "
26  					+ contactPhoneNumber;

27  			logger.logp(Level.FINEST, className, methodName,       
28             	            traceString);
29		}

30		logger.exiting(className, methodName, contactPhoneNumber);
31		return contactPhoneNumber;
32	}

33	public String getSomeString() {
34		return "SomeString";
35	}

36  }

使用 JUL API 將日誌記錄和跟蹤程式碼新增到應用程式,將極大地改進您應用程式的服務能力。以下是一些建議的原則,可幫助您獲得極佳的結果:

  1. 儲存記錄器例項,而不要重複呼叫 Logger.getLogger。
    在清單 1 中,Logger.getLogger() 僅僅呼叫了一次,以獲得類的記錄器。記錄器是執行緒安全的,因此可以安全地將其儲存在靜態變數中,以供任何類例項使用。這樣您就能夠在類中的任何位置使用記錄器,而且不必再次呼叫 Logger.getLogger(),從而提高您程式碼的效能。

  2. 使用完全限定類名稱作為記錄器名稱。
    記錄器名稱在需要更改記錄器級別時用於標識記錄器(例如,在管理控制檯中)。通過為記錄器分配完全限定類名稱,可方便地指定需要調整哪個記錄器的級別來從使用者獲得所需的跟蹤。

  3. 確保日誌和跟蹤條目易於連結回程式碼。
    通過在日誌和跟蹤條目中指定類名稱和方法名稱,將能夠立即指出事件在程式碼中的生成位置。

    您還需要使用 entering() 方法呼叫來標記方法的開始位置,但要記住 entering() 方法呼叫將生成 Level.FINER 事件,而在 WebSphere Application Server 中預設禁止 Level.FINER 事件。

    有些 JUL 實現將嘗試在未指定這些引數的情況下計算哪個方法和類生成了事件,但這可能會產生不希望的效能影響——在 JIT 刪除了堆疊框架的情況下甚至可能會不正確。在 WebSphere Application Server 中,不會嘗試計算代表呼叫方的方法和類名稱(這項功能是可選的,而且被視為非常低效的功能)。在能夠提供自己的類和方法名稱的情況下,使用 JUL 記錄器方法更好。

    表 2. 允許指定類和方法名稱的記錄器方法

    記錄器方法
    entering(String sourceClass, String sourceMethod)
    entering(String sourceClass, String sourceMethod, Object param1)
    entering(String sourceClass, String sourceMethod, Object[] params)
    exiting(String sourceClass, String sourceMethod)
    exiting(String sourceClass, String sourceMethod, Object result)
    Logp(Level level, String sourceClass, String sourceMethod, String msg)
    Logp(Level level, String sourceClass, String sourceMethod, String msg, Object param1)
    logp(Level level, String sourceClass, String sourceMethod, String msg, Object[] params)
    logp(Level level, String sourceClass, String sourceMethod, String msg, Throwable thrown)
    throwing(String sourceClass, String sourceMethod, Throwable thrown)


  4. 遵循應用伺服器的日誌和跟蹤級別約定。
    WebSphere Application Server 預設配置在預設情況下支援 Level.INFO 和更高的 JUL 級別。應用伺服器將從 Level.CONFIG 到 Level.SEVERE 的所有 JUL 級別作為日誌事件級別對待,旨在供管理員使用。

    表 3. 日誌記錄級別

    日誌記錄級別
    Level.SEVERE
    Level.WARNING
    Level.INFO
    Level.CONFIG


    應用伺服器將從 Level.FINE 到 Level.FINEST 的級別作為跟蹤級別對待(這些級別用於旨在幫助程式碼的作者進行除錯的事件)。

    表 4. 跟蹤級別

    跟蹤級別
    Level.FINE
    Level.FINER
    Level.FINEST


    通過在程式碼中遵循這些約定,就將能夠在預設情況下記錄正確的事件集。

  5. 不要在程式碼中設定日誌記錄級別。每個 JUL 記錄器都具有關聯的級別。此級別控制忽略哪些事件和記錄哪些事件。記錄器級別在應用伺服器啟動時使用應用伺服器配置檔案中儲存的資料設定。管理員可以利用指令碼(使用 wsadmin)或以程式設計方式(使用 JMX Mbean 客戶端)通過管理控制檯更改記錄器級別。應用伺服器控制記錄器級別。

    通過直接呼叫 logger setLevel() 方法對記錄器級別設定的更改並不更改應用伺服器的中央日誌記錄配置,因此,通過 setLevel() 設定的記錄器級別將不會反映在管理控制檯中,而且可能在日誌記錄基礎設施基於管理員更改應用新日誌記錄設定時被忽略。所以請避免使用此方法:setLevel(Level newLevel)。更改伺服器的中央記錄器配置時,會將這些更改推送到所有受影響的記錄器。這意味著,對記錄器 getLevel() 方法的呼叫將按照預期的方式工作。

  6. 請僅將記錄器 entering() 和 exiting() 方法用於重要方法。
    JUL 提供了建議在方法的開始和結束時使用的 Logger.entering() 和 Logger.exiting() 方法。將這些跟蹤點新增到程式碼中的每個方法所涉及工作量將非常大,而且並不會提高應用程式的服務能力。通常,對於特定方法的內部不重要的情況(如簡單的 getter 或 setter 方法),請避免使用 entering() 和 exiting() 方法。

  7. 最好將應用程式日誌和跟蹤寫入到應用伺服器日誌。
    雖然 JUL 提供了只需最少程式碼或配置來新增新日誌檔案的能力(處理器),但通常這樣做沒有什麼優勢。在除錯時讓日誌和跟蹤資訊與應用伺服器日誌和跟蹤交織在一起的做法很好。對於不能將日誌寫入相同的日誌檔案的情況,或者涉及多個系統時,Log Analyzer(作為 IBM Support Assistant 的外掛提供)之類的工具可以幫助您合併日誌檔案。

  8. 在合適的情況使用 Logger.isLoggable()。
    因為 WebSphere Application Server 預設情況下禁用跟蹤,因此務必儘可能高效地禁用跟蹤語句。為了避免計算跟蹤方法引數的效能成本,JUL 提供了 Logger.isLoggable() 方法,此方法將進行檢查,確定記錄器的設定是否等於或高於您所指定的級別。請記住,記錄器將執行相同的檢查,因此,在計算日誌和跟蹤引數將帶來一定效能成本的情況下,並沒有必要將日誌或跟蹤語句與 Logger.isLoggable() 檢查包裝在一起。

與 WebSphere Application Server 的 JUL 整合

從 V6.0 開始,所有的 WebSphere Application Server 版本都可以利用 JUL。以下是通過使用 JUL 來檢測程式碼將獲得的一些額外好處:

  • 內建日誌和跟蹤檔案
    WebSphere Application Server 將設定日誌和跟蹤事件的格式,並將其寫入到相應的應用伺服器日誌檔案中(在 Windows®、Linux®、HP/UX、Solaris™、AIX® 和 i5/OS 作業系統上,所指的是 SystemOut.log、trace.log 和 activity.log 檔案;而在 System z™ 上,所指的是平臺日誌記錄工具)。應用伺服器將為您管理這些日誌檔案,並提供易於配置的存檔策略。您可以使用知道如何處理應用伺服器日誌檔案的工具(如 IBM Rational® Application Developer 或 IBM Support Assistant 中的 Log Analyzer)或各種 IBM Tivoli® 工具來使用日誌內容。

  • 用於應用程式的內建記錄器級別管理
    WebSphere Application Server 提供了為任何指定 JUL 記錄器設定級別的方法,包括您在自己的應用程式中建立的記錄器。JUL 記錄器級別可以使用管理控制檯、wsadmin 或 JMX 配置設定。



    圖 2. WebSphere Application Server Change Log Detail Levels 皮膚顯示您的 JUL 記錄器
    圖 2. WebSphere Application Server Change Log Detail Levels 皮膚顯示您的 JUL 記錄器

  • 事件和應用伺服器事件間的固有相關性
    應用伺服器日誌和跟蹤事件將與您自己的日誌和跟蹤事件交織在一起,因此消除了將這些獨立事件集相關的需求。這樣可以在使用日誌和跟蹤診斷問題時節省時間。對於不希望存在這種交織的情況,可以選擇建立自己的日誌檔案(以後的文章中將對此進行更多的討論)。

  • WebSphere Application Server 的 JUL 擴充套件
    WebSphere Application Server 提供了(通過 Logger.properties 檔案)將一系列有用屬性與記錄器關聯的方法。通過這些屬性,您可以將記錄器新增到組,或通過將記錄器與本地化資源包使用來提高效能。

  • 企業級別配置
    WebSphere Application Server 基於伺服器配置設定初始化日誌記錄環境,而不會使用 JRE/lib 目錄中的 JUL logging.properties 設定(後者是 JUL 預設方式)。這樣的好處在於,日誌設定與您的伺服器關聯。這意味著將伺服器新增到叢集時,所有伺服器上的日誌記錄行為將保持一致,將僅僅依賴於與您 J2EE™ 環境關聯的設定。

結束語

日誌記錄和跟蹤是應用程式程式碼中重要的組成部分。通過遵循一些最佳實踐,您可以確保服務能力程式碼與所在的執行時很好地整合,提供在現場除錯程式碼的必要資訊,而且不會對程式碼的效能造成大的影響。

本專欄後面的部分將討論一些更為高階的日誌和跟蹤主題,如:

  • 如果存在使用應用伺服器中的 Log4J 或 JCL 的程式碼,該如何處理?
  • 如何在使用 JUL 時新增自己的日誌檔案?
  • 如何將本地化資源包與 JUL 結合使用?

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-410071/,如需轉載,請註明出處,否則將追究法律責任。

相關文章