在第二代執行階段 (Java 11 以上版本) 中,記錄的某些方面與第一代執行階段 (Java 8) 不同。與第一代執行階段不同,在第二代執行階段中,應用程式記錄並未在「記錄檔探索工具」中依要求記錄分組。此外,在第二代執行階段中,App Engine 會將與要求相關聯的每個應用程式記錄,以單獨的記錄項目寫入 Cloud Logging。
本指南說明如何實作與第一代執行階段應用程式相同的記錄方法,並在將應用程式遷移至 Java 11 以上版本時,取得幾乎相同的篩選和記錄相關聯結果。
主要差異
下表說明第一代與第二代執行階段之間的記錄差異:
第一代執行階段 (Java 8) | 第二代執行階段 (Java 11 以上版本) | |
---|---|---|
要求和應用程式記錄 (也稱為應用程式記錄) | App Engine 會將所有應用程式記錄嵌入要求記錄中。 | App Engine 不會在要求記錄中嵌入應用程式記錄。 |
stdout 和 stderr |
App Engine 會將寫入 stdout 和 stderr 的記錄嵌入要求記錄中。 |
App Engine 不會將寫入 stdout 和 stderr 的記錄嵌入。 |
App Engine 平台記錄檔 | App Engine 不會發出內部平台記錄。 | App Engine 會在執行個體啟動或關閉期間,以記錄名稱 /var/log/google_init.log 發出內部平台記錄。 |
Cloud Logging API 配額 | 每個要求都對應至一個 Cloud Logging 寫入。 | 與要求相關聯的每個應用程式記錄項目都會對應到一個 Cloud Logging 寫入作業。Cloud Logging API 用量在第二代執行階段增加。 |
要求記錄和應用程式記錄
第一代與第二代執行階段的記錄行為有以下差異:
在第一代執行階段中,App Engine 會將應用程式記錄嵌入要求記錄的
protoPayload.line
欄位中。您可以在「Logs Explorer」中展開要求,查看應用程式記錄。下圖顯示第一代執行階段中關聯的請求和應用程式記錄:
在第二代執行階段中,要求記錄檔不包含應用程式記錄項目,因為要求記錄檔中沒有
protoPayload.line
欄位。相反地,App Engine 會將每個應用程式記錄記錄為個別項目。記錄名稱取決於記錄設定。var/log/app
包含使用標準記錄架構 (例如java.util.logging
或 Simple Logging Facade for Java (SLF4J)) 產生的記錄。stderr
和stdout
記錄檔包含使用System.err.print()
或System.out.print()
記錄的應用程式記錄檔。下圖顯示第二代執行階段中的個別要求和應用程式記錄:
stdout
和 stderr
在第一代執行階段中,App Engine 會將傳送至 stdout
和 stderr
的記錄視為應用程式記錄,並自動將這些應用程式記錄項目歸入相關聯的要求記錄下方。
在第二代執行階段中,App Engine 預設不會將記錄與 stdout
和 stderr
關聯。如要使用 stdout
和 stderr
將應用程式記錄實體與要求記錄分組,請按照「將結構化記錄寫入 stdout
和 stderr
」中的操作說明操作。
我們不建議您將記錄資料寫入 stdout
和 stderr
,因為某些 App Engine 平台記錄資料 (JVM、Jetty、內部基礎架構記錄資料) 也會傳送至 stderr
。應用程式記錄和平台記錄會與 stderr
記錄名稱一併顯示,導致混淆。由於 App Engine 的平台記錄量較高,因此在第二代執行階段中,這項問題會更加嚴重。
App Engine 平台記錄
在第一代執行階段中,App Engine 不會發出平台記錄。
在第二代執行階段中,App Engine 會在執行個體啟動或關閉期間,以 /var/log/google_init.log
為記錄名稱,傳送平台記錄。
您可以放心忽略平台記錄。如要避免看到這些記錄,請使用查詢 logName="/var/log/google_init.log"
將篩選器新增至 Logs Explorer。
下圖顯示第二代執行階段中的平台記錄:
Cloud Logging API 配額
在第一代執行階段中,App Engine 會將要求期間產生的所有應用程式記錄嵌入單一要求記錄,並將嵌入的要求傳送至 Cloud Logging。每個要求都對應至一筆 Cloud Logging 寫入作業。
在第二代執行階段中,App Engine 會將每個應用程式記錄以個別記錄項目的形式傳送至 Cloud Logging,導致每項要求的 Cloud Logging 寫入總數增加。
Google Cloud 會根據 Cloud Logging 使用的整體儲存空間來決定計費。即使記錄檔所需的整體儲存空間並未大幅增加,每分鐘的寫入次數也會增加,具體取決於 App Engine 每個要求寫入的應用程式記錄數量。如果應用程式超過 Cloud Logging 寫入配額,您可以要求提高使用量配額。
詳情請參閱 Cloud Logging 的定價。
轉換程序總覽
即使應用程式記錄檔未嵌入第二代執行階段的請求記錄檔,仍可保留第一代應用程式類似的記錄檔查看體驗。
您可以選擇下列任一選項,在第二代執行階段中設定記錄:
使用
java.util.logging
(JUL) 套件:App Engine 內建支援功能,可將要求和應用程式記錄與追蹤 ID 建立關聯。如果應用程式記錄中包含追蹤 ID,記錄檔探索工具會將應用程式記錄以要求記錄為單位群組呈現。使用 Java 適用的 Simple Logging Facade (SLF4J):您必須修改來源程式碼,才能根據應用程式使用的下列記錄後端新增追蹤 ID:
使用 java.util.logging
(JUL) 套件
如果您的應用程式使用第一代執行階段,並為所有記錄需求實作 java.util.logging
套件,則無需修改程式碼即可遷移至第二代執行階段。
以下範例說明如何使用 java.util.logging
套件,在第二代執行階段記錄資料:
package com.example.appengine.my_app;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.util.logging.Logger;
@WebServlet(name = "HelloAppEngine", value = "/")
public class HelloAppEngine extends HttpServlet {
// Use the java.util.logging.Logger to log messages
private static final Logger logger = Logger.getLogger(HelloAppEngine.class.getName());
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// Sample log messages
logger.info("Info message");
logger.warning("Warning message");
logger.severe("Severe message");
response.setContentType("text/plain");
response.getWriter().println("Hello App Engine");
}
}
將應用程式記錄與要求記錄分組
在第二代執行階段中,要求記錄中的 protoPayload.line
欄位不包含應用程式記錄。記錄檔探索工具會使用 trace
欄位將要求記錄檔和應用程式記錄檔分組。java.util.logging
套件會自動將追蹤 ID 新增至所有要求和應用程式記錄。如要在 Logs Explorer 中查看相關聯的記錄,請參閱「查看相關聯的記錄」。
使用 Java 適用的 Simple Logging Facade (SLF4J)
SLF4J 是 Java 應用程式中使用率最高的記錄介面。由於是 Facade,SLF4J 介面不受其記錄後端平台限制,因此您可以選擇任何適合應用程式的後端。
下圖顯示兩個 SLF4J 後端的整合選項,包括 java.util.logging
程式庫和 Logback 附加程式:
搭配 java.util.logging
套件的 SLF4J
當您使用 SLF4J 搭配 java.util.logging
做為記錄後端時,SLF4J 可讓您將應用程式與 Cloud Logging 整合。根據預設,App Engine 會在所有要求和應用程式記錄中新增追蹤 ID。這個機制可在 Logs Explorer 中將要求和應用程式記錄分組。
如要使用 java.util.logging
實作 SLF4J,請按照下列步驟操作:
將
slf4j-jdk14.jar
依附元件新增至pom.xml
檔案。slf4j-jdk14.jar
檔案可為java.util.logging
程式庫提供後端整合:<!-- SLF4J interface --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.4</version> </dependency> <!-- JUL implementation for SLF4J --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>2.0.9</version> </dependency>
建立
WEB-INF/logging.properties
檔案以新增自訂設定:com.example.appengine.java8.HelloAppEngine.level = INFO
更新
appengine-web.xml
檔案,加入WEB-INF/logging.properties
的<property>
值:<system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties>
下圖顯示 SLF4J 搭配 java.util.logging
如何自動將追蹤 ID 新增至應用程式記錄:
如要將記錄檔探索工具檢視畫面調整為以要求為中心的檢視畫面 (例如第一代執行階段),請參閱「查看關聯記錄」。
搭配 Logback 附加程式使用 SLF4J
如果第一代執行階段應用程式使用內建的 SLF4J 實作項目,並搭配使用 Logback,則必須更新原始碼,並實作額外的步驟來分組要求和應用程式記錄。
如要將應用程式與 Cloud Logging 整合,請按照下列步驟操作:
將
google-cloud-logging-logback
附加程式新增至pom.xml
檔案,即可安裝 Logback 的記錄附加程式:<!-- SLF4J interface --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.4</version> </dependency> <!-- Logback JARs --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.3.6</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.3.5</version> </dependency> <!-- Google Cloud logging appender for Logback --> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-logging-logback</artifactId> </dependency>
建立記錄增強器,將追蹤 ID 新增至每個
LogEntry
欄位。以下TraceIdLoggingEnhancer
類別會使用 ApiProxy API 擷取與要求相關聯的追蹤 ID:import com.google.appengine.api.utils.SystemProperty; import com.google.cloud.logging.LogEntry; import com.google.cloud.logging.LoggingEnhancer; import com.google.apphosting.api.ApiProxy; import com.google.apphosting.api.ApiProxy.Environment; // Add trace ID to the log entry public class TraceIdLoggingEnhancer implements LoggingEnhancer { @Override public void enhanceLogEntry(LogEntry.Builder logEntry) { final String PROJECT_ID = SystemProperty.applicationId.get(); Environment environment = ApiProxy.getCurrentEnvironment(); if (environment instanceof ApiProxy.EnvironmentWithTrace) { ApiProxy.EnvironmentWithTrace environmentWithTrace = (ApiProxy.EnvironmentWithTrace) environment; environmentWithTrace .getTraceId() .ifPresent( id -> logEntry.setTrace(String.format("projects/%s/traces/%s", PROJECT_ID, id))); } } } // [END logging_enhancer]
在
logback.xml
檔案中新增 Cloud Logging 附加程式設定,以設定 Logback。Logback 架構會透過WEB-INF/classes
中的logback.xml
檔案管理設定:<configuration> <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender"> <!-- This should be set to the new Logging Enhancer in the app code. --> <enhancer>com.example.appengine.my_app.enhancers.TraceIdLoggingEnhancer</enhancer> <resourceType>gae_app</resourceType> </appender> <root level="info"> <appender-ref ref="CLOUD" /> </root> </configuration>
下圖顯示最終應用程式目錄結構:
查看相關聯的記錄檔
您可以使用每個記錄項目中的追蹤 ID 欄位,在記錄檔探索工具中查看相關聯的記錄檔。如要在記錄檔探索工具中查看相關聯的記錄,請按照下列步驟操作:
在 Google Cloud 控制台的導覽面板中,依序選取「Logging」和「Logs Explorer」:
在「Resource Type」(資源類型) 中,選取「GAE Application」(GAE 應用程式)。
如要查看並關聯要求記錄,請在「記錄名稱」中選取「request_log」。或者,如要依據要求記錄檔建立關聯,請按一下「依據」,然後選取「request_log」:
如要展開記錄項目,請在「查詢結果」窗格中按一下「展開」。展開後,每個要求記錄都會顯示相關聯的應用程式記錄。