EventPipe

EventPipe é um componente de runtime que pode ser usado para coletar dados de rastreamento, semelhantes a ETW ou perf_events. O objetivo do EventPipe é permitir que os desenvolvedores do .NET rastreiem facilmente seus aplicativos .NET sem precisar contar com componentes de alto privilégio específicos da plataforma, como ETW ou perf_events.

O EventPipe é o mecanismo por trás de muitas das ferramentas de diagnóstico e pode ser usado para consumir eventos emitidos pelo runtime, bem como eventos personalizados gravados com EventSource.

Este artigo é uma visão geral de alto nível do EventPipe. Ele descreve quando e como usar o EventPipe e como configurá-lo para atender da melhor forma às suas necessidades.

Noções básicas do EventPipe

O EventPipe agrega eventos emitidos por componentes de runtime - por exemplo, o compilador Just-In-Time ou o coletor de lixo, e eventos gravados a partir de instâncias EventSource nas bibliotecas e no código do usuário.

Em seguida, os eventos são serializados no formato de arquivo .nettrace e podem ser gravados diretamente em um arquivo ou transmitidos por meio de uma porta de diagnóstico para consumo fora do processo.

Para saber mais sobre o formato NetTrace, consulte a documentação do formato NetTrace.

EventPipe versus ETW/perf_events

O EventPipe faz parte do runtime do .NET e foi projetado para funcionar da mesma maneira em todas as plataformas compatíveis com o .NET Core. Isso permite que as ferramentas de rastreamento baseadas em EventPipe, como dotnet-counters, dotnet-gcdump e dotnet-trace, funcionem perfeitamente entre plataformas.

No entanto, como o EventPipe é um componente interno de runtime, seu escopo é limitado ao código gerenciado e ao próprio runtime. Sem outras ferramentas de rastreamento, os eventos do EventPipe incluem rastreamentos de pilha com informações apenas sobre quadros de código gerenciados. Para obter eventos de outras bibliotecas de modo de usuário não gerenciadas, amostragem de CPU para eventos de código nativo ou kernel, use ferramentas de rastreamento específicas do sistema operacional, como ETW ou perf_events. No Linux, a ferramenta de perfcollect ajuda a automatizar o uso de perf_events e LTTng.

A partir do .NET 10, o EventPipe no Linux pode emitir eventos como user_events, permitindo a coleta de eventos gerenciados, eventos do SO/kernel e pilhas de chamadas nativas em um único rastreamento unificado. Esse modo requer privilégios de administrador/raiz e kernel linux 6.4+. Para obter mais informações, consulte dotnet-trace collect-linux.

Outra grande diferença entre EventPipe e ETW/perf_events é o requisito de privilégio de administrador/raiz. Para rastrear um aplicativo usando ETW ou perf_events, você precisa ser um administrador/raiz. Usando EventPipe padrão, você pode rastrear aplicativos desde que o rastreador (por exemplo, dotnet-trace) seja executado como o mesmo usuário que o usuário que iniciou o aplicativo. O modo EventPipe (user_events) descrito anteriormente requer privilégios de administrador/raiz porque interage com a infraestrutura de rastreamento no nível do sistema operacional.

A tabela a seguir é um resumo das diferenças entre EventPipe e ETW/perf_events.

Funcionalidade EventPipe EventPipe (user_events) ETW perf_events
Multiplataforma Sim Não (somente em distribuições do Linux com suporte) Não (somente no Windows) Não (somente em distribuições do Linux com suporte)
Exigir privilégio de administrador/raiz Não Sim Sim Sim
Pode obter eventos do Sistema Operacional/kernel Não Sim Sim Sim
Pode resolver pilhas de chamadas nativas Não Sim Sim Sim

Usar o EventPipe para rastrear seu aplicativo .NET

Você pode usar o EventPipe para rastrear seu aplicativo .NET de várias maneiras:

Depois de produzir um arquivo nettrace que contém seus eventos eventPipe, você pode exibir o arquivo no PerfView ou no Visual Studio. Em plataformas que não sejam Windows, você pode converter o arquivo nettrace em um formato de rastrteamento speedscope ou Chromium usando o comando dotnet-trace convert e exibi-lo com speedscope ou Chrome DevTools.

Você também pode analisar rastreamentos do EventPipe programaticamente com o TraceEvent.

Ferramentas que usam o EventPipe

Essa é a maneira mais fácil de usar o EventPipe para rastrear seu aplicativo. Para saber mais sobre como usar cada uma dessas ferramentas, consulte a documentação de cada ferramenta.

  • Os dotnet-counters permitem monitorar e coletar várias métricas emitidas pelo runtime do .NET e bibliotecas principais, bem como métricas personalizadas que você pode gravar.

  • dotnet-gcdump permite coletar dumps de heap do GC de processos ativos para analisar o heap gerenciado de um aplicativo.

  • O dotnet-trace permite coletar rastreamentos de aplicativos para analisar o desempenho.

Rastreamento usando variáveis de ambiente

O mecanismo preferencial para usar o EventPipe é usar o dotnet-trace ou a biblioteca Microsoft.Diagnostics.NETCore.Client .

No entanto, você pode usar as variáveis de ambiente a seguir para configurar uma sessão EventoPipe em um aplicativo e fazer com que ele escreva o rastreamento diretamente em um arquivo. Para interromper o rastreamento, saia do aplicativo.

  • DOTNET_EnableEventPipe: defina isso para 1 para iniciar uma sessão do EventPipe que grava diretamente em um arquivo. O valor padrão é 0.

  • DOTNET_EventPipeOutputPath: o caminho para o arquivo de rastreamento de saída do EventPipe quando configurado para ser executado via DOTNET_EnableEventPipe. O valor padrão é trace.nettrace, que será criado no mesmo diretório do qual o aplicativo está sendo executado.

    Observação

    Desde o .NET 6, as instâncias da cadeia de caracteres {pid} em DOTNET_EventPipeOutputPath são substituídas pela ID de processo do processo que está sendo rastreado.

  • DOTNET_EventPipeCircularMB: um valor hexadecimal que representa o tamanho do buffer interno do EventPipe em megabytes. Esse valor de configuração só é utilizado quando o EventPipe é configurado para ser executado por meio do DOTNET_EnableEventPipe. O tamanho padrão do buffer é 1024 MB, que se traduz para essa variável de ambiente que está sendo definida como 400, desde 0x400 == 1024 .

    Observação

    Se o processo de destino gravar eventos com muita frequência, ele poderá estourar esse buffer e alguns eventos poderão ser descartados. Se o runtime descartar muitos eventos, defina DOTNET_EventPipeBufferingMode=1 com DOTNET_EventPipeOutputStreaming=1 ou aumente o tamanho do buffer para ver se o número de eventos descartados diminui. Se o número de eventos descartados não diminuir com um tamanho de buffer maior, um leitor lento poderá impedir que os buffers do processo de destino sejam liberados.

  • DOTNET_EventPipeBufferingMode: disponível no .NET 11 e posterior. Essa configuração controla como a sessão eventPipe de inicialização manipula a gravação de um evento quando o buffer na memória está cheio. Defina-o como 0 (padrão) para descartar eventos que transbordariam o buffer ou 1 para pausar threads de gravação de eventos até que o espaço do buffer fique disponível. 1 requer uma sessão de streaming (consulte DOTNET_EventPipeOutputStreaming).

  • DOTNET_EventPipeOutputStreaming: defina isso como 1 para transmitir os eventos da sessão EventPipe de inicialização para o disco o mais rápido possível depois que eles ocorrerem. Por padrão, os eventos são armazenados na memória e não gravados em disco até que o aplicativo seja encerrado. Uma sessão de streaming é necessária para DOTNET_EventPipeBufferingMode=1 entrar em vigor.

  • DOTNET_EventPipeProcNumbers: defina para 1 para habilitar a captura de números de processador em cabeçalhos de evento do EventPipe. O valor padrão é 0.

  • DOTNET_EventPipeThreadSamplingRate: disponível no .NET 10.0.10 e posterior. Define o intervalo, em milissegundos, para o profiler de amostragem de tempo do thread do EventPipe. Quando definido como 0 ou omitido, o runtime usa seu padrão interno de 1 ms (aproximadamente 1.000 Hz). Builds sem suporte a threading, como WebAssembly de thread único, usam um padrão de 5 ms (~200 Hz). Essa configuração é global de processo e afeta todas as sessões eventPipe, incluindo rastreamentos sob demanda iniciados por ferramentas como dotnet-trace. Definir um valor grande reduz a sobrecarga de amostragem, mas também reduz a resolução de qualquer rastreamento coletado durante a vida útil do processo.

  • DOTNET_EventPipeConfig: define a configuração da sessão do EventPipe ao iniciar uma sessão do EventPipe com DOTNET_EnableEventPipe. A sintaxe dela é a seguinte:

    <provider>:<keyword>:<level>

    Você também pode especificar vários provedores concatenando-os com uma vírgula:

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

    Se essa variável de ambiente não estiver definida, mas o EventPipe estiver habilitado por DOTNET_EnableEventPipe, ele começará a rastrear habilitando os seguintes provedores com as seguintes palavras-chave e níveis:

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

    Para saber mais sobre alguns dos provedores conhecidos no .NET, consulte Provedores de eventos conhecidos.