Enregistrement des étendues APM en tant qu'événements JFR

Le traceur APM et l'agent APM prennent en charge l'enregistrement des étendues APM en tant qu'événements JFR.

Actuellement, les versions 11 et ultérieures de JDK sont prises en charge.

Pour plus d'informations sur l'enregistrement des étendues APM en tant qu'événements JFR à l'aide de l'agent APM, reportez-vous à Enregistrement des étendues APM en tant qu'événements JFR sous Provisionnement et déploiement d'agents Java APM sur des serveurs d'applications.

Remarque

JFR (Java Flight Recorder) est un outil de collecte de données de diagnostic et de profilage sur une application Java en cours d'exécution. Pour plus d'informations sur JFR et JMC (Java Mission Control), reportez-vous à JDK Mission Control.

Capture d'événements APM dans des enregistrements JFR

Pour capturer les événements APM dans des enregistrements JFR à l'aide du traceur APM, procédez comme suit :

  1. Assurez-vous que le traceur APM fonctionne correctement.

    Ouvrez l'explorateur de traces et vérifiez que vous pouvez visualiser toutes les traces. Pour plus d'informations sur l'ouverture et l'utilisation de l'explorateur de traces, reportez-vous à Surveillance des traces dans l'explorateur de traces.

  2. Ajoutez au projet Maven une dépendance qui permettra au traceur APM d'ajouter des événements dans les enregistrements JFR réalisés par la JVM Helidon.

    <dependency>
        <groupId>com.oracle.apm.agent.java</groupId>
        <artifactId>apm-java-agent-jfr11</artifactId>
        <version>[1.0.1389,)</version>
    </dependency>
  3. Lancez un enregistrement.

    Pour vérifier que tout fonctionne correctement, vous devez lancer un enregistrement à l'aide de la méthode de votre choix (vous pouvez utiliser l'interface utilisateur de JDK Mission Control ou l'utilitaire de ligne de commande JCMD). Une fois l'enregistrement lancé, les événements de trace apparaissent dans l'interface utilisateur de JDK Mission Control lorsque vous consultez l'enregistrement.

    Pour vérifier que les événements de trace APM sont correctement ajoutés aux enregistrements JFR, connectez-vous à JDK Mission Control et vérifiez que les traces APM apparaissent sous Navigateur d'événements : cliquez sur APM OpenTracing et vérifiez que les événements de trace APM sont visibles.

Configuration d'événements JFR dans le traceur APM

(Facultatif) Il s'agit d'une étape facultative permettant de personnaliser la génération des rapports relatifs aux événements.

Pour simplifier l'analyse des événements d'enregistrement JFR, chaque événement est classé dans une catégorie ou un type d'événement.

Catégorie par défaut

Dans le traceur APM, la catégorie par défaut des événements JFR APM est obtenue à l'aide du contenu de Span Operation Name (dans un champ nommé name au sein de l'étendue). La balise component peut ne pas être renseignée. Elle ne peut donc pas être utilisée comme catégorie par défaut.

Evénements

Les types d'événement permettent d'organiser et de classer les événements dans l'interface utilisateur de JMC. Lorsque le traceur APM obtient une étendue, il peut générer un événement correspondant, mais il doit déterminer le type de l'événement en question.

Exemples de type d'événement : servlet, jdbc et jax-rs.

Configuration du type d'événement

Il existe plusieurs façons de configurer le type ou la catégorie d'un événement. Voici les différents cas d'emploi :

  • Cas 1 : balise component

    Il s'agit de la méthode la plus simple pour classer un événement. Cette méthode est recommandée.

    Dans la plupart des scénarios, l'étendue OpenTracing contient une balise nommée component. La valeur de cette balise component est utilisée pour déterminer le type d'événement.

    Par exemple, reportez-vous à l'étendue suivante :

    {  "id":"e926ff3d06013045",
      "trace-id":"49abd92e69786853e926ff3d06013045",
      "parent-id":"6ef54ec2c524c99a",
      "name":"content-write",
      "ts-micros":1614190751360177,
      "td-micros":219348,
      "attributes":{
        "server":"Helidon SE",
        "http.url":"http://localhost:8079/health",
        "http.status_code":200,
        "component":"helidon-webserver",
        "http.method":"GET",
        "organization":"development"
      },
      "events":[
      ]
    },

    Dans ce cas, le type d'événement helidon-webserver est affecté à l'événement généré car il s'agit de la valeur de la balise component.

  • Cas 2 : autre balise

    Si votre application n'utilise pas la balise component, mais qu'elle utilise une autre balise ou qu'il existe une bibliothèque dans laquelle elle génère des balises, vous pouvez configurer le traceur APM de façon à lire le type d'événement à partir d'une autre balise.

    Par exemple, dans l'étendue suivante, vous pouvez lire le type d'événement à partir de la balise nommée span.type :

    {  "id":"e926ff3d06013045",
      "trace-id":"49abd92e69786853e926ff3d06013045",
      "parent-id":"6ef54ec2c524c99a",
      "name":"content-write",
      "ts-micros":1614190751360177,
      "td-micros":219348,
      "attributes":{
        "server":"Helidon SE",
        "http.url":"http://localhost:8079/health",
        "http.status_code":200,
        "span.type":"helidon-webserver",
        "http.method":"GET",
        "organization":"development"
      },
      "events":[
      ]
    },

    Dans ce cas, vous pouvez demander au traceur APM de lire le type d'événement à partir de la balise span.type en utilisant la propriété système suivante lors du démarrage de l'application Java :

    java -Dcom.oracle.apm.agent.jfr.category.tag=span.type ...
  • Cas 3 : utilisation du nom d'opération lorsqu'aucune balise n'est disponible

    Si votre application n'utilise aucune balise possédant des catégories utiles, vous pouvez utiliser la valeur Operation Name pour déterminer le type d'événement. Cette méthode n'est toutefois pas recommandée.

    Le système JFR a besoin que le nom du type d'événement soit un identificateur Java valide, mais la valeur Operation Name comporte souvent des espaces et d'autres caractères non autorisés. Le traceur APM convertit la valeur Operation Name en identificateur valide en remplaçant tous les caractères non autorisés par un trait de soulignement.

    java -Dcom.oracle.apm.agent.jfr.category.default=ORACLE_APM_USE_SPAN_OPERATION_NAMES
    Remarque

    La valeur Operation Name n'est utilisée que si la balise de catégorie est manquante ou vide.

    Cette solution n'est pas simple car la valeur Operation Name peut contenir des jetons uniques tels que des ID. Dans ce cas, chaque événement devient son propre type d'événement. En outre, la conversion de la valeur Operation Name en un identificateur valide entraîne d'autres problèmes lors de la configuration du type d'événement pour configurer les champs nécessaires à l'événement. De plus, vous devrez effectuer la configuration en fonction de la valeur Operation Name convertie, sous peine de devoir configurer plusieurs variantes de la valeur Operation Name en suivant la même procédure.

  • Cas 4 : aucune balise n'est disponible et tous les noms d'opération sont uniques

    Dans ce cas, aucune information n'est disponible pour classer les types d'événement. Il s'agit du scénario le plus défavorable dans lequel tous les événements sont classés dans le même type d'événement, ou dans lequel ils sont chacun classés dans un type unique en cas de configuration à l'aide du scénario du cas d'emploi 3 ci-dessus. Tout ce que vous pouvez faire, c'est choisir le nom du type d'événement par défaut, qui peut être configuré comme indiqué ci-dessous.

    java -Dcom.oracle.apm.agent.jfr.category.default=Unknown
    Remarque

    La valeur par défaut ne sera utilisée que si la balise de catégorie est manquante ou vide.

    Dans ce cas, tous les événements sont classés dans le type d'événement nommé Unknown ou toute valeur personnalisée sélectionnée.

Champs du type d'événement

Pour chaque type d'événement, vous pouvez ajouter des champs contenant des données propres à cet événement.

La liste des champs pouvant être ajoutés au type d'événement doit être configurée dans le fichier ACML et uniquement après avoir rendu possible la publication de ces champs dans JFR. Pour chaque champ, vous devez renseigner les informations suivantes :
  • Nom.
  • Type (nombre entier, nombre à virgule flottante, chaîne, thread).
  • Libellé.
  • Description.
Par exemple, reportez-vous à la définition de champ suivante pour traceID :
- name: traceID
  type: String
  label: New Trace ID
  description: New Opentracing Trace ID

Création d'un fichier ACML

Cette étape est facultative. Si les paramètres par défaut fonctionnent comme prévu, vous pouvez ignorer cette étape.

Vous pouvez créer un fichier ACML si vous souhaitez modifier les paramètres par défaut et personnaliser les enregistrements.

L'exemple suivant présente le format d'un fichier ACML qui configure la journalisation des événements dans JFR en écrasant les paramètres par défaut intégrés du conteneur de microservices Helidon :

caseSensitiveFieldName: false
recordCallStack: true

eventTypes:
  helidon-webserver:
    name: helidon-webserver
    label: Helidon Webserver Events
    description: All events based on helidon webserver
    recordCallStack: true
    # All fields must be provided here.
    # Fields are NOT incremental since that would make them impossible to remove 
    fields:
      - name: traceID
        type: String
        label: New Trace ID
        description: New Opentracing Trace ID
      - name: spanID
        type: String
        label: New Span ID
        description: New Opentracing Span ID
      - name: http.url
        type: String
        label: New HTTP URL
        description: The New URL for the HTTP endpoint being hit
      - name: organization
        type: String
        label: Organization
        description: The New Organization value of this call
      - name: startThread
        type: Thread
        label: Start Thread
        description: The thread on which this event started
      - name: http.status_code
        type: int
        label: Status Code
        description: The HTTP Response status code
      - name: http.method
        type: String
        label: HTTP Method
        description: The HTTP Method

Vous pouvez utiliser le format de fichier ACML ci-dessus lorsque vous utilisez l'agent APM et le traceur APM. Dans le cas du traceur APM, ce format fonctionne pour n'importe quel conteneur, par exemple Helidon, Spring Boot ou Micronaut.

Foire aux questions

  1. Lorsque les deux paramètres com.oracle.apm.agent.jfr.category.tag et com.oracle.apm.agent.jfr.category.default sont fournis, lequel est prioritaire ?

    Si une valeur leur est affectée à tous les deux, nous recherchons d'abord la balise de catégorie dans l'étendue. Si elle est trouvée, elle est utilisée. Si elle est manquante, la valeur par défaut est utilisée.

  2. Pour le traceur APM, un fichier de configuration est-il obligatoire ? Puis-je simplement spécifier les propriétés sans fichier ?

    Le fichier de configuration n'est pas obligatoire. Si la valeur par défaut vous convient, vous n'avez pas besoin d'un fichier de configuration et vous pouvez toujours spécifier les propriétés.

  3. Pourquoi les entrées semblent-elles être dupliquées dans certains cas ? Par exemple, le fragment de code suivant du fichier de configuration ACML comporte deux fois l'entrée helidon-webserver :
    eventTypes:
      helidon-webserver:
        name: helidon-webserver

    La première entrée helidon-webserver correspond à la valeur lue ou déduite à partir des balises ou du nom de l'opération. Si le type d'événement est clair, facile à lire et intuitif, comme dans l'exemple ci-dessus, vous pouvez l'utiliser pour l'envoi à l'enregistrement JFR. Le résultat est alors affiché de cette façon dans JMC.

    Toutefois, lorsque vous utilisez la valeur operation name, vous pouvez obtenir un type d'événement comme q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A= qui représente une requête JDBC d'un client de base de données. Dans ce cas, vous avez tout intérêt à remplacer le nom envoyé à l'enregistrement JFR par un nom intuitif. L'exemple ci-dessous peut alors être utilisé :
    eventTypes:
      q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A=:
        name: jdbc-select-query
  4. Si recordCallStack peut être spécifié pour chaque type d'événement, pourquoi un paramètre recordCallStack de niveau supérieur doit-il également être utilisé ?

    Nous prenons en charge deux cas d'utilisation pour assurer une flexibilité maximale dans l'enregistrement de la pile d'appels. L'enregistrement de la pile d'appels peut être désactivé globalement, puis activé de manière sélective pour certains types d'événement. Vous pouvez également l'activer globalement, puis le désactiver de manière sélective pour certains types d'événement. Etant donné que ces deux cas d'utilisation sont pris en charge, le paramètre est défini à la fois au niveau de l'événement et au niveau supérieur.

  5. J'ai quelques étendues qui n'ont pas été configurées et qui sont ignorées. Est-il possible de capturer ces événements sans les configurer ?

    Oui. Si vous définissez allowUnconfiguredEvents: true dans la configuration principale de niveau supérieur, ces événements sont capturés. Lorsque cela se produit, nous ne savons pas quels champs collecter. Seuls les champs par défaut suivants sont collectés : traceID, spanID, parentSpanID, startThread et operationName.

  6. Si je me suis servi de com.oracle.apm.agent.jfr.category.default=ORACLE_APM_USE_SPAN_OPERATION_NAMES pour utiliser des catégories définies en fonction du nom de l'opération, le nom de l'opération doit-il correspondre exactement au nom du type d'événement dans le fichier de configuration ? Si tel est le cas, et si j'ai des noms d'opération uniques, dois-je spécifier un type d'événement pour chaque opération ?

    Oui, le nom de l'opération doit correspondre au nom du type d'événement dans le fichier de configuration. Même si vous disposez de nombreux noms d'opération uniques, vous devez indiquer un type d'événement pour chaque opération, car chacun de ces types d'événement est susceptible d'avoir un ensemble de champs différents à configurer.

  7. Le nom de mon opération est converti en identificateur Java. Par conséquent, je ne peux pas configurer son type d'événement. Comment puis-je déterminer la valeur convertie du nom de mon opération ?

    Tous les caractères non autorisés ont été remplacés par un trait de soulignement. Si vous avez besoin d'un échantillon de code Java pour convertir vos chaînes en identificateurs, vous pouvez utiliser le code ci-dessous. Il s'agit de la même routine qu'APM utilise pour convertir les chaînes.
    // Convert an arbitrary string into a valid java identifier by replacing non-identifier chars with an underscore
    public static String getJavaIdentifier(String inString)
    {
        if (inString == null || inString.length() == 0)
           return inString;
        StringBuilder stringBuilder = new StringBuilder();
        char[] allChars = inString.toCharArray();
    
        if(Character.isJavaIdentifierStart(allChars[0]))
            stringBuilder.append(allChars[0]);
        else
            stringBuilder.append("_");
    
        for (int i = 1; i < allChars.length; i++)
        {
            if (Character.isJavaIdentifierPart(allChars[i]))
                stringBuilder.append(allChars[i]);
            else
                stringBuilder.append("_");
        }
        return stringBuilder.toString();
    }
  8. Le nom correspondant peut-il être une expression régulière ?

    Non. Les expressions régulières ne sont pas prises en charge.