web server apache tomcat11-22-logging 日誌

前言

整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本爲 v11 最新的版本。

開源項目

從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。

系列文章

web server apache tomcat11-01-官方文檔入門介紹

web server apache tomcat11-02-setup 啓動

web server apache tomcat11-03-deploy 如何部署

web server apache tomcat11-04-manager 如何管理?

web server apache tomcat11-06-Host Manager App -- Text Interface

web server apache tomcat11-07-Realm Configuration

web server apache tomcat11-08-JNDI Resources

web server apache tomcat11-09-JNDI Datasource

web server apache tomcat11-10-Class Loader

web server apache tomcat11-11-Jasper 2 JSP Engine

web server apache tomcat11-12-SSL/TLS Configuration

web server apache tomcat11-13-SSI

web server apache tomcat11-14-CGI

...

簡介

Apache Tomcat 的內部日誌記錄使用了 JULI,這是 Apache Commons Logging 的打包重命名分支,被硬編碼爲使用 java.util.logging 框架。這確保了 Tomcat 的內部日誌記錄和任何 Web 應用程序日誌記錄保持獨立,即使一個 Web 應用程序使用了 Apache Commons Logging。

要配置 Tomcat 使用替代的日誌記錄框架進行內部日誌記錄,請按照替代日誌記錄框架提供的指令,重定向使用 java.util.logging 的應用程序的日誌記錄。請注意,替代的日誌記錄框架需要能夠在存在不同類加載器中具有相同名稱的不同記錄器的環境中工作。

在 Apache Tomcat 上運行的 Web 應用程序可以:

  • 使用任何其選擇的日誌記錄框架。
  • 使用系統日誌記錄 API,java.util.logging。
  • 使用由 Java Servlets 規範提供的日誌記錄 API,jakarta.servlet.ServletContext.log(...)

不同 Web 應用程序使用的日誌記錄框架是獨立的。有關更多詳情,請參閱類加載。唯一的例外是 java.util.logging。如果您的日誌記錄庫直接或間接地使用了它,那麼它的某些元素將在 Web 應用程序之間共享,因爲它是由系統類加載器加載的。

Java 日誌記錄 API — java.util.logging

Apache Tomcat 具有 java.util.logging API 的幾個關鍵元素的自己的實現。這個實現被稱爲 JULI。其中的關鍵組件是一個自定義的 LogManager 實現,它瞭解正在 Tomcat 上運行的不同 Web 應用程序(及其不同的類加載器)。它支持每個應用程序私有的日誌記錄配置。它還在 Web 應用程序從內存中卸載時受到 Tomcat 的通知,以便清除對其類的引用,防止內存泄漏。

當啓動 Java 時,通過提供特定的系統屬性來啓用此 java.util.logging 實現。Apache Tomcat 的啓動腳本會爲您執行此操作,但如果您使用不同的工具來運行 Tomcat(如 jsvc,或在 IDE 中運行 Tomcat),則應自行處理它們。

有關 java.util.logging 的更多詳細信息可在 JDK 的文檔和其 java.util.logging 包的 Javadoc 頁面中找到。

Servlets 日誌記錄 API

對 jakarta.servlet.ServletContext.log(...) 的調用來寫日誌消息是由內部的 Tomcat 日誌記錄處理的。這樣的消息被記錄到名爲

org.apache.catalina.core.ContainerBase.[${engine}].[${host}].[${context}]

的類別中。此日誌記錄根據 Tomcat 日誌記錄配置執行。您無法在 Web 應用程序中覆蓋它。

Servlets 日誌記錄 API 早於現在由 Java 提供的 java.util.logging API。因此,它並不提供太多選項。例如,您無法控制日誌級別。不過,可以注意到,在 Apache Tomcat 實現中,對 ServletContext.log(String) 或 GenericServlet.log(String) 的調用是以 INFO 級別記錄的。對 ServletContext.log(String, Throwable) 或 GenericServlet.log(String, Throwable) 的調用是以 SEVERE 級別記錄的。

控制檯

在 Unix 上運行 Tomcat 時,控制檯輸出通常會重定向到名爲 catalina.out 的文件中。該名稱可使用環境變量進行配置。(參見啓動腳本)。所有寫入到 System.err/out 的內容都將被捕獲到該文件中。這可能包括:

  • 由 java.lang.ThreadGroup.uncaughtException(...) 打印的未捕獲異常
  • 如果通過系統信號請求了線程轉儲,則線程轉儲

在 Windows 上作爲服務運行時,控制檯輸出也會被捕獲和重定向,但文件名不同。

Apache Tomcat 中的默認日誌記錄配置將相同的

消息寫入控制檯和日誌文件。這在開發時使用 Tomcat 時非常方便,但在生產環境中通常是不需要的。

仍在使用 System.out 或 System.err 的舊應用程序可以通過在 Context 上設置 swallowOutput 屬性來欺騙。如果將屬性設置爲 true,則在請求處理過程中對 System.out/err 的調用將被攔截,並將其輸出通過 jakarta.servlet.ServletContext.log(...) 調用饋送到日誌子系統中。
請注意,swallowOutput 功能實際上是一個技巧,它有其侷限性。它僅適用於對 System.out/err 的直接調用,並且僅在請求處理週期中起作用。它可能無法攔截由應用程序創建的其他線程中的日誌記錄框架。它不能用於攔截那些自己寫入系統流的日誌記錄框架,因爲它們早在重定向發生之前就開始,並且可能直接獲得對流的引用。

訪問日誌記錄

訪問日誌記錄是一個相關但不同的功能,它作爲一個閥門實現。它使用自包含的邏輯來寫入其日誌文件。訪問日誌記錄的基本要求是處理大量連續數據而不增加太多開銷,因此它僅使用 Apache Commons Logging 用於自身的調試消息。這種實現方法避免了額外的開銷和潛在的複雜配置。有關其配置的更多詳細信息,請參閱閥門文檔,其中包括各種報告格式。

使用 java.util.logging(默認)

JDK 提供的 java.util.logging 的默認實現過於受限,以至於無法使用。關鍵限制是無法實現每個 Web 應用程序的日誌記錄,因爲配置是基於 VM 的。因此,在默認配置下,Tomcat 將替換默認的 LogManager 實現爲一個容器友好型的實現,稱爲 JULI,它解決了這些缺陷。

JULI 支持與標準 JDK java.util.logging 相同的配置機制,使用編程方法或屬性文件。主要區別在於可以設置每個類加載器屬性文件(這樣就可以輕鬆地重新部署友好的 Web 應用程序配置),並且屬性文件支持擴展結構,允許更自由地定義處理程序並將其分配給記錄器。

JULI 默認啓用,並支持每個類加載器配置,除了常規的全局 java.util.logging 配置之外。這意味着日誌記錄可以在以下層次進行配置:

  • 全局配置。通常在 ${catalina.base}/conf/logging.properties 文件中完成。該文件由 java.util.logging.config.file 系統屬性指定,該屬性由啓動腳本設置。如果該文件不可讀或未配置,則默認使用 JRE 中的 ${java.home}/lib/logging.properties 文件。
  • 在 Web 應用程序中。該文件將是 WEB-INF/classes/logging.properties

JRE 中的默認 logging.properties 指定了一個 ConsoleHandler,將日誌路由到 System.err。Apache Tomcat 中默認的 conf/logging.properties 還添加了幾個 AsyncFileHandler,用於寫入文件。

處理程序的日誌級別閾值默認爲 INFO,可以使用 SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST 或 ALL 進行設置。您還可以針對特定的包來收集日誌,並指定一個級別。

要爲 Tomcat 的部分內部啓用調試日誌記錄,應同時配置適當的記錄器和適當的處理程序,以使用 FINEST 或 ALL 級別。例如:

org.apache.catalina.session.level=ALL
java.util.logging.ConsoleHandler.level=ALL

在啓用調試日誌記錄時,建議將其限制在可能的最窄範圍內,因爲調試日誌記錄可能會產生大量信息。

JULI 使用的配置與純 java.util.logging 支持的配置

相同,但使用了一些擴展,以便更好地靈活地配置記錄器和處理程序。主要的區別包括:

  • 可以向處理程序名稱添加前綴,以便可以實例化單個類的多個處理程序。前綴是一個以數字開頭、以 '.' 結尾的字符串。例如,22foobar. 是一個有效的前綴。
  • 對於包含 ${systemPropertyName} 的屬性值,將執行系統屬性替換。
  • 如果使用實現了 org.apache.juli.WebappProperties 接口的類加載器(Tomcat 的 Web 應用程序類加載器會這樣做),則還會對 ${classloader.webappName}、${classloader.hostName} 和 ${classloader.serviceName} 進行屬性替換,分別替換爲 Web 應用程序名稱、主機名和服務名稱。
  • 默認情況下,如果日誌記錄器具有關聯處理程序,則日誌記錄器將不委託給其父級。可以使用 loggerName.useParentHandlers 屬性更改每個記錄器的此行爲,該屬性接受布爾值。
  • 根記錄器可以使用 .handlers 屬性定義其處理程序集。
  • 默認情況下,日誌文件將在文件系統上保留 90 天。可以使用 handlerName.maxDays 屬性爲每個處理程序更改此設置。如果屬性的指定值 ≤0,則日誌文件將永遠保留在文件系統上,否則它們將保留指定的最大天數。
  • 還有一些其他的實現類,可以與 Java 提供的實現類一起使用。值得注意的是 org.apache.juli.FileHandler 和 org.apache.juli.AsyncFileHandler。

org.apache.juli.FileHandler 支持日誌的緩衝。默認情況下,不啓用緩衝。要配置它,請使用處理程序的 bufferSize 屬性。值爲 0 使用系統默認緩衝(通常將使用 8K 緩衝)。值 <0 強制在每次日誌寫入時刷新寫入器。值 >0 使用具有定義值的 BufferedOutputStream,但請注意還會應用系統默認緩衝。

org.apache.juli.AsyncFileHandler 是 FileHandler 的子類,它將日誌消息排隊並異步寫入日誌文件。可以通過設置一些系統屬性來配置其附加行爲。

示例 logging.properties 文件,放置在 $CATALINA_BASE/conf 中:

handlers = 1catalina.org.apache.juli.FileHandler, \
           2localhost.org.apache.juli.FileHandler, \
           3manager.org.apache.juli.FileHandler, \
           java.util.logging.ConsoleHandler

.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

1catalina.org.apache.juli.FileHandler.level = FINE
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.
1catalina.org.apache.juli.FileHandler.maxDays = 90
1catalina.org.apache.juli.FileHandler.encoding = UTF-8

2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.prefix = localhost.
2localhost.org.apache.juli.FileHandler.maxDays = 90
2localhost.org.apache.juli.FileHandler.encoding = UTF-8

3manager.org.apache.juli.FileHandler.level = FINE
3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
3manager.org.apache.juli.FileHandler.prefix = manager.
3manager.org.apache.juli.FileHandler.bufferSize = 16384
3manager.org.apache.juli.FileHandler.maxDays = 90
3manager.org.apache.juli.FileHandler.encoding = UTF-8

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.OneLineFormatter
java.util.logging.ConsoleHandler.encoding = UTF-8

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = \
   2localhost.org.apache.juli.FileHandler

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = \
   3manager.org.apache.juli.FileHandler

# For example, set the org.apache.catalina.util.LifecycleBase logger to log
# each component that extends LifecycleBase changing state:
#org.apache.catalina.util.LifecycleBase.level = FINE

Example logging.properties for the servlet-examples web application to be placed in WEB-INF/classes inside the web application:

handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

org.apache.juli.FileHandler.level = FINE
org.apache.juli.FileHandler.directory = ${catalina.base}/logs
org.apache.juli.FileHandler.prefix = ${classloader.webappName}.

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.OneLineFormatter

文檔參考

請查閱以下資源獲取更多信息:

Apache Tomcat 的 org.apache.juli 包的 Javadoc。

Oracle Java 11 的 java.util.logging 包的 Javadoc。

生產使用考慮事項

您可能需要注意以下事項:

考慮從配置中移除 ConsoleHandler。默認情況下(通過 .handlers 設置),日誌會同時發送到 FileHandler 和 ConsoleHandler。後者的輸出通常會被捕獲到一個文件中,比如 catalina.out。因此,您最終會得到相同消息的兩份拷貝。
考慮移除那些您不使用的應用程序的 FileHandlers。例如,host-manager 的一個。
處理程序默認使用系統默認編碼來寫入日誌文件。可以使用 encoding 屬性進行配置。請參閱 Javadoc 獲取詳細信息。
考慮配置訪問日誌。

參考資料

https://tomcat.apache.org/tomcat-11.0-doc/monitoring.html

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