將記錄功能遷移至第二代 Java 執行階段

第二代執行階段 (Java 11 以上版本) 中,記錄的某些方面與第一代執行階段 (Java 8) 不同。與第一代執行階段不同,在第二代執行階段中,應用程式記錄並未在「記錄檔探索工具」中依要求記錄分組。此外,在第二代執行階段中,App Engine 會將與要求相關聯的每個應用程式記錄,以單獨的記錄項目寫入 Cloud Logging。

本指南說明如何實作與第一代執行階段應用程式相同的記錄方法,並在將應用程式遷移至 Java 11 以上版本時,取得幾乎相同的篩選和記錄相關聯結果。

主要差異

下表說明第一代與第二代執行階段之間的記錄差異:

第一代執行階段 (Java 8) 第二代執行階段 (Java 11 以上版本)
要求和應用程式記錄 (也稱為應用程式記錄) App Engine 會將所有應用程式記錄嵌入要求記錄中。 App Engine 不會在要求記錄中嵌入應用程式記錄。
stdoutstderr App Engine 會將寫入 stdoutstderr 的記錄嵌入要求記錄中。 App Engine 不會將寫入 stdoutstderr 的記錄嵌入。
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」中展開要求,查看應用程式記錄。

    下圖顯示第一代執行階段中關聯的請求和應用程式記錄:

    Java 8 中的相關記錄

  • 第二代執行階段中,要求記錄檔不包含應用程式記錄項目,因為要求記錄檔中沒有 protoPayload.line 欄位。相反地,App Engine 會將每個應用程式記錄記錄為個別項目。記錄名稱取決於記錄設定。var/log/app 包含使用標準記錄架構 (例如 java.util.logging 或 Simple Logging Facade for Java (SLF4J)) 產生的記錄。stderrstdout 記錄檔包含使用 System.err.print()System.out.print() 記錄的應用程式記錄檔。

    下圖顯示第二代執行階段中的個別要求和應用程式記錄:

    在 Java 11 中分開記錄

stdoutstderr

在第一代執行階段中,App Engine 會將傳送至 stdoutstderr 的記錄視為應用程式記錄,並自動將這些應用程式記錄項目歸入相關聯的要求記錄下方。

在第二代執行階段中,App Engine 預設不會將記錄與 stdoutstderr 關聯。如要使用 stdoutstderr 將應用程式記錄實體與要求記錄分組,請按照「將結構化記錄寫入 stdoutstderr」中的操作說明操作。

我們不建議您將記錄資料寫入 stdoutstderr,因為某些 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) 套件

如果您的應用程式使用第一代執行階段,並為所有記錄需求實作 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 附加程式:

SLF4J 簡介

搭配 java.util.logging 套件的 SLF4J

當您使用 SLF4J 搭配 java.util.logging 做為記錄後端時,SLF4J 可讓您將應用程式與 Cloud Logging 整合。根據預設,App Engine 會在所有要求和應用程式記錄中新增追蹤 ID。這個機制可在 Logs Explorer 中將要求和應用程式記錄分組。

如要使用 java.util.logging 實作 SLF4J,請按照下列步驟操作:

  1. 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>
    
  2. 建立 WEB-INF/logging.properties 檔案以新增自訂設定:

    com.example.appengine.java8.HelloAppEngine.level = INFO
    
  3. 更新 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 新增至應用程式記錄:

依追蹤 ID 將應用程式記錄檔分組

如要將記錄檔探索工具檢視畫面調整為以要求為中心的檢視畫面 (例如第一代執行階段),請參閱「查看關聯記錄」。

搭配 Logback 附加程式使用 SLF4J

如果第一代執行階段應用程式使用內建的 SLF4J 實作項目,並搭配使用 Logback,則必須更新原始碼,並實作額外的步驟來分組要求和應用程式記錄。

如要將應用程式與 Cloud Logging 整合,請按照下列步驟操作:

  1. 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>
    
  2. 建立記錄增強器,將追蹤 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]
    
  3. 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 欄位,在記錄檔探索工具中查看相關聯的記錄檔。如要在記錄檔探索工具中查看相關聯的記錄,請按照下列步驟操作:

  1. 在 Google Cloud 控制台的導覽面板中,依序選取「Logging」和「Logs Explorer」

    前往「Logs Explorer」

  2. 在「Resource Type」(資源類型) 中,選取「GAE Application」(GAE 應用程式)

  3. 如要查看並關聯要求記錄,請在「記錄名稱」中選取「request_log」。或者,如要依據要求記錄檔建立關聯,請按一下「依據」,然後選取「request_log」

    關聯記錄檔

  4. 如要展開記錄項目,請在「查詢結果」窗格中按一下「展開」。展開後,每個要求記錄都會顯示相關聯的應用程式記錄。