Tomcat 中的記錄

目錄

簡介

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 Servlet 規格提供的記錄 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.util.logging 實作是透過在啟動 Java 時提供某些系統屬性來啟用的。Apache Tomcat 啟動指令碼會為您執行此動作,但如果您使用不同的工具來執行 Tomcat(例如 jsvc,或從 IDE 內部執行 Tomcat),您應該自行處理它們。

有關 java.util.logging 的更多詳細資訊,可以在 JDK 的文件和 java.util.logging 套件的 Javadoc 頁面上找到。

有關 Tomcat JULI 的更多詳細資訊,請參閱以下內容。

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.outSystem.err 的舊應用程式可以透過在 Context 上設定 swallowOutput 屬性來欺騙。如果屬性設定為 true,在要求處理期間對 System.out/err 的呼叫會被攔截,其輸出會使用 jakarta.servlet.ServletContext.log(...) 呼叫提供給記錄子系統。
請注意swallowOutput 功能實際上是一種技巧,且有其限制。它僅適用於對 System.out/err 的直接呼叫,且僅在要求處理週期中。它可能無法在應用程式可能建立的其他執行緒中執行。它無法用於攔截記錄架構,因為這些架構本身會寫入系統串流,因為它們會在重新導向發生之前啟動並可能取得串流的直接參考。

存取記錄

存取記錄是一種相關但不同的功能,它實作為 Valve。它使用獨立的邏輯來寫入其記錄檔。存取記錄的基本要求是處理大量持續資料串流且負擔低,因此它只使用 Apache Commons Logging 來記錄其自己的偵錯訊息。此實作方法可避免額外的負擔和潛在的複雜設定。請參閱 Valve 文件,以取得有關其設定的更多詳細資訊,包括各種報告格式。

使用 java.util.logging (預設)

JDK 中提供的 java.util.logging 的預設實作太受限,無法發揮作用。主要的限制是無法針對每個 Web 應用程式進行記錄,因為組態是針對每個 VM。因此,在預設組態中,Tomcat 會以稱為 JULI 的容器友善實作取代預設的 LogManager 實作,以解決這些缺點。

JULI 支援與標準 JDK java.util.logging 相同的組態機制,採用程式設計方法或屬性檔案。主要的差異是,可以設定每個類別載入器的屬性檔案(這可輕鬆重新部署友善的 Webapp 組態),而屬性檔案支援擴充結構,可更自由地定義處理常式並將它們指定給記錄器。

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 指定將記錄路由到 System.err 的 ConsoleHandler。Apache Tomcat 中的預設 conf/logging.properties 也新增了幾個會寫入檔案的 AsyncFileHandler

處理常式的記錄層級閾值預設為 INFO,可以使用 SEVEREWARNINGINFOCONFIGFINEFINERFINESTALL 設定。你也可以鎖定特定套件來收集記錄,並指定層級。

若要針對 Tomcat 內部的一部分啟用偵錯記錄,你應該將適當的記錄器和適當的處理常式組態為使用 FINESTALL 層級。例如

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.FileHandlerorg.apache.juli.AsyncFileHandler

org.apache.juli.FileHandler 支援日誌的緩衝。預設情況下未啟用緩衝。若要設定,請使用處理程序的 bufferSize 屬性。0 的值使用系統預設緩衝(通常會使用 8K 緩衝)。<0 的值會在每次寫入日誌時強制寫入器更新。>0 的值使用具有定義值的 BufferedOutputStream,但請注意系統預設緩衝也會套用。

org.apache.juli.AsyncFileHandlerFileHandler 的子類別,它會將日誌訊息排隊,並非同步地將其寫入日誌檔案。可以透過設定一些 系統屬性 來設定其額外行為。

範例 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

範例 logging.properties 適用於 servlet-examples 網路應用程式,要放置在網路應用程式內的 WEB-INF/classes

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

文件參考

請參閱下列資源以取得更多資訊

生產環境使用考量

您可能想要注意以下事項

  • 考慮從設定中移除 ConsoleHandler。預設情況下(感謝 .handlers 設定),記錄會同時傳送到 FileHandlerConsoleHandler。後者的輸出通常會擷取到檔案中,例如 catalina.out。因此,您最終會得到兩份相同的訊息副本。
  • 考慮移除您不使用的應用程式的 FileHandler。例如,host-managerFileHandler
  • 處理程序預設使用系統預設編碼來寫入日誌檔案。可以使用 encoding 屬性來設定。請參閱 Javadoc 以取得詳細資訊。
  • 考慮設定 存取日誌