Traces und Messwerte mit Java generieren

In diesem Dokument wird beschrieben, wie Sie eine Java-Anwendung ändern, um Trace- und Messwertdaten mit dem Open-Source-Framework OpenTelemetry zu erfassen und strukturierte JSON-Logs in die Standardausgabe zu schreiben. Dieses Dokument enthält auch Informationen zu einer Java Spring Boot-Beispielanwendung, die Sie installieren und ausführen können. Die Anwendung ist so konfiguriert, dass Messwerte, Traces und Logs generiert werden. Die Schritte sind unabhängig davon, ob Sie das Spring Boot Framework verwenden, identisch.

Manuelle und automatische Instrumentierung

Die in diesem Dokument beschriebene Instrumentierung basiert auf der automatischen OpenTelemetry-Instrumentierung, um Telemetrie an Ihr Google Cloud-Projekt zu senden. Bei Java bezieht sich die automatische Instrumentierung auf das dynamische Einfügen von Bytecode in Bibliotheken und Frameworks, um Telemetrie zu erfassen. Die automatische Instrumentierung kann Telemetriedaten für eingehende und ausgehende HTTP-Aufrufe erfassen. Weitere Informationen finden Sie unter Automatische Instrumentierung für Java.

OpenTelemetry bietet auch eine API zum Hinzufügen einer benutzerdefinierten Instrumentierung zu Ihrem eigenen Code. Bei OpenTelemetry wird dies als manuelle Instrumentierung bezeichnet. In diesem Dokument wird die manuelle Instrumentierung nicht beschrieben. Beispiele und Informationen zu diesem Thema finden Sie unter Manuelle Instrumentierung.

Hinweise

Cloud Logging, Cloud Monitoring, and Cloud Trace APIs aktivieren.

Aktivieren Sie die APIs

Anwendung für die Erfassung von Traces, Messwerten und Logs instrumentieren

Führen Sie die folgenden Schritte aus, um Ihre Anwendung so zu instrumentieren, dass Trace- und Messwertdaten erfasst und strukturiertes JSON in die Standardausgabe geschrieben wird, wie in den folgenden Abschnitten dieses Dokuments beschrieben:

  1. Anwendung für die Verwendung des OpenTelemetry-Java-Agents konfigurieren
  2. OpenTelemetry konfigurieren
  3. Strukturiertes Logging konfigurieren
  4. Strukturierte Logs schreiben

Anwendung für die Verwendung des OpenTelemetry-Java-Agents konfigurieren

Wenn Sie die Anwendung so konfigurieren möchten, dass strukturierte Logs geschrieben sowie Messwerte und Trace-Daten mit OpenTelemetry erfasst werden, aktualisieren Sie den Aufruf Ihrer Anwendung so, dass sie den OpenTelemetry-Java-Agent verwendet. Diese Methode zur Instrumentierung Ihrer Anwendung wird als automatische Instrumentierung bezeichnet, da Sie den Anwendungscode dazu nicht ändern müssen.

Das folgende Codebeispiel zeigt ein Dockerfile, das die JAR-Datei des OpenTelemetry-Java-Agent herunterlädt und den Befehlszeilenaufruf aktualisiert, um das Flag -javaagent zu übergeben.

RUN wget -O /opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.31.0/opentelemetry-javaagent.jar
CMD sh -c "java -javaagent:/opentelemetry-javaagent.jar -cp app:app/lib/* com.example.demo.DemoApplication \
	2>&1 | tee /var/log/app.log"

Alternativ können Sie das Flag -javaagent auch in der Umgebungsvariable JAVA_TOOL_OPTIONS festlegen:

export JAVA_TOOL_OPTIONS="-javaagent:PATH/TO/opentelemetry-javaagent.jar"

OpenTelemetry konfigurieren

Die Standardkonfiguration für den OpenTelemetry-Java-Agent exportiert Traces und Messwerte mithilfe des OTLP-Protokolls. Außerdem wird OpenTelemetry so konfiguriert, dass das Format W3C Trace Context zur Weitergabe von Trace-Kontext verwendet wird. Diese Konfiguration gewährleistet, dass Spans die richtige hierarchische Beziehung in einem Trace haben.

Weitere Informationen und Konfigurationsoptionen finden Sie unter Automatische OpenTelemetry-Java-Instrumentierung.

Strukturiertes Logging konfigurieren

Wenn Sie die Trace-Informationen in die JSON-formatierten Logs aufnehmen möchten, die in die Standardausgabe geschrieben werden, konfigurieren Sie Ihre Anwendung so, dass strukturierte Logs im JSON-Format ausgegeben werden. Wir empfehlen die Verwendung von Log4j2 als Logging-Implementierung. Das folgende Codebeispiel zeigt eine log4j2.xml-Datei, die für die Ausgabe strukturierter JSON-Logs mithilfe des JSON-Vorlagenlayouts konfiguriert wurde:

<!-- Format JSON logs for the Cloud Logging agent
https://cloud.google.com/logging/docs/structured-logging#special-payload-fields -->

<!-- Log4j2's JsonTemplateLayout includes a template for Cloud Logging's special JSON fields
https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-templates -->
<JsonTemplateLayout eventTemplateUri="classpath:GcpLayout.json">
  <!-- Extend the included GcpLayout to include the trace and span IDs from Mapped
  Diagnostic Context (MDC) so that Cloud Logging can correlate Logs and Spans -->
  <EventTemplateAdditionalField
    key="logging.googleapis.com/trace"
    format="JSON"
    value='{"$resolver": "mdc", "key": "trace_id"}'
  />
  <EventTemplateAdditionalField
    key="logging.googleapis.com/spanId"
    format="JSON"
    value='{"$resolver": "mdc", "key": "span_id"}'
  />
  <EventTemplateAdditionalField
    key="logging.googleapis.com/trace_sampled"
    format="JSON"
    value="true"
  />
</JsonTemplateLayout>

Die vorherige Konfiguration extrahiert Informationen zum aktiven Span aus dem zugeordneten Diagnosekontext von SLF4J und fügt diese Informationen als Attribute dem Log hinzu. Mit diesen Attributen können Sie dann ein Log mit einem Trace korrelieren:

  • logging.googleapis.com/trace: Der Ressourcenname des Trace, das mit dem Logeintrag verknüpft ist.
  • logging.googleapis.com/spanId: Die Span-ID mit dem Trace, das dem Logeintrag zugeordnet ist.
  • logging.googleapis.com/trace_sampled: Der Wert dieses Felds muss true oder false sein.

Weitere Informationen zu diesen Feldern finden Sie in der Struktur LogEntry.

Strukturierte Logs schreiben

Verwenden Sie die SLF4J Logging API, um strukturierte Logs zu schreiben, die mit einem Trace verknüpft sind. Die folgende Anweisung zeigt beispielsweise, wie die Methode Logger.info() aufgerufen wird:

logger.info("handle /multi request with subRequests={}", subRequests);

Der OpenTelemetry-Java-Agent füllt automatisch den zugeordneten Diagnosekontext des SLF4J mit dem Span-Kontext des aktuellen aktiven Spans im OpenTelemetry-Kontext. Der zugeordnete Diagnosekontext wird dann in die JSON-Logs eingefügt, wie unter Strukturiertes Logging konfigurieren beschrieben.

Beispielanwendung ausführen, die für die Erfassung von Telemetriedaten konfiguriert ist

Die Beispielanwendung verwendet anbieterneutrale Formate, einschließlich JSON für Logs und OTLP für Messwerte und Traces sowie das Spring Boot Framework. In diesem Beispiel wird die mit Google-Exportern konfigurierte OpenTelemetry-Collector verwendet, um die Telemetrie an Google Cloud weiterzuleiten. Die Anwendung hat zwei Endpunkte:

  • Der /multi-Endpunkt wird von der handleMulti-Funktion verarbeitet. Der Lastgenerator in der Anwendung gibt Anfragen an den Endpunkt /multi aus. Wenn dieser Endpunkt eine Anfrage empfängt, sendet er zwischen drei und sieben Anfragen an den Endpunkt /single auf dem lokalen Server.

    /**
     * handleMulti handles an http request by making 3-7 http requests to the /single endpoint.
     *
     * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the controller body.
     */
    @GetMapping("/multi")
    public Mono<String> handleMulti() throws Exception {
      int subRequests = ThreadLocalRandom.current().nextInt(3, 8);
    
      // Write a structured log with the request context, which allows the log to
      // be linked with the trace for this request.
      logger.info("handle /multi request with subRequests={}", subRequests);
    
      // Make 3-7 http requests to the /single endpoint.
      return Flux.range(0, subRequests)
          .concatMap(
              i -> client.get().uri("http://localhost:8080/single").retrieve().bodyToMono(Void.class))
          .then(Mono.just("ok"));
    }
  • Der /single-Endpunkt wird von der handleSingle-Funktion verarbeitet. Wenn dieser Endpunkt eine Anfrage empfängt, wechselt er für eine kurze Verzögerung in den Ruhemodus und antwortet dann mit einem String.

    /**
     * handleSingle handles an http request by sleeping for 100-200 ms. It writes the number of
     * milliseconds slept as its response.
     *
     * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the controller body.
     */
    @GetMapping("/single")
    public String handleSingle() throws InterruptedException {
      int sleepMillis = ThreadLocalRandom.current().nextInt(100, 200);
      logger.info("Going to sleep for {}", sleepMillis);
      Thread.sleep(sleepMillis);
      logger.info("Finishing the request");
      return String.format("slept %s\n", sleepMillis);
    }

Anwendung herunterladen und bereitstellen

So führen Sie das Beispiel aus:

  1. Aktivieren Sie Cloud Shell in der Google Cloud Console.

    Cloud Shell aktivieren

    Unten in der Google Cloud Console wird eine Cloud Shell-Sitzung gestartet und eine Eingabeaufforderung angezeigt. Cloud Shell ist eine Shell-Umgebung, in der das Google Cloud CLI bereits installiert ist und Werte für Ihr aktuelles Projekt bereits festgelegt sind. Das Initialisieren der Sitzung kann einige Sekunden dauern.

  2. Klonen Sie das Repository:

    git clone https://github.com/GoogleCloudPlatform/opentelemetry-operations-java
    
  3. Gehen Sie zum Beispielverzeichnis:

    cd opentelemetry-operations-java/examples/instrumentation-quickstart
    
  4. Erstellen Sie das Beispiel und führen Sie es aus:

    docker compose up --abort-on-container-exit
    

    Wenn Sie Cloud Shell nicht ausführen, führen Sie die Anwendung mit der Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS aus, die auf eine Datei mit Anmeldedaten verweist. Standardanmeldedaten für Anwendungen stellt eine Datei mit Anmeldedaten unter $HOME/.config/gcloud/application_default_credentials.json bereit.

    # Set environment variables
    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json"
    export USERID="$(id -u)"
    
    # Run
    docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
    

Messwerte ansehen

Die OpenTelemetry-Instrumentierung in der Beispielanwendung generiert Prometheus-Messwerte, die Sie mit dem Metrics Explorer aufrufen können:

  • Prometheus/http_server_duration_milliseconds/histogram zeichnet die Dauer von Serveranfragen auf und speichert die Ergebnisse in einem Histogramm.

  • Prometheus/http_client_duration_milliseconds/histogram zeichnet die Dauer von Clientanfragen auf und speichert die Ergebnisse in einem Histogramm.

So rufen Sie die von der Beispielanwendung generierten Messwerte auf:
  1. Rufen Sie in der Google Cloud Console die Seite Metrics Explorer auf.

    Zum Metrics Explorer

    Wenn Sie diese Seite über die Suchleiste suchen, wählen Sie das Ergebnis aus, dessen Zwischenüberschrift Monitoring ist.

  2. Maximieren Sie im Element Messwert das Menü Messwert auswählen, geben Sie http_server in die Filterleiste ein und wählen Sie dann über die Untermenüs einen bestimmten Ressourcentyp und Messwert aus:
    1. Wählen Sie im Menü Aktive Ressourcen die Option Prometheus-Ziel aus.
    2. Wählen Sie im Menü Aktive Messwertkategorien die Option Http aus.
    3. Wählen Sie im Menü Aktive Messwerte einen Messwert aus.
    4. Klicken Sie auf Anwenden.
  3. Konfigurieren Sie, wie die Daten angezeigt werden.

    Wenn die Messungen für einen Messwert kumulativ sind, normalisiert Metrics Explorer die gemessenen Daten automatisch nach dem Ausrichtungszeitraum. Dadurch wird im Diagramm eine Rate angezeigt. Weitere Informationen finden Sie unter Arten, Typen und Umwandlungen.

    Wenn ganzzahlige oder doppelte Werte gemessen werden, z. B. mit den beiden counter-Messwerten, summiert der Metrics Explorer automatisch alle Zeitachsen. Wenn Sie die Daten für die HTTP-Routen /multi und /single aufrufen möchten, legen Sie im ersten Menü des Eintrags Aggregation die Option Keine fest.

    Weitere Informationen zum Konfigurieren eines Diagramms finden Sie unter Messwerte bei Verwendung von Metrics Explorer auswählen.

Traces ansehen

So rufen Sie Ihre Trace-Daten auf:

  1. Rufen Sie in der Google Cloud Console die Seite Trace Explorer auf:

    Zum Trace Explorer

    Sie können diese Seite auch über die Suchleiste finden.

  2. Wählen Sie im Streudiagramm einen Trace mit dem URI /multi aus.
  3. Wählen Sie im Gantt-Diagramm im Bereich Trace-Details den Span mit der Bezeichnung /multi aus.

    Ein Steuerfeld mit Informationen zur HTTP-Anfrage wird geöffnet. Zu diesen Details gehören die Methode, der Statuscode, die Anzahl der Byte und der User-Agent des Aufrufers.

  4. Wählen Sie den Tab Logs und Ereignisse aus, um die mit diesem Trace verknüpften Logs aufzurufen.

    Auf dem Tab werden einzelne Logs angezeigt. Maximieren Sie den Logeintrag, um die Details anzusehen. Sie können auch auf Logs ansehen klicken und das Log mit dem Log-Explorer aufrufen.

Weitere Informationen zur Verwendung von Cloud Trace Explorer finden Sie unter Traces suchen und untersuchen.

Logs ansehen

Im Log-Explorer können Sie Ihre Logs prüfen und sich auch die zugehörigen Traces ansehen, sofern vorhanden.

  1. Wählen Sie im Navigationsbereich der Google Cloud Console Logging und anschließend Log-Explorer aus:

    Zum Log-Explorer

  2. Suchen Sie ein Log mit der Beschreibung handle /multi request.

    Erweitern Sie den Logeintrag, um die Details des Logs aufzurufen.

  3. Klicken Sie auf Traces für einen Logeintrag mit der Nachricht "handle /multi request" und wählen Sie dann Trace-Details anzeigen aus.

    Der Bereich Trace-Details wird geöffnet und zeigt den ausgewählten Trace an.

Weitere Informationen zur Verwendung des Log-Explorers finden Sie unter Logs mit dem Log-Explorer ansehen.

Nächste Schritte