EventPipe

EventPipe ist eine Runtimekomponente, die wie ETW oder LTTng zum Erfassen von Ablaufverfolgungsdaten verwendet werden kann. EventPipe soll es .NET-Entwicklern ermöglichen, die Aktivitäten ihrer .NET-Anwendungen problemlos nachverfolgen zu können, ohne sich dabei auf plattformspezifische und betriebssystemnative Komponenten wie ETW oder LTTng verlassen zu müssen.

EventPipe ist der Mechanismus hinter vielen der Diagnosetools und kann zum Verarbeiten von Ereignissen, die von der Runtime ausgegeben werden, sowie von benutzerdefinierten Ereignissen verwendet werden, die mit EventSource geschrieben wurden.

Dieser Artikel bietet einen allgemeinen Überblick über EventPipe. Hier wird beschrieben, wann und wie EventPipe verwendet werden sollte und wie die Komponente Ihren Anforderungen entsprechend konfiguriert werden kann.

EventPipe-Grundlagen

EventPipe aggregiert Ereignisse, die von Runtimekomponenten (z. B. Just-In-Time-Compiler oder Garbage Collector) ausgegeben werden, und Ereignisse, die aus EventSource-Instanzen in den Bibliotheken und im Benutzercode geschrieben werden.

Die Ereignisse werden dann im Dateiformat .nettrace serialisiert und können direkt in eine Datei geschrieben oder über einen Diagnoseport zur Nutzung außerhalb des Prozesses gestreamt werden.

Weitere Informationen zum EventPipe-Serialisierungsformat finden Sie in der Dokumentation zum EventPipe-Format.

EventPipe im Vergleich zu ETW/LTTng

EventPipe ist Teil der .NET-Runtime (CoreCLR) und so konzipiert, dass diese Komponente auf allen Plattformen, die .NET Core unterstützt, auf dieselbe Weise funktioniert. Dadurch können auf EventPipe basierende Ablaufverfolgungstools wie dotnet-counters, dotnet-gcdump und dotnet-trace problemlos plattformübergreifend verwendet werden.

Da EventPipe jedoch eine integrierte Runtimekomponente ist, ist der zugehörige Bereich auf verwalteten Code und die Runtime selbst beschränkt. EventPipe kann nicht zum Nachverfolgen detaillierterer Ereignisse wie das Auflösen von nativen Codestapeln oder das Abrufen verschiedener Kernelereignisse verwendet werden. Wenn Sie die C/C++-Interop in Ihrer App verwenden, die Runtime selbst überwachen (in C++ geschrieben) oder eine genauere Diagnose des App-Verhaltens haben möchten, die Kernelereignisse erfordert (d. h. threadnative, den Kontext wechselnde Ereignisse), sollten Sie ETW oder perf/LTTng verwenden.

Ein weiterer wichtiger Unterschied zwischen EventPipe und ETW/LTTng besteht in den Anforderungen für die Berechtigungen für Administratoren und Root-Benutzer. Sie müssen Administrator oder Root-Benutzer sein, um eine Anwendung mithilfe von ETW oder LTTng nachverfolgen zu können. Wenn Sie EventPipe verwenden, können Sie Anwendungen nachverfolgen, solange die Ablaufverfolgung (z. B. dotnet-trace) für den Benutzer ausgeführt wird, der die Anwendung gestartet hat.

Die folgende Tabelle ist eine Zusammenfassung der Unterschiede zwischen EventPipe und ETW/LTTng.

Funktion EventPipe ETW LTTng
Plattformübergreifend Ja Nein (nur unter Windows) Nein (nur für unterstützte Linux-Distributionen)
Anfordern von Berechtigungen für Administratoren und Root-Benutzer Nein Ja Ja
Abrufen von Betriebssystem- oder Kernelereignissen Nein Ja Ja
Auflösen nativer Aufruflisten Nein Ja Ja

Verwenden von EventPipe zum Nachverfolgen der .NET-Anwendung

Sie können EventPipe verwenden, um Ihre .NET-Anwendung auf unterschiedlichste Weise nachzuverfolgen:

Nachdem Sie eine nettrace-Datei erstellt haben, die Ihre EventPipe-Ereignisse enthält, können Sie die Datei in PerfView oder Visual Studio anzeigen. Auf Nicht-Windows-Plattformen können Sie die nettrace-Datei mithilfe des Befehls dotnet-trace convert in das speedscope- oder Chromium-Ablaufverfolgungsformat konvertieren und mit speedscope oder Chrome DevTools anzeigen.

Sie können EventPipe-Ablaufnachverfolgungen mit TraceEvent auch programmgesteuert analysieren.

Tools, die EventPipe verwenden

Dies ist die einfachste Möglichkeit, EventPipe zum Nachverfolgen Ihrer Anwendung zu verwenden. Weitere Informationen zur Verwendung dieser Tools finden Sie in der Dokumentation zu den einzelnen Tools.

  • dotnet-counters ermöglicht Ihnen das Überwachen und Erfassen von verschiedenen Metriken, die von der .NET-Runtime und Kernbibliotheken ausgegeben werden. Dies ist ebenfalls für benutzerdefinierte Metriken möglich, die Sie selbst schreiben.

  • Mit dotnet-gcdump können Sie GC-Heapspeicherabbilder von Liveprozessen erfassen, um den verwalteten Heap einer Anwendung zu analysieren.

  • dotnet-trace ermöglicht das Erfassen von Ablaufnachverfolgungen von Anwendungen, um die Leistung zu analysieren.

Ablaufverfolgung mithilfe von Umgebungsvariablen

Der bevorzugte Mechanismus zur Verwendung von EventPipe ist die Verwendung von dotnet-trace oder der Microsoft.Diagnostics.NETCore.Client-Bibliothek.

Sie können jedoch die folgenden Umgebungsvariablen verwenden, um eine EventPipe-Sitzung für eine App einzurichten und die Ablaufverfolgung direkt in eine Datei zu schreiben. Beenden Sie die Anwendung, um die Ablaufverfolgung zu beenden.

  • DOTNET_EnableEventPipe: Legen Sie diese Umgebungsvariable auf 1 fest, um eine EventPipe-Sitzung zu starten, die die Ablaufverfolgung direkt in eine Datei schreibt. Der Standardwert ist 0.

  • DOTNET_EventPipeOutputPath: Dies ist der Pfad zur ausgegebenen EventPipe-Ablaufverfolgungsdatei, wenn diese für die Ausführung über DOTNET_EnableEventPipe konfiguriert ist. Der Standardwert ist trace.nettrace, der in demselben Verzeichnis erstellt wird, über das die App ausgeführt wird.

    Hinweis

    Ab .NET 6 werden Instanzen der Zeichenfolge {pid} in DOTNET_EventPipeOutputPath durch die Prozess-ID des Prozesses ersetzt, der überwacht wird.

  • DOTNET_EventPipeCircularMB: Dies ist ein Hexadezimalwert, der die Größe des internen EventPipe-Puffers in Megabyte darstellt. Dieser Konfigurationswert wird nur verwendet, wenn EventPipe für die Ausführung über DOTNET_EnableEventPipe konfiguriert ist. Die Standardpuffergröße beträgt 1024 MB. Dies bedeutet, dass die Umgebungsvariable auf 400 festgelegt wird, da 0x400 == 1024.

    Hinweis

    Wenn der Zielprozess zu häufig Ereignisse schreibt, kann dieser Puffer überlaufen, und einige Ereignisse werden möglicherweise verworfen. Wenn zu viele Ereignisse verworfen werden, erhöhen Sie die Puffergröße, um zu ermitteln, ob sich die Anzahl der verworfenen Ereignisse verringert. Wenn die Anzahl der verworfenen Ereignisse bei einer größeren Puffergröße nicht abnimmt, kann dies daran liegen, dass ein langsamer Leser verhindert, dass die Puffer des Zielprozesses geleert werden.

  • DOTNET_EventPipeProcNumbers: Legen Sie diese Variable auf 1 fest, damit Prozessornummern in EventPipe-Ereignisheadern erfasst werden können. Standardwert: 0.

  • DOTNET_EventPipeConfig: Hiermit wird die EventPipe-Sitzungskonfiguration eingerichtet, wenn eine EventPipe-Sitzung mit DOTNET_EnableEventPipe gestartet wird. Die Syntax ist wie folgt:

    <provider>:<keyword>:<level>

    Sie können auch mehrere Anbieter angeben, indem Sie sie mit einem Komma verketten:

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

    Wenn diese Umgebungsvariable nicht festgelegt ist, EventPipe aber durch DOTNET_EnableEventPipe aktiviert wird, wird die Ablaufverfolgung gestartet, indem die folgenden Anbieter mit den folgenden Schlüsselwörtern und Ebenen aktiviert werden:

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

    Weitere Informationen zu einigen der bekannten Anbieter in .NET finden Sie unter Bekannte Ereignisanbieter.

Hinweis

In .NET 6 ist das Präfix DOTNET_ statt COMPlus_ Standard für Umgebungsvariablen, die das .NET-Runtimeverhalten konfigurieren. Das Präfix COMPlus_ funktioniert jedoch weiterhin. Wenn Sie eine frühere Version der .NET-Runtime verwenden, sollten Sie weiterhin das Präfix COMPlus_ für Umgebungsvariablen verwenden.