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 den Laufzeiten der zweiten Generation nicht im Log-Explorer unter 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 die Logging-Methoden implementieren können, die Sie in Ihren Laufzeitanwendungen der ersten Generation verwendet haben. Sie erhalten dann bei der Migration Ihrer Anwendung zu Java 11+ fast dieselben Filter- und Logging-Korrelationsergebnisse.
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 oder höher) | |
---|---|---|
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. |
In App Engine werden keine Logs eingebettet, die in stdout und stderr geschrieben wurden.
|
App Engine-Plattformlogs | 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.
|
Kontingent für die Cloud Logging API | Jede Anfrage entspricht einem Cloud Logging-Schreibvorgang. | Jeder mit einer Anfrage verknüpfte Anwendungslogeintrag entspricht einem Cloud Logging-Schreibvorgang. Die Cloud Logging API-Nutzung steigt in den Laufzeiten der zweiten Generation an. |
Logs und Anwendungslogs anfordern
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. Maximieren Sie eine Anfrage im Log-Explorer, um Anwendungslogs aufzurufen.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 protokolliert App Engine jedes Anwendungslog als separaten Eintrag. Der Logname hängt von der Logging-Einrichtung ab.var/log/app
enthält Logs, die mit Standard-Logging-Frameworks wiejava.util.logging
oder der Simple Logging Facade für Java (SLF4J) ausgegeben werden. Die Logsstderr
undstdout
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 im zugehörigen Anfragelog.
In den Laufzeiten der zweiten Generation korreliert App Engine keine Logs, die standardmäßig an stdout
und stderr
ausgegeben 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. Dies ist in Laufzeiten der zweiten Generation übertrieben, da App Engine ein größeres Volumen an Plattformlogs hat.
App Engine-Plattformlogs
In der Laufzeit der ersten Generation gibt App Engine keine Plattformlogs aus.
In den Laufzeiten der zweiten Generation gibt App Engine beim Starten oder Herunterfahren einer Instanz Plattformlogs mit dem Lognamen /var/log/google_init.log
aus.
Sie können die Plattformlogs ignorieren. Fügen Sie dem Log-Explorer einen Filter mit der Abfrage logName="/var/log/google_init.log"
hinzu, um diese Logs zu vermeiden.
Die folgende Abbildung zeigt Plattformlogs in den Laufzeiten der zweiten Generation:
Kontingente für die Cloud Logging API
In der Laufzeit der ersten Generation bettet App Engine alle Anwendungslogs ein, die während einer Anfrage ausgegeben werden, in ein einzelnes Anfragelog und sendet die eingebettete Anfrage an Cloud Logging. Jede Anfrage entspricht einem Cloud Logging-Schreibvorgang.
In den Laufzeiten der zweiten Generation sendet App Engine jedes Anwendungslog in separaten Logeinträgen an Cloud Logging, was zu einer Erhöhung der Gesamtzahl der Cloud Logging-Schreibvorgänge pro Anfrage führt.
Die Abrechnung in Google Cloud basiert auf dem Gesamtspeicher, den Cloud Logging verwendet. Auch wenn der für Logs benötigte Gesamtspeicher nicht erheblich zunimmt, steigen die 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 beantragen.
Weitere Informationen finden Sie unter pricing.
Übersicht über den Migrationsprozess
Auch wenn Anwendungslogs nicht in die Anfragelogs der Laufzeiten der zweiten Generation eingebettet sind, können Sie die Logs wie bei Anwendungen der ersten Generation beibehalten.
Sie können eine der folgenden Optionen auswählen, um das Logging in Laufzeiten der zweiten Generation einzurichten:
java.util.logging
-Paket (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 Anwendungslogs vorhanden ist, rendert Logs Explorer Anwendungslogs, die in einem Anfragelog gruppiert sind.Simple Logging Facade for Java (SLF4J) verwenden: Sie müssen Ihren Quellcode ändern, um die Trace-ID abhängig vom folgenden Logging-Back-End, das von Ihrer Anwendung verwendet wird, hinzuzufügen:
Das 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, sind für die Migration zu Laufzeiten der zweiten Generation keine Codeänderungen erforderlich.
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. Der Log-Explorer verwendet das Feld trace
, um Anfragelogs und Anwendungslogs zu gruppieren. 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.
Einfache Logging-Fassade für Java (SLF4J) verwenden
SLF4J ist die gängigste Logging-Schnittstelle, die in Java-Anwendungen verwendet wird. Da es sich um eine Fassade handelt, ist die SLF4J-Schnittstelle plattformunabhängig von ihrem Logging-Back-End, sodass Sie jedes für Ihre Anwendungen geeignete Back-End auswählen können.
Die folgende Abbildung zeigt Integrationsoptionen für zwei SLF4J-Back-Ends, einschließlich der Bibliothek java.util.logging
und des Logback-Appenders:
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. App Engine fügt standardmäßig allen Anfrage- und Anwendungslogs eine Trace-ID hinzu. Dieser Mechanismus ermöglicht die Gruppierung von Anfrage- und Anwendungslogs im Log-Explorer.
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
stellt die Back-End-Integration für die Bibliothekjava.util.logging
bereit:<!-- 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
so, dass sie den Wert<property>
fürWEB-INF/logging.properties
enthält:<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
die Trace-ID automatisch zu einem Anwendungslog hinzufügt:
Informationen zum Optimieren der Log-Explorer-Ansicht auf eine anfrageorientierte Ansicht wie die 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 binden Sie Ihre Anwendung in Cloud Logging ein:
Fügen Sie den Appender
google-cloud-logging-logback
zur Dateipom.xml
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 die Datei
logback.xml
ein, 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 Struktur des Anwendungsverzeichnisses:
Korrelierte Logs ansehen
Sie können korrelierte Logs im Log-Explorer mithilfe des Trace-ID-Felds 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.