EventPipe

EventPipe es un componente en tiempo de ejecución similar a ETW o LTTng que se puede usar para recopilar datos de seguimiento. El objetivo de EventPipe es permitir a los desarrolladores de .NET realizar un seguimiento sencillo de sus aplicaciones .NET sin tener que depender de componentes nativos del sistema operativo específicos de la plataforma como ETW o LTTng.

EventPipe es el mecanismo subyacente de muchas de las herramientas de diagnóstico y se puede usar para consumir eventos emitidos por el entorno de ejecución, así como eventos personalizados escritos con EventSource.

Este artículo es una introducción de alto nivel a EventPipe. Describe cuándo y cómo usar EventPipe y cómo configurarlo para que se adapte mejor a sus necesidades.

Aspectos básicos de EventPipe

EventPipe agrega eventos emitidos por componentes en tiempo de ejecución (por ejemplo, el compilador Just-in-Time o el recolector de elementos no utilizados) y eventos escritos desde instancias de EventSource en las bibliotecas y el código de usuario.

A continuación, los eventos se serializan en el formato de archivo .nettrace y se pueden escribir directamente en un archivo o transmitirse a través de un puerto de diagnóstico para el consumo fuera del proceso.

Para obtener más información sobre el formato de serialización de EventPipe, vea la documentación de formato de EventPipe.

EventPipe frente a ETW/LTTng

EventPipe forma parte del entorno de ejecución .NET (CoreCLR) y está diseñado para funcionar de la misma manera en todas las plataformas compatibles con .NET Core. Esto permite que herramientas de seguimiento basadas en EventPipe, como dotnet-counters, dotnet-gcdump y dotnet-trace, funcionen sin problemas entre plataformas.

Pero, dado que EventPipe es un componente integrado en tiempo de ejecución, su ámbito se limita al código administrado y al propio entorno de ejecución. EventPipe no se puede usar para realizar el seguimiento de algunos eventos de nivel inferior, como resolver la pila de código nativo u obtener distintos eventos de kernel. Si usa interoperabilidad de C/C++ en la aplicación, quiere realizar un seguimiento del propio entorno de ejecución (que está escrito en C++) o quiere un diagnóstico más profundo sobre el comportamiento de la aplicación que requiera eventos de kernel (es decir, eventos de cambio de contexto de subprocesos nativos), debe usar ETW o perf/LTTng.

Otra diferencia importante entre EventPipe y ETW/LTTng es el requisito de privilegios de administrador o raíz. Para realizar el seguimiento de una aplicación mediante ETW o LTTng, debe ser administrador o raíz. Con EventPipe puede realizar un seguimiento de las aplicaciones siempre que el seguimiento (por ejemplo, dotnet-trace) se ejecute como el mismo usuario que el que ha iniciado la aplicación.

En la tabla siguiente se presenta un resumen de las diferencias entre EventPipe y ETW/LTTng.

Característica EventPipe ETW LTTng
Multiplataforma No (solo en Windows) No (solo en distribuciones Linux compatibles)
Requiere privilegios de administrador o raíz No
Puede obtener eventos de SO o kernel No
Puede resolver pilas de llamadas nativas No

Uso de EventPipe para el seguimiento de la aplicación .NET

Puede usar EventPipe para realizar un seguimiento de la aplicación .NET de muchas maneras:

Después de haber creado un archivo nettrace que contiene los eventos EventPipe, puede verlo en PerfView o en Visual Studio. En las plataformas que no son de Windows, puede convertir el archivo nettrace a un formato de seguimiento de speedscope o Chromium mediante el comando dotnet-trace convert y verlo con speedscope o Chrome DevTools.

También puede analizar los seguimientos de EventPipe mediante programación con TraceEvent.

Herramientas que usan EventPipe

Esta es la forma más sencilla de usar EventPipe para realizar un seguimiento de la aplicación. Para obtener más información sobre cómo usar cada una de estas herramientas, vea la documentación de cada una de ellas.

  • dotnet-counters permite supervisar y recopilar diversas métricas emitidas por el entorno de ejecución .NET y las bibliotecas principales, así como métricas personalizadas que se pueden escribir.

  • dotnet-gcdump permite recopilar volcados de memoria del montón de GC de procesos en vivo para analizar el montón administrado de una aplicación.

  • dotnet-trace permite recopilar seguimientos de aplicaciones para analizar el rendimiento.

Seguimiento mediante variables de entorno

El mecanismo preferido para usar EventPipe es emplear dotnet-trace o la biblioteca Microsoft.Diagnostics.NETCore.Client.

pero puede usar las siguientes variables de entorno para configurar una sesión de EventPipe en una aplicación y hacer que escriba el seguimiento directamente en un archivo. Para detener el seguimiento, salga de la aplicación.

  • DOTNET_EnableEventPipe: establezca en 1 para iniciar una sesión de EventPipe que escriba directamente en un archivo. El valor predeterminado es 0.

  • DOTNET_EventPipeOutputPath: ruta de acceso al archivo de seguimiento de EventPipe de salida cuando está configurado para ejecutarse mediante DOTNET_EnableEventPipe. El valor predeterminado es trace.nettrace, que se crea en el mismo directorio desde el que se ejecuta la aplicación.

    Nota:

    A partir de .NET 6, las instancias de la cadena {pid} en DOTNET_EventPipeOutputPath se reemplazan por el identificador del proceso del que se realiza el seguimiento.

  • DOTNET_EventPipeCircularMB: valor hexadecimal que representa el tamaño del búfer interno de EventPipe en megabytes. Este valor de configuración solo se usa cuando EventPipe está configurado para ejecutarse mediante DOTNET_EnableEventPipe. El tamaño de búfer predeterminado es de 1024 MB, que se traduce en esta variable de entorno estableciéndose en 400, puesto que 0x400 == 1024.

    Nota:

    Si el proceso de destino escribe eventos con demasiada frecuencia, puede desbordar este búfer y se pueden eliminar algunos eventos. Si se quitan demasiados eventos, aumente el tamaño del búfer para ver si se reduce el número de eventos eliminados. Si el número de eventos eliminados no disminuye con un tamaño de búfer mayor, puede deberse a que un lector lento está evitando que se vacíen los búferes del proceso de destino.

  • DOTNET_EventPipeProcNumbers: establézcalo en 1 para habilitar la captura de números de procesador en los encabezados de evento de EventPipe. El valor predeterminado es 0.

  • DOTNET_EventPipeConfig: establece la configuración de sesión de EventPipe al iniciar una sesión de EventPipe con DOTNET_EnableEventPipe. La sintaxis es la siguiente:

    <provider>:<keyword>:<level>

    También puede especificar varios proveedores si los concatena con una coma:

    <provider1>:<keyword1>:<level1>,<provider2>:<keyword2>:<level2>

    Si no se establece esta variable de entorno sino que EventPipe se habilita por medio de DOTNET_EnableEventPipe, comienza el seguimiento mediante la habilitación de los siguientes proveedores con las siguientes palabras clave y niveles:

    • Microsoft-Windows-DotNETRuntime:4c14fccbd:5
    • Microsoft-Windows-DotNETRuntimePrivate:4002000b:5
    • Microsoft-DotNETCore-SampleProfiler:0:5

    Para obtener más información acerca de algunos de los proveedores conocidos en .NET, consulte Proveedores de eventos conocidos en .NET.

Nota:

.NET 6 estandariza en el prefijo DOTNET_ en lugar de en COMPlus_ para las variables de entorno que configuran el comportamiento en tiempo de ejecución de .NET. Sin embargo, el prefijo COMPlus_ seguirá funcionando. Si usa una versión anterior del runtime de .NET, debe seguir usando el prefijo COMPlus_ para las variables de entorno.