Instrumentation personnalisée avec OpenTelemetry custom-instrumentation

Lorsque la fonction OpenTelemetry est activée pour votre environnement, AEM as a Cloud Service effectue le suivi de chaque requête et exporte automatiquement les mesures JVM, HTTP et AEM. Cette télémétrie décrit AEM. Cela indique qu’une page a mis 900 millisecondes pour s’afficher et quels composants elle a rendus. Il ne peut pas afficher ce que faisait votre propre code, par exemple pour quel élément de liste une requête de référentiel était destinée et s’il a trouvé quelque chose, ou quelles pages sont renvoyées à une recherche coûteuse parce qu’un auteur a oublié un champ.

Vous pouvez ajouter ces connaissances vous-même avec l’API OpenTelemetry. Les étendues et attributs créés par votre code se déplacent avec la télémétrie automatique : même nom de service, même traitement, même fournisseur APM. Vous ne configurez pas de point d’entrée, d’informations d’identification ou d’exportateur dans votre code.

Si vous découvrez OpenTelemetry sur AEM as a Cloud Service, commencez par le tutoriel Observability via OpenTelemetry pour découvrir comment il fonctionne. Suivez ensuite Configuration d’OpenTelemetry pour obtenir des informations sur les applications AEM afin de l’activer pour votre environnement.

Les exemples de cette page instrumentent le site de référence WKND. Chaque exemple décrit ce que vous souhaitez accomplir, le code à ajouter et le résultat attendu de la part de votre fournisseur APM. Le code instrumenté complet, y compris les tests unitaires qui s’appuient sur les étendues, se trouve sur la branche tutorial/otel-custom-instrumentation du référentiel WKND.

NOTE
L’instrumentation personnalisée nécessite l’activation d’OpenTelemetry pour votre environnement. Voir Configuration de l’intégration.

Fonctionnement des instruments personnalisés how-it-works

  • L’agent Java OpenTelemetry qu’Adobe exécute dans votre environnement AEM contient le SDK et les exportateurs OpenTelemetry. Votre code dépend uniquement de l’API OpenTelemetry API.
  • Lorsque votre code appelle GlobalOpenTelemetry, l’agent le connecte à sa propre implémentation. Vos plages font partie de la trace de la requête qui les exécute et votre télémétrie est exportée avec le reste de la télémétrie de votre environnement.
  • Lorsque l’agent n’est pas présent (le SDK AEM local, les tests unitaires ou un environnement sans OpenTelemetry activé), l’API ne fait rien, à un coût négligeable. Vous pouvez déployer le même code dans chaque environnement.
Ce que vous ajoutez
Comment
Envoyé à votre fournisseur APM
Spans
Une Tracer, ou l’annotation @WithSpan
Oui
Attributs, événements et statut d’erreur sur les étendues
L’API Span
Oui
Entrées de journal corrélées aux traces
Journalisation de vos SLF4J existants
Oui, au niveau WARN et supérieur, lorsque les journaux sont activés
NOTE
Les mesures personnalisées, telles que les compteurs et les histogrammes créés par votre code, sont prévues pour une prochaine version.

Configurer votre projet set-up-project

Étape 1 : ajouter l’API OpenTelemetry add-api

Ajoutez l’API OpenTelemetry et les annotations d’instrumentation à la section dependencyManagement du pom.xml parent de votre projet, avec la portée 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>

Ajoutez ensuite les deux dépendances, sans versions, au pom.xml de chaque lot qui les utilise, par exemple 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>

Utilisez opentelemetry-api 1.61.0 et opentelemetry-instrumentation-annotations 2.27.0, ou des versions antérieures. Elles correspondent à l’agent Java OpenTelemetry qu’AEM as a Cloud Service exécute et les versions ultérieures de l’agent continuent de les prendre en charge. Les fonctionnalités d’API ajoutées après la version prise en charge par l’agent n’ont aucun effet.

Étape 2 : incorporation de l’API dans votre lot embed-api

AEM as a Cloud Service n’exporte pas les packages d’API OpenTelemetry, de sorte que chaque lot qui utilise l’API doit contenir sa propre copie. Ajoutez les instructions suivantes à la configuration de liaison de votre lot. Avec l’archétype de projet ​, il s’agit de la configuration bnd-maven-plugin dans core/pom.xml. Conservez toutes les entrées de votre instruction Import-Package.

Import-Package: !io.opentelemetry.*,javax.annotation;version=0.0.0,*
-includepackage: io.opentelemetry.*
Instruction
Pourquoi est-ce nécessaire ?
!io.opentelemetry.* début Import-Package
L’API fait référence à des packages OpenTelemetry facultatifs qu’AEM ne fournit pas et ne les charge que s’ils sont présents. Sans cette exclusion, votre lot importe ces packages, il ne peut pas démarrer et la création de Cloud Manager échoue. Voir Dépannage.
-includepackage: io.opentelemetry.*
Copie l’API complete dans votre lot. L’agent connecte la copie de l’API de votre lot à sa propre implémentation uniquement lorsque l’API entière est présente. Si vous incorporez uniquement les packages auxquels votre code fait référence, par exemple avec -conditionalpackage, vos étendues et attributs sont ignorés sans erreur.

Chaque lot qui utilise l’API incorpore sa propre copie et l’agent connecte chaque copie séparément.

CAUTION
N’ajoutez pas le SDK OpenTelemetry, un exportateur ou le module de configuration automatique de SDK à votre projet, et ne créez pas votre propre instance de OpenTelemetrySdk ou n’appelez pas de GlobalOpenTelemetry.set(). La télémétrie envoyée de cette manière contourne l’agent, la suppression des détails de l’infrastructure Cloud Service décrite dans Quelles données sont envoyées ​ et le point d’entrée que vous avez configuré.

Étape 3 : créer un traceur create-tracer

Créez une Tracer pour votre base de code et réutilisez-la partout. Dans WKND, une petite classe la contient :

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() {
    }
}

Le nom de la portée s’affiche sur chaque étendue que vous créez par l’intermédiaire de ce traceur, sous la forme de portée d’instrumentation (ou nom de bibliothèque). Utilisez un nom qui identifie votre code, tel que le package Java de base de votre projet.

Emplacement de vos étendues where-spans-appear

Sur AEM as a Cloud Service, une requête de page produit déjà des plages à partir d’AEM. Les plages créées par votre code y sont ajoutées. Par exemple, voici le chemin d’accès au composant Liste d’images dans une trace de la page WKND Magazine :

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

Lorsqu’un composant effectue le rendu, la portée de son script HTL est la portée actuelle. Un modèle Sling que le script charge avec data-sly-use s’exécute à l’intérieur de cette étendue, de sorte que les étendues créées par le modèle deviennent ses enfants.

Chaque plage de requêtes est nommée GET /* (ou POST /*, etc.). Pour rechercher les traces d’une page particulière, recherchez l’attribut url.path de l’étendue de la requête ou ajoutez vos propres attributs, comme indiqué dans Exemple 3.

Exemples examples

Exemple 1 : suivi d’une opération coûteuse trace-operation

Ce que vous souhaitez accomplir trace-operation-goal

Le composant Liste d’images WKND (wknd/components/image-list) affiche une liste de pages, chacune avec sa première image. Pour trouver cette image, son modèle Sling, ImageListImpl, exécute une requête QueryBuilder pour chaque élément de la liste. Les propres étendues AEM affichent déjà ces requêtes : sur la page du magazine WKND, qui répertorie cinq articles, la trace contient cinq étendues de JCR query sous l’étendue HTL de la liste d’images. Elles n’indiquent pas à quel élément de liste chaque requête correspondait, si elle a trouvé une image ou le temps passé à traiter les résultats. Le code d’origine a minuté la requête avec System.currentTimeMillis() et a écrit le résultat dans une entrée de journal DEBUG, qui n’est pas disponible en production. Vous souhaitez que chaque requête apparaisse dans la trace sous la forme d’une opération nommée, avec ce contexte.

Le code trace-operation-code

Dans ImageListImpl.findPageComponentResources(), créez une étendue autour de la requête :

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() fait de votre étendue le parent de tout ce qui s’exécute à l’intérieur du bloc, y compris les étendues créées par AEM pour la requête de référentiel.
  • Appelez toujours end() dans un bloc de finally. Une étendue non terminée n’est jamais exportée.
  • Attribuez à la plage un nom fixe qui décrit l’opération et placez des valeurs variables, telles que des chemins, dans les attributs.

Le résultat trace-operation-outcome

Sur la page du magazine WKND, qui répertorie cinq articles, la trace contient désormais cinq plages d’ImageList.findPageComponentResources dans la liste d’images, une pour chaque élément de liste. Chacune d’elles est le parent de l’étendue de JCR query créée par AEM pour sa requête :

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

Chacune de vos plages possède la portée d’instrumentation com.adobe.aem.guides.wknd et les attributs suivants :

Attribut
Exemple de valeur
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

Vous pouvez désormais voir, pour chaque élément de liste, quelle page la requête a recherchée, si elle a trouvé une image (wknd.query.result_count est 0 alors que ce n’est pas le cas) et combien de temps a pris l’ensemble de la recherche, y compris le traitement des résultats. Sur la page du magazine WKND, chaque recherche prend environ 6,5 millisecondes, dont environ 3,5 millisecondes pour la requête de référentiel elle-même : la moitié du temps est consacrée au traitement des résultats, ce que les plages propres à AEM n’affichent pas. Étant donné que le nombre de requêtes augmente avec la longueur de la liste, vous pouvez également voir le temps de rendu du composant pris en compte par les recherches.

Exemple 2 : suivi d’une méthode avec une annotation with-span

Ce que vous souhaitez accomplir with-span-goal

Le modèle de SocialImageImpl de WKND s’exécute sur chaque page pour renseigner la balise meta og:image. Si un auteur n’a pas défini d’image en vedette, le modèle parcourt l’arborescence de contenu de la page pour trouver la première image, visitant jusqu’à 500 ressources. Vous voulez savoir à quelle fréquence cette marche court, et quelle partie de l’arbre elle visite, sans restructurer la méthode.

Le code with-span-code

Annotez la méthode avec @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
}
  • L’agent démarre une plage chaque fois que la méthode s’exécute et la termine lorsque la méthode renvoie ou renvoie une exception.
  • @WithSpan fonctionne sur des méthodes publiques, protégées et privées.
  • Pour enregistrer un paramètre de méthode en tant qu’attribut, annotez le paramètre avec @SpanAttribute, par exemple void applyTemplate(@SpanAttribute("wknd.page.template") String template).
  • L’annotation ne prend effet que là où l’agent s’exécute. Dans le SDK AEM local et dans les tests unitaires, la méthode s’exécute inchangée.

Le résultat with-span-outcome

Une étendue de SocialImage.resolveFromFirstImageOnPage apparaît uniquement dans les traces des pages qui n’ont pas d’image en vedette :

Attribut
Exemple de valeur
wknd.social_image.nodes_visited
21
wknd.social_image.walk_truncated
false
code.namespace
com.adobe.aem.guides.wknd.core.models.impl.SocialImageImpl (ajoutée par l’agent)
code.function
resolveFromFirstImageOnPage (ajoutée par l’agent)

Recherchez ce nom d’étendue pour répertorier les pages qui ont besoin d’une image en vedette. Si wknd.social_image.walk_truncated est true, la marche s’est arrêtée à 500 ressources et la page peut ne pas avoir d’image sociale du tout.

Les plages créées par @WithSpan portent la portée d’instrumentation de l’agent (io.opentelemetry.opentelemetry-instrumentation-annotations-1.16), et non la vôtre.

Exemple 3 : ajouter un contexte métier à la plage actuelle current-span

Ce que vous souhaitez accomplir current-span-goal

Vous souhaitez filtrer les traces en fonction d’un fait que votre code connaît, ici, l’origine de l’image du réseau social de la page, sans créer d’autre étendue.

Le code current-span-code

Dans SocialImageImpl, ajoutez un attribut à l’étendue déjà active :

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() renvoie la plage la plus active, qu’AEM ou votre code l’ait créée. Pour un modèle Sling chargé à partir de HTL, c’est l’étendue du script HTL qui a chargé le modèle.
  • Si aucune plage n’est active, l’appel ne fait rien.
  • La définition de constantes AttributeKey une fois permet de conserver la cohérence des noms d’attributs dans votre code.

Le résultat current-span-outcome

L’étendue du script de customheaderlibs.html de la page, où WKND charge ce modèle, transporte les wknd.social_image.source avec la valeur featured_image, first_image_on_page ou none. Recherchez les traces où wknd.social_image.source est none pour trouver les pages publiées sans image de réseau social.

Sur le site WKND, chaque page indique first_image_on_page ou none : aucune page ne définit une image en vedette, de sorte que chaque page paie pour la présentation de l’arborescence de contenu à partir de Exemple 2. La définition d’une image en vedette sur les pages les plus visitées supprime ce travail.

Exemple 4 : enregistrement d’une erreur record-errors

Ce que vous souhaitez accomplir record-errors-goal

Le modèle ContentAIAvailabilityImpl de WKND vérifie si la Recherche optimisée par l’IA de contenu est configurée en lisant une configuration OSGi. Si la recherche échoue, le modèle traite l’IA dédiée au contenu comme non configurée et consigne un avertissement. La page est toujours rendue et la requête réussit. Il est donc facile de manquer l’échec. Vous souhaitez que l’échec apparaisse dans les vues d’erreur de votre fournisseur APM, associées à l’opération ayant échoué.

Le 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() ajoute un événement exception à l’étendue, avec le type d’exception, le message et la trace de la pile.
  • setStatus(StatusCode.ERROR, ...) marque l’étendue comme ayant échoué. Définissez-le sur la plage qui représente l’opération qui a échoué. La requête elle-même n’est pas marquée comme ayant échoué, car le composant a été récupéré et la page rendue.

Le résultat record-errors-outcome

La trace contient une étendue ContentAIAvailability.resolveConfigured avec le statut Erreur et la description Content AI configuration lookup failed. L’étendue comporte un événement exception :

Attribut d’événement
Exemple de valeur
exception.type
java.io.IOException
exception.message
Configuration store unavailable
exception.stacktrace
La trace de la pile complète

L’étendue compte comme une erreur dans votre fournisseur APM. Elle apparaît donc partout où votre fournisseur affiche des opérations ayant échoué. L’étendue de la requête conserve son statut, car la requête a renvoyé un HTTP 200.

Exemple 5 : corréler les logs avec les traces correlate-logs

Ce que vous souhaitez accomplir correlate-logs-goal

Lorsque la recherche de l’IA dédiée au contenu dans Exemple 4 échoue, vous devez passer de l’avertissement dans vos journaux à la trace de la requête qui l’a générée, puis revenir en arrière.

Le code correlate-logs-code

Vous n’avez pas besoin de code OpenTelemetry. Connectez-vous avec SLF4J comme d’habitude et activez les journaux (logs: true) dans votre configuration OpenTelemetry :

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

L’agent ajoute les identifiants de suivi et d’étendue de l’étendue actuelle à chaque entrée du journal. Étant donné que ContentAIAvailabilityImpl enregistre tant que son étendue de Exemple 4 est actuelle, l’avertissement est lié à cette étendue.

Le résultat correlate-logs-outcome

Votre fournisseur APM reçoit une entrée de journal telle que la suivante et peut l’afficher avec sa trace :

Champ
Exemple de valeur
Gravité
WARN
Corps
Unable to determine whether Content AI is configured (PID com.adobe.cq.wcm.core.components.internal.services.contentai.ContentAIClientImpl)
Identifiant de suivi et identifiant d’étendue
Identifiants de l’étendue ContentAIAvailability.resolveConfigured
exception.type, exception.message, exception.stacktrace
Exception consignée
Portée de l’instrumentation
Le nom de l’enregistreur, com.adobe.aem.guides.wknd.core.models.impl.contentai.ContentAIAvailabilityImpl
NOTE
Seules les entrées de journal de niveau WARN et supérieur sont envoyées. Les entrées INFO et DEBUG ne le sont pas. Ne vous fiez pas à eux pour les diagnostics de production : enregistrez les informations en tant qu’attribut d’étendue à la place.

Bonnes pratiques best-practices

  • Le nom s’étend après les opérations, et non sur les données. Utilisez des noms tels que ImageList.findPageComponentResources et placez des valeurs qui varient, telles que des chemins d’accès et des identifiants, dans les attributs.
  • Préfixez vos propres noms d’attribut avec un espace de noms pour votre projet, tel que wknd.. Cela permet d’éviter les conflits avec les conventions sémantiques OpenTelemetry et avec les noms utilisés par AEM. N’utilisez pas le préfixe aem., qui est réservé à AEM.
  • N’enregistrez pas de données personnelles ou de secrets dans les noms d’étendue, les attributs, les événements ou les messages du journal. Cela inclut les noms, adresses e-mail, adresses IP, jetons et chaînes de requête qui peuvent les contenir.
  • Ajoutez des étendues pour les opérations, et non des itérations. Par exemple, la mention Exemple 2 crée une étendue pour la marche de l’arborescence de contenu et enregistre le nombre de ressources visitées en tant qu’attribut, plutôt que de créer une étendue pour chaque ressource. AEM crée déjà de nombreuses plages pour une seule page (environ 260 pour la page du magazine WKND), et chaque plage s’ajoute au volume ingéré par votre fournisseur APM.
  • Créez des traceurs une seule fois puis réutilisez-les.
  • Terminez chaque étendue dans un bloc de finally, puis fermez chaque Scope du thread qui l’a ouverte.
  • Transmettez le contexte aux threads que vous démarrez vous-même par exemple avec Context.current().wrap(runnable), de sorte que le travail effectué sur un autre thread rejoigne la même trace.
  • Attendez-vous à une nouvelle trace pour le travail en dehors d’une requête. Le code qui s’exécute dans une tâche Sling, une tâche planifiée ou un écouteur d’événement n’a pas de durée de requête. Les plages que vous y créez commencent leurs propres traces, une pour chaque exécution.

Tester votre instrumentation test

  • Tests unitaires : sans l’agent, l’API ne fait rien, de sorte que vos tests unitaires existants continuent à passer inchangés.
  • Build: Exécutez mvn clean install localement. L’analyseur AEM, que Cloud Manager exécute également, vérifie que les importations de votre lot peuvent être résolues.
  • Contenu du bundle : vérifiez que votre bundle contient l’API complète, comme décrit dans Étape 2. Par exemple, unzip -l core/target/<your-core-bundle>.jar | grep "io/opentelemetry/api/baggage/" devez répertorier les classes et le META-INF/MANIFEST.MF du lot ne doit importer aucun package io.opentelemetry.
  • Votre fournisseur APM : effectuez un déploiement dans un environnement de développement pour lequel OpenTelemetry est activé, demandez une page qui exécute votre code et recherchez vos noms d’étendue ou la portée d’instrumentation que vous avez choisie à l’étape 3 dans votre fournisseur APM.

Résolution des problèmes troubleshooting

Symptôme
Cause et solution
La version de Cloud Manager échoue avec [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.
Votre lot importe des packages OpenTelemetry facultatifs. Ajoutez !io.opentelemetry.* au début de la Import-Package. Voir Étape 2.
Votre lot est installé, mais pas actif, avec missing requirement ... osgi.wiring.package=io.opentelemetry.api.incubator.
Même cause et solution que la ligne précédente.
@WithSpan étendues apparaissent, mais pas les autres étendues ni les attributs que vous définissez avec Span.current().
Votre lot ne contient qu’une partie de l’API. L’agent ne connecte donc pas votre copie de celui-ci. Ajoutez -includepackage: io.opentelemetry.*. Voir Étape 2.
Aucune de vos étendues n’apparaît.
Vérifiez que OpenTelemetry est activé pour l’environnement et qu’un déploiement a été exécuté depuis que vous avez déployé votre code. Vérifiez que le chemin d’accès au code s’exécute et que chaque étendue est terminée.
Vos plages apparaissent sous la forme de traces distinctes au lieu de figurer dans la requête.
La plage a été créée sur un autre thread sans le contexte de la requête. Transmettez le contexte au thread, par exemple avec Context.current().wrap(runnable).
Vos entrées de journal n’apparaissent pas.
Seules les entrées de niveau WARN et supérieur sont envoyées, et uniquement lorsque les journaux sont activés dans votre configuration.
recommendation-more-help
experience-manager-cloud-service-help-main-toc