Registro de períodos de APM como eventos de JFR

El rastreador de APM y el agente de APM soportan el registro de períodos de APM como eventos de JFR.

Actualmente está soportado JDK 11 o superior.

Para obtener información sobre el registro de períodos de APM como eventos de JFR al utilizar el agente de APM, consulte Registro de períodos de APM como eventos de JFR en Aprovisionamiento y despliegue de agentes de Java APM en servidores de aplicaciones.

Nota

Java Flight Recorder (JFR) es una herramienta para recopilar datos de diagnóstico y creación de perfiles sobre una aplicación Java en ejecución. Para obtener información sobre Java Flight Recorder (JFR) y Java Mission Control (JMC), consulte JDK Mission Control.

Captura de eventos de APM en grabaciones de JFR

Para capturar eventos de APM en las grabaciones de JFR al utilizar el rastreador de APM, siga estos pasos:

  1. Asegúrese de que el rastreador de APM funciona correctamente.

    Abra el Explorador de rastreo y confirme que puede ver todos los rastreos. Para obtener información sobre la apertura y el uso del Explorador de rastreo, consulte Supervisión de rastreos en el explorador de rastreo.

  2. Agregue una dependencia al proyecto de Maven que permitirá al rastreador de APM agregar eventos en las grabaciones de JFR realizadas por Helidon JVM.

    <dependency>
        <groupId>com.oracle.apm.agent.java</groupId>
        <artifactId>apm-java-agent-jfr11</artifactId>
        <version>[1.0.1389,)</version>
    </dependency>
  3. Inicie una grabación.

    Para probar que todo funciona correctamente, debe iniciar una grabación con su método preferido (podría utilizar la interfaz de usuario de JDK Mission Control o la utilidad de línea de comandos JCMD). Una vez iniciada una grabación, los eventos de rastreo se muestran en la interfaz de usuario de JDK Mission Control cuando se visualiza la grabación.

    Para verificar que los eventos de rastreo de APM se han agregado correctamente a las grabaciones de JFR, conéctese a JDK Mission Control y confirme que los rastreos de APM están visibles en el Explorador de eventos: haga clic en APM OpenTracing y confirme que los eventos de rastreo de APM están visibles.

Configuración de eventos de JFR en el rastreador de APM

(Opcional) Este paso es opcional si desea personalizar la generación de informes de los eventos.

Para simplificar el análisis de eventos de grabación de JFR, cada evento se organiza en una categoría o un tipo de evento.

Categoría por defecto

En el rastreador de APM, la categoría por defecto para eventos de JFR de APM se obtiene utilizando el contenido de Span Operation Name (en un campo denominado name dentro del período). La etiqueta component no se puede rellenar, por lo que no se puede utilizar como categoría por defecto.

Eventos

Un tipo de evento permite organizar y clasificar los eventos dentro de la interfaz de usuario de JMC. Cuando el rastreador de APM obtiene un período, puede generar un evento para este período, pero necesita determinar el tipo de evento de ese evento específico.

Algunos ejemplos de tipo de evento son servlet, jdbc y jax-rs.

Configuración de tipo de evento

Hay varias formas de realizar la configuración de un tipo o categoría de evento. Consulte a continuación los distintos casos de uso:

  • Caso 1: Etiqueta component

    Esta es la forma más sencilla de clasificar un evento. Este es el método que se recomienda utilizar.

    En la mayoría de los escenarios, el período opentracing incluirá una etiqueta denominada component. El valor de la etiqueta component se utiliza para determinar el tipo de evento.

    Por ejemplo, consulte el siguiente período:

    {  "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":[
      ]
    },

    En este caso, al evento generado se le asignará un tipo de evento helidon-webserver, ya que es el valor de la etiqueta component.

  • Caso 2: Otra etiqueta

    Si la aplicación no utiliza la etiqueta component, pero utiliza otra etiqueta o hay una biblioteca que está generando las etiquetas en su lugar, el rastreador de APM se puede configurar para que lea el tipo de evento de esa otra etiqueta.

    Por ejemplo, consulte el siguiente período en el que puede leer el tipo de evento de la etiqueta denominada 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":[
      ]
    },

    En este caso, puede obtener el rastreador de APM para leer el tipo de evento de la etiqueta span.type mediante la siguiente propiedad del sistema al iniciar la aplicación java:

    java -Dcom.oracle.apm.agent.jfr.category.tag=span.type ...
  • Caso 3: Uso de Operation Name cuando no hay ninguna etiqueta disponible

    Si la aplicación no utiliza ninguna etiqueta que tenga categorías útiles, es posible utilizar Operation Name para determinar el tipo de evento, pero este método no se recomienda.

    El sistema JFR requiere que el nombre del tipo de evento sea un identificador Java válido, pero Operation Name suele tener espacios y también otros caracteres no válidos. El rastreador de APM convertirá Operation Name en un identificador válido sustituyendo todos los caracteres no válidos por un carácter de subrayado.

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

    Operation Name solo se utilizará si la etiqueta de categoría falta o está vacía.

    Esta no es una solución sencilla porque Operation Name puede contener tokens únicos como identificadores que convertirán todos los eventos en su propio tipo de evento. Además, la conversión de Operation Name en un identificador válido causará más problemas al configurar el tipo de evento para definir qué campos son necesarios en el evento, y también será necesario realizar la configuración según el valor de Operation Name convertido. De lo contrario, deberá configurar muchas variantes diferentes de Operation Name de la misma forma.

  • Caso 4: No hay ninguna etiqueta disponible y todos los nombres de operaciones son únicos

    En este caso, no hay información disponible para clasificar los tipos de eventos. Este es el peor escenario, en el cual todos los eventos terminarán como el mismo tipo de evento, o todos terminarán siendo únicos si se configuran utilizando el escenario del caso de uso 3 descrito anteriormente. Lo único que se puede hacer es que se le permita elegir el nombre de este tipo de evento por defecto y esto se puede configurar como se muestra a continuación.

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

    El valor por defecto solo se utilizará si la etiqueta de categoría falta o está vacía.

    En este caso, todos los eventos se colocan en el tipo de evento denominado Unknown o cualquier valor personalizado seleccionado.

Campos para el tipo de evento

Para cada tipo de evento, podemos agregar 1 o más campos que contienen datos específicos de ese evento.

La lista de campos que se pueden agregar al tipo de evento debe configurarse en el archivo ACML y solo después podrán publicarse los campos en JFR. Para cada campo, se necesita la siguiente información:
  • Nombre.
  • Tipo (entero, flotante, cadena, thread).
  • Etiqueta.
  • Descripción.
Por ejemplo, consulte la siguiente definición de campo para traceID:
- name: traceID
  type: String
  label: New Trace ID
  description: New Opentracing Trace ID

Creación de un archivo ACML

Éste es un paso opcional. Si la configuración por defecto funciona como se esperaba, puede omitir este paso.

Puede crear un archivo ACML si desea cambiar la configuración por defecto y personalizar las grabaciones.

En el siguiente ejemplo se muestra el formato de un archivo ACML que configura el registro de eventos en JFR sobrescribiendo la configuración por defecto incorporada para el contenedor de microservicios de 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

Puede utilizar el formato anterior del archivo ACML al utilizar el agente de APM y el rastreador de APM. En el caso del rastreador de APM, funcionará para cualquier contenedor como Helidon, Springboot y Micronaut.

Preguntas frecuentes

  1. Si se han proporcionado ambos valores: las propiedades com.oracle.apm.agent.jfr.category.tag y com.oracle.apm.agent.jfr.category.default, ¿qué valor tiene prioridad?

    Si a ambos se les ha asignado un valor, en primer lugar buscaremos en el período la etiqueta de categoría. Si se encuentra, será este el que se utilizará. Si falta, se utilizará el valor por defecto.

  2. Para el rastreador de APM, ¿es obligatorio el archivo de configuración? ¿Puedo simplemente especificar las propiedades sin el archivo?

    El archivo de configuración no es obligatorio. Si el valor por defecto se ajusta a sus necesidades, no necesita un archivo de configuración y puede especificar las propiedades.

  3. En algunos casos, ¿por qué parece que se duplican las entradas? Por ejemplo, el siguiente fragmento del archivo de configuración de ACML tiene la entrada helidon-webserver dos veces:
    eventTypes:
      helidon-webserver:
        name: helidon-webserver

    La primera entrada helidon-webserver es lo que leemos/deducimos de las etiquetas o del nombre de la operación. Si el tipo de evento es limpio, fácil de leer e intuitivo, como en el ejemplo anterior, puede utilizar el mismo tipo de evento para enviarlo a la grabación de JFR y así es cómo se mostrará en JMC.

    Sin embargo, a veces, al utilizar operation name, puede obtener un tipo de evento como el siguiente: q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A= que representa una consulta JDBC de un cliente de base de datos. En este caso, es posible que desee cambiar el nombre que se envía a la grabación de JFR por uno intuitivo, por lo que el siguiente ejemplo se puede utilizar en esos casos:
    eventTypes:
      q_AxPsCbac9Ykp0HjpU+ENCiYHKl5HzMCmR02AfGzow3A=:
        name: jdbc-select-query
  4. Si se puede especificar recordCallStack para cada tipo de evento, ¿por qué es también necesario tener recordCallStackde nivel superior?

    Están soportados dos casos de uso para ofrecer la máxima flexibilidad en la grabación de la pila de llamadas. La grabación de la pila de llamadas se puede desactivar globalmente y, a continuación, se puede activar de forma selectiva para tipos de eventos específicos. Otra opción es activarla globalmente y, a continuación, desactivarla de forma selectiva para tipos de eventos específicos. Ambos casos de uso están soportados, de modo que la configuración está tanto en el nivel superior como en el nivel de evento.

  5. Tengo algunos períodos que no se han configurado y que se están ignorando. ¿Es posible capturar esos eventos sin configurarlos?

    Sí. Si define allowUnconfiguredEvents: true en la configuración de nivel superior principal, se capturarán esos eventos. Cuando esto sucede, no sabemos qué campos se recopilan. Solo se recopila el siguiente juego de campos por defecto: traceID, spanID, parentSpanID, startThread y operationName.

  6. Si he utilizado com.oracle.apm.agent.jfr.category.default=ORACLE_APM_USE_SPAN_OPERATION_NAMES para utilizar categorías definidas por nombre de operación, ¿tiene que coincidir el nombre de operación exactamente con el nombre de tipo de evento en el archivo de configuración? Si es así y tengo nombres de operación únicos, ¿debo especificar un tipo de evento para cada operación?

    Sí, debe coincidir con el nombre de tipo de evento en el archivo de configuración. Incluso si tiene muchos nombres de operación únicos, tendrá que especificar un tipo de evento para cada operación porque es probable que cada uno de esos tipos de evento tenga un juego diferente de campos que se deben configurar.

  7. Mi nombre de operación se convierte en un identificador Java. Por ello, no puedo configurar su tipo de evento. ¿Cómo puedo determinar en qué se ha convertido mi nombre de operación?

    Todos los caracteres no válidos se han sustituido por un carácter de subrayado. Si necesita un código Java de ejemplo para convertir las cadenas en identificadores, puede utilizar el siguiente código, que no es la misma rutina que utiliza APM para convertir las cadenas.
    // 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. ¿Puede ser el nombre coincidente una expresión regular?

    No. Las expresiones regulares no están soportadas.