Enregistrer les intervalles APM en tant qu'événements JFR

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

Actuellement, JDK version 11 ou supérieure est pris en charge.

Pour plus d'informations sur l'enregistrement des intervalles APM en tant qu'événements JFR lors de l'utilisation de l'agent APM, voir Enregistrer les intervalles APM en tant qu'événements JFR sous Provisionner et déployer des agents Java APM sur des serveurs d'applications.

Note

Java Flight Recorder (JFR) est un outil permettant de collecter des données de diagnostic et de profilage sur une application Java en cours d'exécution. Pour plus d'informations sur Java Flight Recorder (JFR) et Java Mission Control (JMC), voir JDK Mission Control.

Saisir les événements APM dans des enregistrements JFR

Pour saisir les événements APM dans des enregistrements JFR lors de l'utilisation du traceur APM, procédez comme suit :

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

    Ouvrez l'explorateur de trace et vérifiez que vous pouvez voir toutes les traces. Pour plus d'informations sur l'ouverture et l'utilisation de l'explorateur de trace, voir Surveiller les traces dans l'explorateur de trace.

  2. Ajoutez une dépendance au projet Maven qui permettra au traceur APM d'ajouter des événements aux enregistrements JFR effectué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 selon votre méthode préférée (à l'aide de l'interface utilisateur de JDK Mission Control ou au moyen de l'utilitaire de ligne de commande JCMD). Une fois l'enregistrement lancé, les événements de trace s'affichent dans l'interface utilisateur de JDK Mission Control lorsque l'enregistrement est consulté.

    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 sont visibles sous Event Browser (Navigateur d'événements) : cliquez sur APM OpenTracing et vérifiez que les événements de trace APM sont visibles.

Configurer des événements JFR dans le traceur APM

(Facultatif) Cette étape est facultative et permet de personnaliser la production de rapports sur les événements.

Pour simplifier l'analyse des événements d'enregistrement JFR, tous les événements sont en catégories ou types d'événement.

Catégorie par défaut

Dans le traceur APM, la catégorie par défaut pour les événements JFR APM est obtenue en utilisant le contenu de Span Operation Name (dans un champ appelé name dans l'intervalle). Comme l'étiquette component ne peut pas être alimentée, elle ne peut donc pas être utilisée comme catégorie par défaut.

Événements

Un type d'événement permet d'organiser et de classer les événements dans l'interface utilisateur de JMC. Lorsque le traceur APM obtient un intervalle, il peut générer un événement pour cet intervalle, mais il doit déterminer le type d'événement de cet événement précis.

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

Configuration du type d'événement

Il existe plusieurs façons de configurer un type ou une catégorie d'événements. Voir ci-dessous les différents cas d'utilisation :

  • Cas 1 : Marqueur component

    C'est le moyen le plus simple de classer un événement. Il s'agit de la méthode recommandée.

    Dans la plupart des scénarios, l'intervalle Opentracing contient un marqueur nommé component. La valeur du marqueur component est utilisée pour déterminer le type d'événement.

    Voir l'exemple ci-dessous :

    {  "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 du marqueur component.

  • Cas 2 : Autre marqueur

    Si votre application utilise un marqueur autre que le marqueur component, ou une bibliothèque génère les marqueurs pour vous, le traceur APM peut être configuré pour lire le type d'événement de cet autre marqueur.

    Par exemple, dans l'intervalle suivant vous pouvez lire le type d'événement à partir du marqueur nommé 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 configurer le traceur APM pour qu'il lise le type d'événement à partir du marqueur 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 : Utiliser le nom de l'opération si aucun marqueur n'est disponible

    Si votre application n'utilise aucun marqueur ayant des catégories utiles, il est possible d'utiliser Operation Name pour déterminer le type d'événement, mais cette méthode n'est pas recommandée.

    Le système JFR exige que le nom du type d'événement soit un identificateur Java valide, mais Operation Name comporte souvent des espaces et d'autres caractères non autorisés. Le traceur APM convertit le fichier Operation Name en un 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
    Note

    La valeur de Operation Name ne sera utilisée que si le marqueur de catégorie est manquant ou vide.

    Il ne s'agit pas d'une solution simple, car Operation Name peut contenir des jetons uniques, comme des ID, qui feront de chaque événement son propre type d'événement. De plus, la conversion de Operation Name en identificateur valide entraînera d'autres problèmes lors de la configuration du type d'événement pour configurer les champs nécessaires à l'événement. De plus, la configuration devra être effectuée en fonction de la valeur convertie de Operation Name, sinon vous devrez configurer de nombreuses variantes différentes de Operation Name de la même manière.

  • Cas 4 : Aucun marqueur 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 pire scénario où tous les événements finiront par être du même type d'événement ou par être uniques s'ils sont configurés conformément au cas d'utilisation 3 ci-dessus. La seule chose possible est de vous permettre de choisir le nom de ce type d'événement par défaut, qui peut être configuré de la façon indiquée ci-dessous.

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

    La valeur par défaut ne sera utilisée que si le marqueur de catégorie est manquant ou vide.

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

Champs associés au type d'événement

Pour chaque type d'événement, nous pouvons ajouter un ou plusieurs 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 seulement après que les champs puissent être publiés dans JFR. Les informations suivantes sont requises pour chaque champ :
  • Nom
  • Type (int, float, string, thread).
  • Étiquette
  • Description
Par exemple, la définition de champ suivante pour traceID :
- name: traceID
  type: String
  label: New Trace ID
  description: New Opentracing Trace ID

Créer un fichier ACML

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

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

L'exemple suivant présente le format d'un fichier ACML dans lequel la journalisation des événements dans JFR est configurée en écrasant les réglages par défaut intégrés pour le 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 ci-dessus du fichier ACML lorsque vous utilisez l'agent APM et le traceur APM. Pour le traceur APM, il fonctionne pour tous les conteneurs tels que Helidon, Springboot et Micronaut.

Foire aux questions

  1. Lorsque les deux paramètres sont fournis : propriétés com.oracle.apm.agent.jfr.category.tag et com.oracle.apm.agent.jfr.category.default, lequel a priorité?

    Si une valeur leur est affectée, nous rechercherons d'abord le marqueur de catégorie dans l'intervalle. Si nous le trouvons, il sera utilisé. Dans le cas contraire, la valeur par défaut sera utilisée.

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

    Un fichier de configuration n'est pas obligatoire. Si la valeur par défaut fonctionne pour vous, vous n'avez pas besoin d'un fichier de configuration et vous pouvez quand même spécifier les propriétés.

  3. Dans certains cas, pourquoi les entrées sont-elles dupliquées? Par exemple, l'extrait de code suivant du fichier de configuration ACML contient l'entrée helidon-webserver deux fois :
    eventTypes:
      helidon-webserver:
        name: helidon-webserver

    La première entrée helidon-webserver correspond à ce que nous avons lu/déduit à partir des marqueurs 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 utiliser le même type d'événement pour l'envoyer à l'enregistrement JFR et c'est ainsi qu'il sera affiché dans JMC.

    Toutefois, lorsque vous utilisez operation name, vous obtiendrez parfois un type d'événement comme ceci : q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A=, qui représente une interrogation JDBC à partir d'un client de base de données. Dans un tel cas, vous souhaiterez remplacer le nom envoyé à l'enregistrement JFR par un nom intuitif en suivant l'exemple ci-dessous :
    eventTypes:
      q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A=:
        name: jdbc-select-query
  4. Si recordCallStack peut être spécifié pour chaque type d'événement, Pourquoi est-il également nécessaire d'avoir le niveau supérieur recordCallStack?

    Nous prenons en charge deux cas d'utilisation pour une flexibilité maximale d'enregistrement dans la pile d'appels. L'enregistrement de pile d'appels peut être désactivé globalement, puis il peut être activé de manière sélective pour des types d'événement spécifiques. Une autre option consiste à l'activer globalement, puis à la désactiver pour des types d'événement spécifiques. Les deux cas d'utilisation sont pris en charge. Par conséquent, le paramètre est défini au niveau supérieur et au niveau de l'événement.

  5. J'ai des intervalles qui n'ont pas été configurés du tout et qui sont ignorés. Est-il possible de saisir ces événements sans les configurer?

    Oui. Si vous réglez allowUnconfiguredEvents: true dans la configuration de niveau supérieur principal, ces événements seront saisis. Dans ce cas, nous ne savons pas quels champs collecter. Seul le jeu de champs par défaut suivant est collecté : traceID, spanID, parentSpanID, startThread et operationName.

  6. Si j'ai utilisé com.oracle.apm.agent.jfr.category.default=ORACLE_APM_USE_SPAN_OPERATION_NAMES pour employer des catégories définies par le 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? Dans l'affirmative, et si j'ai des noms d'opération uniques, dois-je spécifier un type d'événement pour chaque opération?

    Oui, il doit correspondre au nom du type d'événement dans le fichier de configuration. Même si vous avez beaucoup de noms d'opération uniques, vous devez spécifier un type d'événement pour chaque opération, car chacun de ces types d'événement est susceptible d'avoir un jeu de champs différent à configurer.

  7. Mon nom d'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 à quoi mon nom d'opération a été converti?

    Tous les caractères non autorisés ont été remplacés par un trait de soulignement. Si vous avez besoin d'un exemple de code Java pour convertir vos chaînes en identificateurs, vous pouvez utiliser le code ci-dessous qui n'est pas le même sous-programme 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. La mise en correspondance des noms peut-elle être effectuée par RegEx?

    Non. RegEx n'est pas pris en charge.