EventPipe

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

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 de serialização do EventPipe, consulte a documentação do formato EventPipe.

EventPipe vs. ETW/LTTng

O EventPipe faz parte do CoreCLR (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. O EventPipe não pode ser usado para acompanhar alguns eventos de nível inferior, como resolver a pilha de código nativa ou obter vários eventos de kernel. Se você usar a interoperabilidade C/C++ em seu aplicativo ou quiser rastrear o runtime em si (que é gravado em C++) ou deseja um diagnóstico mais profundo no comportamento do aplicativo que requer eventos de kernel (ou seja, eventos de alternância de contexto de thread nativo), você deve usar ETW ou perf/LTTng.

Outra grande diferença entre EventPipe e ETW/LTTng é o requisito de privilégio de administrador/raiz. Para rastrear um aplicativo usando ETW ou LTTng, você precisa ser um administrador/raiz. Usando o EventPipe, 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.

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

Recurso EventPipe ETW LTTng
Plataforma cruzada Sim Não (somente no Windows) Não (somente em distribuições do Linux com suporte)
Exigir privilégio de administrador/raiz No Sim Sim
Pode obter eventos de SO/kernel No Sim Yes
Pode resolver pilhas de chamadas nativas No 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.

  • O dotnet-gcdump permite coletar despejos de heap de GC de processos dinâmicos 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 para 1 para iniciar uma sessão EventPipe que grava diretamente em um arquivo. O valor padrão é 0.

  • DOTNET_EventPipeOutputPath: o caminho para o arquivo de rastreamento do EventPipe de saída quando ele está configurado para ser executado por meio de 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ó é usado quando o EventPipe é configurado para ser executado por meio e 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 muitos eventos estiverem sendo descartados, aumente o tamanho do buffer para ver se o número de eventos descartados reduz. Se o número de eventos descartados não diminuir com um tamanho maior de buffer, pode ser devido a um leitor lento que impede que os buffers do processo de destino sejam liberados.

  • 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_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.

Observação

O .NET 6 usa o prefixo DOTNET_ como padrão em vez de COMPlus_ para variáveis de ambiente que configuram o comportamento de tempo de execução do .NET. No entanto, o prefixo COMPlus_ continuará funcionando. Se você estiver usando uma versão anterior do runtime do .NET, ainda terá que usar o prefixo COMPlus_ para variáveis de ambiente.