Benutzerdefinierte Instrumentierung mit OpenTelemetry custom-instrumentation

Wenn OpenTelemetry für Ihre Umgebung aktiviert ist, verfolgt AEM as a Cloud Service jede Anfrage und exportiert JVM-, HTTP- und AEM-Metriken automatisch. Diese Telemetrie beschreibt AEM. Es zeigt an, dass das Rendern einer Seite 900 Millisekunden gedauert hat und welche Komponenten sie gerendert hat. Es kann nicht angezeigt werden, was Ihr eigener Code getan hat, z. B. für welches Listenelement eine Repository-Abfrage durchgeführt wurde und ob sie etwas gefunden hat, oder welche Seiten auf eine teure Suche zurückfallen, da ein Autor ein Feld ausgelassen hat.

Sie können dieses Wissen selbst mit der OpenTelemetry-API hinzufügen. Die Bereiche und Attribute, die Ihr Code erstellt, bewegen sich mit der automatischen Telemetrie: derselbe Service-Name, dieselbe Verarbeitung, derselbe APM-Provider. Sie konfigurieren in Ihrem Code keinen Endpunkt, keine Berechtigung und keinen Exporter.

Wenn Sie mit OpenTelemetry auf AEM as a Cloud Service noch nicht vertraut sind, beginnen Sie mit dem Tutorial Observability via OpenTelemetry, um mehr über die Funktionsweise zu erfahren. Folgen Sie dann OpenTelemetry für Einblicke in AEM-Anwendungen konfigurieren um sie für Ihre Umgebung zu aktivieren.

Die Beispiele auf dieser Seite instrumentieren die WKND-Referenz-Site. Jedes Beispiel beschreibt, was Sie erreichen möchten, den hinzuzufügenden Code und das Ergebnis, das Sie bei Ihrem APM-Anbieter erwarten können. Der vollständige instrumentierte Code, einschließlich der Komponententests, die für die Bereiche gelten, befindet sich auf der tutorial/otel-custom-instrumentation Verzweigung des WKND-Repositorys.

NOTE
Benutzerdefinierte Instrumentierung erfordert, dass OpenTelemetry für Ihre Umgebung aktiviert ist. Siehe Einrichten der Integration.

Funktionsweise der benutzerdefinierten Instrumentierung how-it-works

  • Der OpenTelemetry Java-Agent, den Adobe in Ihrer AEM-Umgebung ausführt, enthält die OpenTelemetry-SDK und -Exporteure. Ihr Code hängt nur von der OpenTelemetry API ab.
  • Wenn Ihr Code GlobalOpenTelemetry aufruft, verknüpft der Agent ihn mit seiner eigenen Implementierung. Ihre Spannen werden Teil der Spur der Anfrage, die sie ausführt, und Ihre Telemetrie wird mit dem Rest der Telemetrie Ihrer Umgebung exportiert.
  • Wenn der Agent nicht vorhanden ist (der lokale AEM SDK, Komponententests oder eine Umgebung ohne aktivierte OpenTelemetry-Funktion), unternimmt die API nichts, und zwar zu vernachlässigbaren Kosten. Sie können denselben Code in jeder Umgebung bereitstellen.
Was Sie hinzufügen
Wie
An Ihren APM-Provider gesendet
Spannen
Eine Tracer oder die @WithSpan Anmerkung
Ja
Attribute, Ereignisse und Fehlerstatus in Bereichen
Die Span-API
Ja
Mit Ablaufverfolgungen korrelierte Protokolleinträge
Ihre bestehende SLF4J-Protokollierung
Ja, auf WARN und höher, wenn Protokolle aktiviert sind
NOTE
Benutzerdefinierte Metriken wie Zähler und Histogramme, die Ihr Code erstellt, sind für eine bevorstehende Version geplant.

Einrichten eines Projekts set-up-project

Schritt 1: OpenTelemetry-API hinzufügen add-api

Fügen Sie die OpenTelemetry-API und die Instrumentationsanmerkungen zum dependencyManagement Abschnitt der übergeordneten pom.xml Ihres Projekts mit dem provided:

<properties>
    <opentelemetry.version>1.61.0</opentelemetry.version>
    <opentelemetry-instrumentation.version>2.27.0</opentelemetry-instrumentation.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-api</artifactId>
            <version>${opentelemetry.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-instrumentation-annotations</artifactId>
            <version>${opentelemetry-instrumentation.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Fügen Sie dann beide Abhängigkeiten (ohne Versionen) zum pom.xml jedes Bundles hinzu, das sie verwendet, z. B. core/pom.xml:

<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-instrumentation-annotations</artifactId>
</dependency>

Verwenden Sie opentelemetry-api 1.61.0 und opentelemetry-instrumentation-annotations 2.27.0 oder frühere Versionen. Sie stimmen mit dem von AEM as a Cloud Service ausgeführten OpenTelemetry-Java-Agenten überein, und neuere Versionen des Agenten unterstützen sie weiterhin. API-Funktionen, die nach der vom Agenten unterstützten Version hinzugefügt wurden, haben keine Auswirkungen.

Schritt 2: Einbetten der API in das Bundle embed-api

AEM as a Cloud Service exportiert die OpenTelemetry-API-Pakete nicht, sodass jedes Bundle, das die API verwendet, eine eigene Kopie enthalten muss. Fügen Sie die folgenden Anweisungen zur Bandkonfiguration Ihres Bundles hinzu. Mit dem AEM-Projektarchetyp 🔗 ist dies die bnd-maven-plugin in core/pom.xml. Behalten Sie alle Einträge bei, die bereits in Ihrer Import-Package enthalten sind.

Import-Package: !io.opentelemetry.*,javax.annotation;version=0.0.0,*
-includepackage: io.opentelemetry.*
Anleitung
Gründe für die Notwendigkeit
!io.opentelemetry.* zu Beginn der Import-Package
Die API verweist auf optionale OpenTelemetry-Pakete, die AEM nicht bereitstellt, und lädt sie nur, wenn sie vorhanden sind. Ohne diesen Ausschluss importiert das Bundle diese Pakete. Es kann nicht gestartet werden und der Cloud Manager-Build schlägt fehl. Siehe Fehlerbehebung.
-includepackage: io.opentelemetry.*
Kopiert die complete-API in Ihr Bundle. Der Agent verbindet die Kopie der API des Bundles nur dann mit einer eigenen Implementierung, wenn die gesamte API vorhanden ist. Wenn Sie nur die Pakete einbetten, auf die Ihr Code verweist, z. B. mit -conditionalpackage, werden Ihre Bereiche und Attribute ohne Fehler verworfen.

Jedes Bundle, das die -API verwendet, bettet eine eigene Kopie ein, und der Agent verbindet jede Kopie separat.

CAUTION
Fügen Sie Ihrem Projekt nicht das OpenTelemetry-SDK, einen Exporter oder das Modul für die automatische Konfiguration von SDK hinzu und erstellen Sie keine eigene OpenTelemetrySdk-Instanz oder GlobalOpenTelemetry.set(). Die so gesendete Telemetrie umgeht den Agenten, die unter Welche Daten werden gesendet? beschriebenen Details der Cloud Service- und den konfigurierten Endpunkt.

Schritt 3: Erstellen eines Tracers create-tracer

Erstellen Sie eine Tracer für Ihre Code-Basis und verwenden Sie sie überall wieder. In WKND wird sie von einer kleinen Klasse gespeichert:

package com.adobe.aem.guides.wknd.core.telemetry;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Tracer;

public final class WkndTelemetry {

    /** Instrumentation scope: identifies telemetry produced by WKND code in your APM provider. */
    public static final String SCOPE = "com.adobe.aem.guides.wknd";

    public static final Tracer TRACER = GlobalOpenTelemetry.getTracer(SCOPE);

    private WkndTelemetry() {
    }
}

Der Bereichsname wird in jedem Bereich, den Sie durch diesen Tracer erstellen, als Instrumentationsbereich (oder Bibliotheksname) angezeigt. Verwenden Sie einen Namen, der Ihren Code identifiziert, z. B. das Java-Basispaket Ihres Projekts.

Wo Ihre Spannen angezeigt werden where-spans-appear

In AEM as a Cloud Service erzeugt eine Seitenanfrage bereits Bereiche aus AEM selbst. Die Bereiche, die Ihr Code erstellt, werden darin hinzugefügt. Dies ist beispielsweise der Pfad zur Bildlisten-Komponente in einer Spur der WKND-Magazinseite:

GET /*                                                     the request (AEM)
└─ SlingMainServlet.service                                Sling request processing (AEM)
   └─ AEM component: cq:Page                               (AEM)
      └─ AEM component: wknd/components/page               the page component (AEM)
         └─ HTL: libs.core.wcm.components.page.v3.page.page__002e__html
            └─ ...                                         containers and layout grids (AEM)
               └─ AEM component: wknd/components/image-list
                  └─ HTL: apps.wknd.components.image__002d__list.image__002d__list__002e__html
                     └─ ...                                spans that the Image List's Sling Model creates

Während eine Komponente gerendert wird, ist die Spanne ihres HTL-Skripts die aktuelle Spanne. Ein Sling-Modell, das mit data-sly-use geladen wird, wird innerhalb dieses Bereichs ausgeführt und umfasst so viele Elemente, dass das Modell als untergeordnete Elemente erstellt wird.

Jeder Anfragebereich erhält den Namen GET /* (oder POST /* usw.). Um die Ablaufverfolgungen für eine bestimmte Seite zu finden, suchen Sie nach dem url.path Attribut des Anfragebereichs oder fügen Sie Ihre eigenen Attribute hinzu, wie in Beispiel 3 dargestellt.

Beispiele examples

Beispiel 1: Verfolgen eines teuren Vorgangs trace-operation

Was Sie erreichen möchten trace-operation-goal

Die WKND-Bildlisten-Komponente (wknd/components/image-list) zeigt eine Liste von Seiten mit jeweils dem ersten Bild an. Um dieses Bild zu finden, führt das Sling-Modell ImageListImpl für jedes Element in der Liste eine QueryBuilder-Abfrage aus. In AEMs eigenen Bereichen werden diese Abfragen bereits angezeigt: Auf der WKND-Magazinseite, auf der fünf Artikel aufgelistet sind, enthält der Trace fünf JCR query Bereiche unter dem HTL-Bereich der Bildliste. Sie zeigen nicht an, für welches Listenelement jede Abfrage war, ob ein Bild gefunden wurde oder wie viel Zeit mit der Verarbeitung der Ergebnisse verbracht wurde. Der ursprüngliche Code synchronisierte die Abfrage mit System.currentTimeMillis() und schrieb das Ergebnis in einen DEBUG Protokolleintrag, der in der Produktion nicht verfügbar ist. Jede Abfrage soll in der Ablaufverfolgung als benannter Vorgang mit diesem Kontext angezeigt werden.

Der Code trace-operation-code

Erstellen Sie ImageListImpl.findPageComponentResources() einen Bereich um die Abfrage:

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;

// ... build the QueryBuilder parameters, as before

final Span span = WkndTelemetry.TRACER.spanBuilder("ImageList.findPageComponentResources")
        .setAttribute("wknd.query.path", page.getContentResource().getPath())
        .setAttribute("wknd.query.resource_type", slingResourceType)
        .setAttribute("wknd.query.limit", limit)
        .startSpan();

try (Scope ignored = span.makeCurrent()) {
    // ... run the query and collect the resources, as before

    span.setAttribute("wknd.query.result_count", componentResources.size());
} catch (RuntimeException e) {
    span.recordException(e);
    span.setStatus(StatusCode.ERROR, "Image List query failed");
    throw e;
} finally {
    span.end();
}

return componentResources;
  • makeCurrent() macht Ihren Bereich zum übergeordneten Element aller Vorgänge, die innerhalb des Blocks ausgeführt werden, einschließlich der Bereiche, die AEM für die Repository-Abfrage erstellt.
  • Rufen Sie end() immer in einem finally auf. Ein nicht beendeter Bereich wird nie exportiert.
  • Geben Sie der span einen festen Namen, der den Vorgang beschreibt, und legen Sie unterschiedliche Werte, wie z. B. Pfade, in Attributen fest.

Das Ergebnis trace-operation-outcome

Auf der Seite WKND-Magazin , die fünf Artikel auflistet, enthält die Spur jetzt fünf ImageList.findPageComponentResources Bereiche innerhalb der Bildliste, einen für jedes Listenelement. Jede ist die übergeordnete Komponente des JCR query , den AEM für seine Abfrage erstellt:

AEM component: wknd/components/image-list
└─ HTL: apps.wknd.components.image__002d__list.image__002d__list__002e__html
   ├─ ImageList.findPageComponentResources        your span
   │  └─ JCR query                                AEM
   ├─ ImageList.findPageComponentResources
   │  └─ JCR query
   └─ ...                                         three more

Jeder Ihrer Bereiche verfügt über den Instrumentationsbereich com.adobe.aem.guides.wknd und die folgenden Attribute:

Attribut
Beispielwert
wknd.query.path
/content/wknd/us/en/magazine/arctic-surfing/jcr:content
wknd.query.resource_type
wknd/components/image
wknd.query.limit
1
wknd.query.result_count
1

Sie können jetzt für jedes Listenelement sehen, nach welcher Seite die Abfrage gesucht hat, ob ein Bild gefunden wurde (wknd.query.result_count ist 0, wenn dies nicht der Fall war) und wie lange die gesamte Suche gedauert hat, einschließlich der Verarbeitung der Ergebnisse. Auf der Seite „WKND-Magazin“ dauert jede Suche etwa 6,5 Millisekunden, wovon die Repository-Abfrage selbst etwa 3,5 benötigt: Die Hälfte der Zeit geht in die Verarbeitung der Ergebnisse, die in AEM eigenen Bereichen nicht angezeigt werden. Da die Anzahl der Abfragen mit der Länge der Liste zunimmt, können Sie auch sehen, wie viel der Rendering-Zeit der Komponente die Suchvorgänge verzeichnen.

Beispiel 2: Verfolgen einer Methode mit einer Anmerkung with-span

Was Sie erreichen möchten with-span-goal

Das WKND-SocialImageImpl wird auf jeder Seite ausgeführt, um das og:image-Meta-Tag auszufüllen. Wenn ein Autor kein vorgestelltes Bild festgelegt hat, durchsucht das Modell den Inhaltsbaum der Seite, um das erste Bild zu finden, und besucht bis zu 500 Ressourcen. Sie möchten wissen, wie oft dieser Spaziergang läuft und wie viel von dem Baum er besucht, ohne die Methode umzustrukturieren.

Der Code with-span-code

Kommentieren Sie die Methode mit @WithSpan:

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.annotations.WithSpan;

@WithSpan("SocialImage.resolveFromFirstImageOnPage")
protected boolean resolveFromFirstImageOnPage() {
    Resource contentResource = currentPage.getContentResource();
    if (contentResource == null) {
        return false;
    }

    int[] visitedCount = new int[]{0};
    Resource firstImage = findFirstImage(contentResource, 0, visitedCount);

    // Span.current() is the span that @WithSpan started for this method.
    Span.current().setAttribute("wknd.social_image.nodes_visited", visitedCount[0]);
    Span.current().setAttribute("wknd.social_image.walk_truncated", visitedCount[0] > MAX_NODES_TO_VISIT);

    // ... use firstImage, as before
}
  • Der Agent startet bei jeder Ausführung der Methode eine Spanne und beendet sie, wenn die Methode eine Ausnahme zurückgibt oder auslöst.
  • @WithSpan arbeitet mit öffentlichen, geschützten und privaten Methoden.
  • Um einen Methodenparameter als Attribut aufzuzeichnen, kommentieren Sie den Parameter mit @SpanAttribute, z. B. void applyTemplate(@SpanAttribute("wknd.page.template") String template).
  • Die Anmerkung wird nur dort wirksam, wo der Agent ausgeführt wird. In der lokalen AEM SDK und in Modultests wird die Methode unverändert ausgeführt.

Das Ergebnis with-span-outcome

Ein SocialImage.resolveFromFirstImageOnPage wird nur in den Spuren von Seiten angezeigt, die kein vorgestelltes Bild haben:

Attribut
Beispielwert
wknd.social_image.nodes_visited
21
wknd.social_image.walk_truncated
false
code.namespace
com.adobe.aem.guides.wknd.core.models.impl.SocialImageImpl (vom Agenten hinzugefügt)
code.function
resolveFromFirstImageOnPage (vom Agenten hinzugefügt)

Suchen Sie nach diesem span-Namen, um die Seiten aufzulisten, die ein vorgestelltes Bild benötigen. Wenn wknd.social_image.walk_truncated true ist, wurde der Spaziergang bei 500 Ressourcen gestoppt und die Seite hat möglicherweise überhaupt kein soziales Bild.

Von @WithSpan erstellte Spannen enthalten den Instrumentierungsbereich (io.opentelemetry.opentelemetry-instrumentation-annotations-1.16) des Agenten, nicht Ihren.

Beispiel 3: Geschäftskontext zur aktuellen Spanne hinzufügen current-span

Was Sie erreichen möchten current-span-goal

Sie möchten Spuren nach der Tatsache filtern, dass Ihr Code weiß, woher das soziale Bild der Seite stammt, ohne einen weiteren Bereich zu erstellen.

Der Code current-span-code

Fügen Sie in SocialImageImpl dem Bereich, der bereits aktiv ist, ein Attribut hinzu:

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.Span;

private static final AttributeKey<String> IMAGE_SOURCE = AttributeKey.stringKey("wknd.social_image.source");

@PostConstruct
protected void init() {
    if (currentPage == null) {
        return;
    }

    final String source;
    if (resolveFromFeaturedImage()) {
        source = "featured_image";
    } else if (resolveFromFirstImageOnPage()) {
        source = "first_image_on_page";
    } else {
        source = "none";
    }

    Span.current().setAttribute(IMAGE_SOURCE, source);
}
  • Span.current() gibt den innersten aktiven Bereich zurück, unabhängig davon, ob er in AEM oder vom Code erstellt wurde. Bei einem Sling-Modell, das aus HTL geladen wird, ist es die Spanne des HTL-Skripts, das das Modell geladen hat.
  • Wenn kein Bereich aktiv ist, führt der Aufruf zu nichts.
  • Durch die Definition AttributeKey Konstanten bleiben Attributnamen im gesamten Code gleich.

Das Ergebnis current-span-outcome

Der Bereich des customheaderlibs.html der Seite, in dem WKND dieses Modell lädt, enthält wknd.social_image.source mit dem Wert featured_image, first_image_on_page oder none. Suchen Sie nach Spuren, bei denen wknd.social_image.source none ist, um die Seiten zu finden, die ohne ein Social-Media-Bild veröffentlicht wurden.

Auf der WKND-Website meldet jede Seite first_image_on_page oder none: Keine Seite legt ein vorgestelltes Bild fest, sodass jede Seite für den Inhaltsbaum-Walk von Beispiel 2 bezahlt. Wenn Sie ein vorgestelltes Bild auf den am häufigsten besuchten Seiten festlegen, wird diese Arbeit entfernt.

Beispiel 4: Fehler aufzeichnen record-errors

Was Sie erreichen möchten record-errors-goal

Das WKND-ContentAIAvailabilityImpl überprüft, ob Inhaltskonfigurationen vorliegen, indem eine OSGi-KI-Suche gelesen wird. Wenn die Suche fehlschlägt, behandelt das Modell die Inhalts-KI als nicht konfiguriert und protokolliert eine Warnung. Die Seite wird weiterhin gerendert und die Anfrage ist erfolgreich, sodass der Fehler leicht zu übersehen ist. Sie möchten, dass der Fehler in den Fehleransichten Ihres APM-Anbieters angezeigt wird, die an den fehlgeschlagenen Vorgang angehängt sind.

Der Code record-errors-code

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;

private boolean resolveConfigured() {
    if (configurationAdmin == null) {
        return false;
    }
    final Span span = WkndTelemetry.TRACER.spanBuilder("ContentAIAvailability.resolveConfigured").startSpan();
    // Close the scope in finally, not with try-with-resources: try-with-resources closes it before
    // the catch block runs, and the warning logged there must carry this span's trace and span IDs.
    final Scope scope = span.makeCurrent();
    try {
        Configuration configuration = lookupConfiguration();
        // ... read the API key, as before
        span.setAttribute("wknd.content_ai.configured", isConfigured);
        return isConfigured;
    } catch (IOException e) {
        span.recordException(e);
        span.setStatus(StatusCode.ERROR, "Content AI configuration lookup failed");
        LOGGER.warn("Unable to determine whether Content AI is configured (PID {})", CONTENT_AI_CLIENT_PID, e);
        return false;
    } finally {
        scope.close();
        span.end();
    }
}
  • recordException() fügt ein exception Ereignis zum Bereich hinzu, mit Ausnahme von Typ, Nachricht und Stacktrace der Ausnahme.
  • setStatus(StatusCode.ERROR, ...) kennzeichnet den Bereich als fehlgeschlagen. Legen Sie sie auf den Bereich fest, der den fehlgeschlagenen Vorgang darstellt. Die Anfrage selbst wird nicht als fehlgeschlagen markiert, da die Komponente wiederhergestellt und die Seite gerendert wurde.

Das Ergebnis record-errors-outcome

Die Ablaufverfolgung enthält einen ContentAIAvailability.resolveConfigured mit dem Status Fehler und der Content AI configuration lookup failed. Der Bereich hat ein exception Ereignis:

Ereignisattribut
Beispielwert
exception.type
java.io.IOException
exception.message
Configuration store unavailable
exception.stacktrace
Die vollständige Stapelablaufverfolgung

Der Bereich wird in Ihrem APM-Provider als Fehler gezählt, sodass er immer dann angezeigt wird, wenn Ihr Provider fehlgeschlagene Vorgänge anzeigt. Der Anfragebereich behält seinen Status, da die Anfrage HTTP 200 zurückgab.

Beispiel 5: Protokolle mit Spuren korrelieren correlate-logs

Was Sie erreichen möchten correlate-logs-goal

Wenn die Suche nach Content-KI in Beispiel 4 fehlschlägt, sollten Sie von der Warnung in Ihren Protokollen zur Verfolgung der Anfrage, die sie erzeugt hat, und zurück gehen.

Der Code correlate-logs-code

Sie benötigen keinen OpenTelemetry-Code. Melden Sie sich wie gewohnt bei SLF4J an und aktivieren Sie Protokolle (logs: true) in Ihrer OpenTelemetry-Konfiguration:

LOGGER.warn("Unable to determine whether Content AI is configured (PID {})", CONTENT_AI_CLIENT_PID, e);

Der Agent fügt jedem Protokolleintrag die Trace- und span-IDs des aktuellen Bereichs hinzu. Da ContentAIAvailabilityImpl protokolliert, während sein Bereich von Beispiel 4 aktuell ist, wird die Warnung mit diesem Bereich verknüpft.

Das Ergebnis correlate-logs-outcome

Ihr APM-Anbieter erhält einen Protokolleintrag wie den folgenden und kann ihn mit seiner Ablaufverfolgung anzeigen:

Feld
Beispielwert
Schweregrad
WARN
Hauptteil
Unable to determine whether Content AI is configured (PID com.adobe.cq.wcm.core.components.internal.services.contentai.ContentAIClientImpl)
Trace-ID und span-ID
Die IDs des ContentAIAvailability.resolveConfigured Bereichs
exception.type, exception.message, exception.stacktrace
Die protokollierte Ausnahme
Instrumentierungsumfang
Der Logger-Name, com.adobe.aem.guides.wknd.core.models.impl.contentai.ContentAIAvailabilityImpl
NOTE
Es werden nur Protokolleinträge auf WARN und höher gesendet. INFO- und DEBUG sind nicht zulässig. Verlassen Sie sich bei der Produktionsdiagnose nicht auf sie: Zeichnen Sie die Informationen stattdessen als span-Attribut auf.

Best Practices best-practices

  • Name erstreckt sich über Vorgänge, nicht über Daten. Verwenden Sie Namen wie ImageList.findPageComponentResources und legen Sie unterschiedliche Werte wie Pfade und IDs in Attributen fest.
  • Stellen Sie Ihren eigenen Attributnamen voran mit einem Namespace für Ihr Projekt, z. B. wknd.. Dadurch werden Konflikte mit den OpenTelemetry-Semantikkonventionen und mit Namen, die AEM verwendet, vermieden. Verwenden Sie nicht das aem. Präfix, das für AEM reserviert ist.
  • Tragen Sie keine personenbezogenen Daten oder in span-Namen, Attributen, Ereignissen oder Protokollnachrichten auf. Dazu gehören Namen, E-Mail-Adressen, IP-Adressen, Token und Abfragezeichenfolgen, die diese enthalten können.
  • Fügen Sie Bereiche für Vorgänge hinzu, nicht für Iterationen. Beispiel: Beispiel 2 erstellt einen Bereich für die Inhaltsstruktur und zeichnet die Anzahl der besuchten Ressourcen als Attribut auf, anstatt für jede Ressource einen Bereich zu erstellen. AEM erstellt bereits viele Bereiche für eine einzelne Seite (etwa 260 für die WKND-Magazinseite), und jeder Bereich erhöht das Volumen, das Ihr APM-Anbieter aufnimmt.
  • Einmalige Erstellung von Tracern deren Wiederverwendung.
  • Beenden Sie jede Spanne in einem finally und schließen Sie jede Scope des Threads, der sie geöffnet hat.
  • Übergeben Sie den Kontext an Threads, die Sie selbst starten,. B. mit Context.current().wrap(runnable), sodass die Arbeit an einem anderen Thread derselben Spur hinzugefügt wird.
  • Für Arbeiten außerhalb einer Anforderung wird eine neue Ablaufverfolgung erwartet. Code, der in einem Sling-Auftrag, einer geplanten Aufgabe oder einem Ereignis-Listener ausgeführt wird, hat keine Anfragespanne. Die Bereiche, die Sie dort erstellen, beginnen ihre eigenen Spuren, eine für jeden Lauf.

Testen der Instrumentierung test

  • Modultests: Ohne den Agenten führt die API keine Aktionen durch, sodass die Übergabe vorhandener Modultests unverändert bleibt.
  • Build: Führen Sie mvn clean install lokal aus. Der AEM Analyzer, den Cloud Manager ebenfalls ausführt, prüft, ob die Importe Ihres Bundles aufgelöst werden können.
  • Bundle-Inhalte: Überprüfen Sie, ob Ihr Bundle die vollständige API enthält, wie in Schritt 2 beschrieben. Beispielsweise müssen unzip -l core/target/<your-core-bundle>.jar | grep "io/opentelemetry/api/baggage/" Klassen auflisten und die META-INF/MANIFEST.MF des Bundles darf kein io.opentelemetry importieren.
  • Ihr APM-Anbieter: Stellen Sie in einer Entwicklungsumgebung bereit, in der OpenTelemetry aktiviert ist, fordern Sie eine Seite an, auf der Ihr Code ausgeführt wird, und suchen Sie bei Ihrem APM-Anbieter nach Ihren span-Namen oder nach dem Instrumentierungsbereich, den Sie in Schritt 3 ausgewählt haben.

Fehlerbehebung troubleshooting

Symptom
Ursache und Lösung
Der Cloud Manager-Build schlägt mit [api-regions-exportsimports] ... is importing package(s) [io.opentelemetry.api.incubator, io.opentelemetry.api.incubator.internal, io.opentelemetry.sdk.autoconfigure] in start level 20 but no bundle is exporting these for that start level. fehl
Ihr Bundle importiert optionale OpenTelemetry-Pakete. Fügen Sie !io.opentelemetry.* am Anfang der Import-Package hinzu. Siehe Schritt 2.
Ihr Bundle ist mit missing requirement ... osgi.wiring.package=io.opentelemetry.api.incubator installiert, aber nicht aktiv.
Dieselbe Ursache und Lösung wie in der vorherigen Zeile.
@WithSpan Bereiche werden angezeigt, Ihre anderen Bereiche und die Attribute, die Sie mit Span.current() festgelegt haben, jedoch nicht.
Ihr Bundle enthält nur einen Teil der API, sodass der Agent Ihre Kopie davon nicht verbindet. Fügen Sie -includepackage: io.opentelemetry.* hinzu. Siehe Schritt 2.
Keiner Ihrer Bereiche wird angezeigt.
Überprüfen Sie, ob OpenTelemetry für die Umgebung aktiviert ist und ob seit der Bereitstellung des Codes eine Bereitstellung ausgeführt wurde. Vergewissern Sie sich, dass der Code-Pfad ausgeführt und alle Zeitspannen beendet wurden.
Ihre Bereiche werden als separate Spuren anstelle innerhalb der Anfrage angezeigt.
Der Bereich wurde in einem anderen Thread ohne Kontext der Anfrage erstellt. Übergeben Sie den Kontext an den Thread, z. B. mit Context.current().wrap(runnable).
Ihre Protokolleinträge werden nicht angezeigt.
Es werden nur Einträge auf WARN und höher gesendet und nur, wenn Protokolle in Ihrer Konfiguration aktiviert sind.
recommendation-more-help
experience-manager-cloud-service-help-main-toc