Einige Aspekte des Loggings in den Laufzeiten der zweiten Generation (Java 11+) unterscheiden sich von der Laufzeit der ersten Generation (Java 8). Im Gegensatz zur Laufzeit der ersten Generation werden Anwendungslogs in der Laufzeit der zweiten Generation im Log-Explorer nicht unter den Anfragelogs gruppiert. Darüber hinaus schreibt App Engine in den Laufzeiten der zweiten Generation jedes mit einer Anfrage verknüpfte Anwendungslog als separaten Logeintrag in Cloud Logging.
In diesem Leitfaden wird beschrieben, wie Sie dieselben Logging-Methoden implementieren, die Sie in Ihren Laufzeitanwendungen der ersten Generation verwendet haben, und bei der Migration Ihrer Anwendung zu Java 11+ fast dieselben Filter- und Logging-Korrelationsergebnisse erhalten.
Wichtige Unterschiede
In der folgenden Tabelle werden die Unterschiede beim Logging zwischen Laufzeiten der ersten und zweiten Generation behandelt:
| Laufzeit der ersten Generation (Java 8) | Laufzeiten der zweiten Generation (Java 11+) | |
|---|---|---|
| Anfrage- und Anwendungslogs (auch Anwendungslogs genannt) | App Engine bettet alle Anwendungslogs in das Anfragelog ein. | App Engine bettet keine Anwendungslogs in das zugehörige Anfragelog ein. |
stdout und stderr |
App Engine bettet Logs, die in stdout und stderr geschrieben wurden, in das Anfragelog ein. |
App Engine bettet keine Logs ein, die in stdout und stderr geschrieben wurden.
|
| App Engine-Plattformlogs | Die App Engine gibt keine internen Plattformlogs aus. | App Engine gibt beim Starten oder Herunterfahren einer Instanz mit dem Lognamen /var/log/google_init.log interne Plattformlogs aus.
|
| Kontingente für die Cloud Logging API | Jede Anfrage entspricht einem Cloud Logging-Schreibvorgang. | Jeder Anwendungslogeintrag, der mit einer Anfrage verknüpft ist, entspricht einem Cloud Logging-Schreibvorgang. Die Nutzung der Cloud Logging API steigt in den Laufzeiten der zweiten Generation. |
Anfragelogs und Anwendungslogs
Das Logging-Verhalten in Laufzeiten der ersten und zweiten Generation unterscheidet sich in folgender Weise:
In der Laufzeit der ersten Generation bettet App Engine Anwendungslogs in das Feld
protoPayload.lineder Anfragelogs ein. Sie können Anwendungslogs aufrufen, indem Sie eine Anfrage im Log-Explorer maximieren.Die folgende Abbildung zeigt korrelierte Anfrage- und Anwendungslogs in den Laufzeiten der ersten Generation:

In den Laufzeiten der zweiten Generation enthalten Anfragelogs keine Anwendungslogeinträge, da das Feld
protoPayload.lineim Anfragelog fehlt. Stattdessen zeichnet die App Engine jedes Anwendungslog als separaten Eintrag auf. Der Logname hängt von Ihrer Logeinrichtung ab.var/log/appenthält Logs, die mit Standard-Logging-Frameworks wiejava.util.loggingoder der Simple Logging Facade for Java (SLF4J) ausgegeben werden. Diestderr- undstdout-Logs enthalten Anwendungslogs, die mitSystem.err.print()oderSystem.out.print()protokolliert werden.Die folgende Abbildung zeigt separate Anfrage- und Anwendungslogs in den Laufzeiten der zweiten Generation:

stdout und stderr
In der Laufzeit der ersten Generation betrachtet App Engine Logs, die an stdout und stderr ausgegeben werden, als Anwendungslogs und gruppiert diese Anwendungslogeinträge automatisch unter dem zugehörigen Anfragelog.
In den Laufzeiten der zweiten Generation korreliert App Engine standardmäßig keine Logs, die an stdout und stderr gesendet werden. Folgen Sie der Anleitung unter Strukturierte Logs in stdout und stderr schreiben, um Anwendungslogentitäten mit dem Anfragelog mithilfe von stdout und stderr zu gruppieren.
Wir empfehlen, das Logging in stdout und stderr nicht, da bestimmte App Engine-Plattformlogs (JVM, Jetty, interne Infrastrukturlogs) ebenfalls an stderr ausgegeben werden. Anwendungs- und Plattformlogs werden zusammen mit dem Lognamen stderr angezeigt, was zu Mehrdeutigkeit führt. Bei Laufzeiten der zweiten Generation ist das Problem noch ausgeprägter, da die App Engine mehr Plattformlogs generiert.
App Engine-Plattformlogs
In der Laufzeit der ersten Generation gibt App Engine keine Plattformlogs aus.
In den Laufzeiten der zweiten Generation gibt App Engine Plattformlogs beim Starten oder Herunterfahren der Instanz mit dem Lognamen /var/log/google_init.log aus.
Sie können die Plattformlogs ignorieren. Wenn Sie diese Logs nicht sehen möchten, fügen Sie dem Log-Explorer einen Filter mit der Abfrage logName="/var/log/google_init.log" hinzu.
Die folgende Abbildung zeigt Plattformlogs in den Laufzeiten der zweiten Generation an:

Kontingente für die Cloud Logging API
In der Laufzeit der ersten Generation bettet App Engine alle Anwendungslogs, die während einer Anfrage ausgegeben werden, in ein einzelnes Anfragelog ein und sendet die eingebettete Anfrage an Cloud Logging. Jede Anfrage entspricht einem Cloud Logging-Schreibvorgang.
Bei Laufzeiten der zweiten Generation sendet App Engine jedes Anwendungslog in separaten Logeinträgen an Cloud Logging. Dadurch steigt die Gesamtzahl der Cloud Logging-Schreibvorgänge pro Anfrage.
Google Cloud richtet sich nach dem Gesamtspeicher, den Cloud Logging verwendet. Auch wenn der Gesamtspeicherplatz für Logs nicht wesentlich zunimmt, steigt die Anzahl der Schreibvorgänge pro Minute, je nachdem, wie viele Anwendungslogs App Engine pro Anfrage schreibt. Wenn Ihre Anwendung das Schreibkontingent von Cloud Logging überschreitet, können Sie eine Erhöhung Ihres Nutzungskontingents anfordern.
Weitere Informationen finden Sie in der Preisübersicht für Cloud Logging.
Übersicht über den Migrationsprozess
Auch wenn Anwendungslogs in den Laufzeiten der zweiten Generation nicht in die Anfragelogs eingebettet sind, können Sie die Logs wie bei Anwendungen der ersten Generation aufrufen.
Sie können eine der folgenden Optionen auswählen, um das Logging in den Laufzeiten der zweiten Generation einzurichten:
Paket
java.util.logging(JUL) verwenden: App Engine bietet integrierte Unterstützung für die Korrelation von Anfrage- und Anwendungslogs mit einer Trace-ID. Wenn die Trace-ID in den Anwendungslogs vorhanden ist, werden die Anwendungslogs im Log-Explorer in einem Anfragelog gruppiert.Simple Logging Facade for Java (SLF4J) verwenden: Sie müssen Ihren Quellcode ändern, um die Trace-ID abhängig vom folgenden Logging-Backend, das Ihre Anwendung verwendet, hinzuzufügen:
Paket java.util.logging (JUL) verwenden
Wenn Ihre Anwendungen, die die Laufzeit der ersten Generation verwenden, das Paket java.util.logging für alle Logging-Anforderungen implementieren, erfordert die Migration zu Laufzeiten der zweiten Generation keine Codeänderungen.
Das folgende Beispiel zeigt, wie Sie das Paket java.util.logging zum Logging in Laufzeiten der zweiten Generation verwenden können:
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");
}
}
Anwendungslogs mit dem Anfragelog gruppieren
In den Laufzeiten der zweiten Generation enthält das Feld protoPayload.line im Anfragelog keine Anwendungslogs. Im Log-Explorer werden Anfrage- und Anwendungslogs anhand des Felds trace gruppiert. Das Paket java.util.logging fügt die Trace-ID automatisch allen Anfrage- und Anwendungslogs hinzu. Informationen zum Anzeigen korrelierter Logs im Log-Explorer finden Sie unter Korrelierte Logs ansehen.
Simple Logging Facade for Java (SLF4J) verwenden
SLF4J ist die gängigste Logging-Schnittstelle in Java-Anwendungen. Da die SLF4J-Schnittstelle eine Fassade ist, ist sie plattformunabhängig vom Logging-Backend, sodass Sie jedes für Ihre Anwendungen geeignete Backend auswählen können.
Die folgende Abbildung zeigt Integrationsoptionen für zwei SLF4J-Backends, einschließlich der java.util.logging-Bibliothek und des Logback-Appender:

SLF4J mit java.util.logging-Paket
Mit SLF4J können Sie Ihre Anwendung in Cloud Logging einbinden, wenn Sie SLF4J mit java.util.logging als Logging-Backend verwenden. Standardmäßig fügt App Engine allen Anfrage- und Anwendungslogs eine Trace-ID hinzu. Mit diesem Mechanismus können Anfrage- und Anwendungslogs im Log-Explorer gruppiert werden.
So implementieren Sie SLF4J mit java.util.logging:
Fügen Sie der Datei
pom.xmldie Abhängigkeitslf4j-jdk14.jarhinzu. Die Dateislf4j-jdk14.jarenthält die Backend-Integration für die Bibliothekjava.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>Erstellen Sie eine
WEB-INF/logging.properties-Datei, um benutzerdefinierte Konfigurationen hinzuzufügen:com.example.appengine.java8.HelloAppEngine.level = INFOAktualisieren Sie die Datei
appengine-web.xml, um den Wert<property>fürWEB-INF/logging.propertiesaufzunehmen:<system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties>
Die folgende Abbildung zeigt, wie SLF4J mit java.util.logging automatisch die Trace-ID in ein Anwendungslog einfügt:

Informationen zum Anpassen der Log-Explorer-Ansicht auf eine anfrageorientierte Ansicht wie bei der Laufzeit der ersten Generation finden Sie unter Korrelierte Logs ansehen.
SLF4J mit Logback-Appender verwenden
Wenn Ihre Laufzeitanwendungen der ersten Generation die integrierte Implementierung von SLF4J mit Logback verwenden, müssen Sie Ihren Quellcode aktualisieren und zusätzliche Schritte zum Gruppieren von Anfrage- und Anwendungslogs implementieren.
So integrieren Sie Ihre Anwendung in Cloud Logging:
Fügen Sie der Datei
pom.xmldengoogle-cloud-logging-logback-Appender hinzu, um den Logging-Appender für Logback zu installieren:<!-- 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>Erstellen Sie eine Logging-Optimierung, um jedem
LogEntry-Feld eine Trace-ID hinzuzufügen. Die folgendeTraceIdLoggingEnhancer-Klasse verwendet die ApiProxy API, um die mit einer Anfrage verknüpfte Trace-ID abzurufen: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]Fügen Sie die Cloud Logging-Appender-Konfiguration in der Datei
logback.xmlhinzu, um das Logback zu konfigurieren. Das Logback-Framework verwaltet die Konfiguration über die Dateilogback.xmlinWEB-INF/classes:<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>Die folgende Abbildung zeigt die endgültige Verzeichnisstruktur der Anwendung:

Korrelierte Logs ansehen
Sie können korrelierte Logs im Log-Explorer mithilfe des Felds „Trace-ID“ in jedem Logeintrag aufrufen. So rufen Sie korrelierte Logs im Log-Explorer auf:
Wählen Sie im Navigationsbereich der Google Cloud Console Logging und dann Log-Explorer aus:
Wählen Sie unter Ressourcentyp die Option GAE-Anwendung aus.
Wählen Sie unter Logname die Option request_log aus, um Anfragelogs aufzurufen und zu korrelieren. Wenn Sie nach Anfragelogs korrelieren möchten, klicken Sie alternativ auf Korrelieren nach und wählen Sie request_log aus.

Klicken Sie im Bereich Abfrageergebnisse auf Maximieren, um einen Logeintrag zu maximieren. Beim Maximieren werden in jedem Anfragelog die zugehörigen Anwendungslogs angezeigt.