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.line
der 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.line
im Anfragelog fehlt. Stattdessen zeichnet die App Engine jedes Anwendungslog als separaten Eintrag auf. Der Logname hängt von Ihrer Logeinrichtung ab.var/log/app
enthält Logs, die mit Standard-Logging-Frameworks wiejava.util.logging
oder 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.
Die Abrechnung in 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.xml
die Abhängigkeitslf4j-jdk14.jar
hinzu. Die Dateislf4j-jdk14.jar
enthä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 = INFO
Aktualisieren Sie die Datei
appengine-web.xml
, um den Wert<property>
fürWEB-INF/logging.properties
aufzunehmen:<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.xml
dengoogle-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.xml
hinzu, um das Logback zu konfigurieren. Das Logback-Framework verwaltet die Konfiguration über die Dateilogback.xml
inWEB-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 anschließend 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.