MSDN Magazin > Home > Ausgaben > 2007 > April >  Ereignisablaufverfolgung: Verbessertes Debuggin...
Ereignisablaufverfolgung
Verbessertes Debugging und Leistungsoptimierung mit ETW
Dr. Insung Park and Ricky Buch

Themen in diesem Artikel:
  • Erläuterungen zur ETW-Architektur
  • Neuerungen bei ETW in Windows Vista
  • Programmieren mit den Ereignisanbieter-APIs
In diesem Artikel werden folgende Technologien verwendet:
Windows Vista
Die zunehmende Größe und Komplexität heutiger Softwaresysteme machen Softwareentwicklung und -verwaltung zu einer großen Herausforderung. Alle Ausführungszustände zu berücksichtigen ist beinahe unmöglich. Anwendungen zeigen oft ein für Entwickler unerwartetes Verhalten. Ferner trägt eine enorme Anzahl von Hardwarekombinationen und eine sich ständig ändernde Arbeitsbelastung zu den Schwierigkeiten bei, die bei der Diagnose verschiedener Softwareprobleme auftreten. Es überrascht nicht, dass Zuverlässigkeit und Verwaltbarkeit an sich zu wichtigen Features werden. Diese Features machen Instrumentation erforderlich.
Eine raffinierte Instrumentation einiger wichtiger Fehlerzustände bei der Softwareausführung kann zu einem viel schnelleren Debuggen von Problemen führen. Instrumentation ist auch in anderen Fällen nützlich. Bestimmte unerwünschte Situationen, z. B. Software- und Hardwarefehler und Zustände niedriger Ressourcen, müssen überwacht und in einer verwalteten Geschäftsumgebung für eine große Gruppe Computer bearbeitet werden. Außerdem kann Instrumentation sehr hilfreich beim Lösen von Leistungsproblemen sein. Sie sind schwierig zu diagnostizieren, da sie von externer Arbeitsbelastung, Konfigurationsparametern und dem zugrunde liegenden Hardware- und Softwarestatus abhängig sind. Die Ablaufverfolgung eines Produktionscomputers während einer Leistungsverschlechterung kann es Entwicklern und Administratoren möglich machen, schlecht funktionierende Komponenten oder Dienste zu identifizieren oder Engpässe zu erkennen, die bei der Entwicklung nicht voraussehbar waren. Außerdem verwenden IT-Fachleute verschiedene Verwaltungstools, mit denen sie Ressourcennutzungsstatistiken aus Transaktionsablaufverfolgungen zur Kapazitätsplanung und Trendanalyse berechnen.
Ereignisablaufverfolgung für Windows® (ETW) ist eine allgemein gültige, schnelle Ablaufverfolgung, die vom Betriebssystem bereitgestellt wird. Mit einem im Kernel implementierten Puffer- und Protokollmechanismus stellt ETW einen Ablaufverfolgungsmechanismus für Ereignisse bereit, die von Anwendungen im Benutzermodus oder von Gerätetreibern im Kernelmodus ausgelöst werden. Zusätzlich gibt ETW Ihnen die Möglichkeit, die Protokollierung dynamisch zu aktivieren und zu deaktivieren, sodass Sie detaillierte Ablaufverfolgungen in Produktionsumgebungen einfach ohne Neustarts oder Anwendungsneustarts durchführen können. Der Protokollmechanismus verwendet Puffer für jeden Prozessor, die von einem asynchronen Schreibthread auf den Datenträger geschrieben werden. Dadurch verursachen große Serveranwendungen beim Schreiben von Ereignissen nur minimale Störungen.
ETW wurde zuerst mit Windows 2000 eingeführt. Seitdem wurde es in verschiedene Kern-OS- und Serverkomponenten zur Instrumentation von Aktivitäten aufgenommen und ist inzwischen eine der wichtigsten Instrumentationstechnologien auf Windows-Plattformen. Eine wachsende Anzahl von Drittanbieteranwendungen verwendet ETW ebenso für Instrumentation, und einige nutzen die Ereignisse, die von Windows bereitgestellt werden. ETW wurde auch in die Softwareablaufverfolgungstechnologie von Windows-Präprozessor (WPP) abstrahiert. So steht ein Satz einfach zu verwendender Makros für die Ablaufverfolgung von Meldungen des Stils „printf“ für das Debuggen während der Entwicklung zur Verfügung.
Auf Windows Vista™ ist ETW bedeutend aktualisiert worden, wobei eine der wichtigsten Änderungen die Einführung eines einheitlichen Ereignisanbietermodells und der zugehörigen APIs ist. Kurz gesagt, werden in den neuen einheitlichen APIs die Protokollierung von Ablaufverfolgungen und das Schreiben in die Ereignisanzeige in einem konsistenten, einfach einsetzbaren Mechanismus für Ereignisanbieter kombiniert. Gleichzeitig wurden mehrere neue Features für eine verbesserte Entwickler- und Endbenutzererfahrung hinzugefügt. In diesem Artikel führen wir das neue ETW-Anbietermodell ein und beschreiben, wie Entwickler das neue Modell in Windows Vista-basierten Anwendungen anpassen können.
Wir beginnen mit einem Überblick über die ETW-Architektur und das Nutzungsmodell und beschreiben dann das neue Ereignismodell und die APIs. Nachfolgend geben wir eine kurze Einweisung zur Entwicklung und Implementierung von Ereignisinstrumentation, und schließlich sehen wir uns die mitgelieferten Tools für die Steuerung von ETW-Sitzungen und die Verarbeitung protokollierter Ereignisse an und analysieren sie hinsichtlich der Berichterstellung für höhere Ebenen.

Ereignisablaufverfolgung für Windows
Die Kernarchitektur von ETW ist in Abbildung 1 dargestellt. Danach gibt es vier Haupttypen von Komponenten in ETW: Ereignisanbieter, Controller, Verbraucher und Ereignisablaufverfolgungssitzungen. Das Puffern und Protokollieren findet in Ereignisablaufverfolgungssitzungen statt, die Ereignisse aufnehmen und eine Ablaufverfolgungsdatei erstellen. Es gibt verschiedene Modi zur Protokollierung von ETW-Sitzungen. Zum Beispiel kann eine Sitzung so konfiguriert werden, dass Ereignisse direkt an Verbraucheranwendungen geliefert werden oder alte Ereignisse in einer Datei bei Erreichen einer bestimmten Größe durch Wrapping überschrieben werden. Ein separat für jede Sitzung erstellter Schreibthread überträgt sie in eine Datei oder an Echtzeitverbraucheranwendungen. Um höchste Leistung zu ermöglichen, werden Puffer für jeden Prozessor verwendet, durch die eine Sperre im Protokollierpfad nicht mehr nötig ist.
Abbildung 1 ETW-Architektur (Klicken Sie zum Vergrößern auf das Bild)
Ein Ereignisanbieter ist eine logische Entität, die Ereignisse in ETW-Sitzungen schreibt. Jede aufzeichnungsfähige Aktivität von Bedeutung kann ein Ereignis sein, und jede Aktivität wird durch ein in ETW protokolliertes Ereignis dargestellt. Ein Ereignisanbieter kann eine Anwendung im Benutzermodus, eine verwaltete Anwendung, ein Treiber oder eine andere Softwareentität sein. Die einzige Anforderung ist, dass der Ereignisanbieter eine Anbieter-ID über die Registrierungs-API bei ETW registrieren muss. Ein Anbieter registriert sich zuerst bei ETW und schreibt durch Aufrufen der ETW-Protokollierungs-API Ereignisse von verschiedenen Stellen im Code aus. Wenn ein Anbieter von der ETW-Controlleranwendung dynamisch aktiviert wird, senden Aufrufe der Protokollierungs-API Ereignisse an eine bestimmte Ablaufverfolgungssitzung, die vom Controller angegeben wird. Jedes Ereignis, das vom Ereignisanbieter zur Ablaufverfolgungssitzung gesendet wird, besteht aus einem festen Header, der Ereignismetadaten und zusätzliche veränderliche Daten aus dem Benutzerkontext umfasst. Aufgrund der wachsenden Ereignisinstrumentation in vielen OS-Komponenten enthält sogar eine einfache Anwendung für Windows Vista bereits mehrere Komponenten, die Ereignisanbieter sind.
Wenn ein Ereignis in einer Sitzung protokolliert wird, fügt ETW den vom Benutzer bereitgestellten Daten ein paar zusätzliche Datenelemente hinzu. Das sind zum Beispiel der Zeitstempel, die Prozess- und Thread-ID, die Prozessornummer und CPU-Nutzungsdaten des protokollierenden Threads. Diese Datenelemente werden im ETW-Ereignisheader aufgezeichnet und zusammen mit dem veränderlichen Ereignisinhalt des Anbieters an die Ereignisverbraucher übergeben. Für viele Ablaufverfolgungsverbraucher machen diese Datenfelder einen wichtigen Teil der Analyse aus.
Ein Controller startet und beendet ETW-Sitzungen und lässt Anbieter für sie zu. In einigen Szenarios, zum Beispiel bei Debugging und Diagnose, wird ein Controllertool bedarfsgesteuert zur Sammlung von detaillierten Ablaufverfolgungen aufgerufen. Für Ereignisse, die auf Admin zielen (wir definieren diese in einem späteren Abschnitt) und daher ständig an die Ereignisanzeige übergeben werden müssen, werden Anbieter automatisch bei der Registrierung vom Ereignisprotokolldienst aktiviert. Ein Controller muss die Berechtigung zu ETW bei Windows Vista haben, um Sitzungen zu steuern. Diese Berechtigung wird nur einer kleinen Gruppe besonderer Benutzer standardmäßig erteilt.
Ein Verbraucher schließlich ist eine Anwendung, die Protokolldateien liest oder in Echtzeit auf Ereignisse einer Sitzung wartet und diese dann verarbeitet. Der Ereignisverbrauch ist rückrufbasiert: ein Verbraucher registriert einen Ereignisrückruf, den ETW für jedes Ereignis getrennt aufruft. Ereignisse werden in chronologischer Reihenfolge an den ETW-Verbraucher übergeben. Es gibt Mehrzweck-Ereignisverbrauchertools, die die Ereignisse in verschiedenen Formaten sichern. Abbildung 2 zeigt eine XML-Sicherung eines „Prozess“-Ereignisses des Kernelanbieters, wie sie vom Tool tracerpt.exe in Windows Vista generiert wird. Dieses Ereignis zeigt den Start eines Editor-Prozesses an. Da Ereignisse benutzerdefinierte Inhalte enthalten, die vom Anbieter protokolliert werden, sind Metadaten erforderlich, um diese richtig zu decodieren. Die Anbieter, die die neuen APIs verwenden, müssen ein Ereignismanifest mitliefern – eine XML-Datei, die alle von Anbietern geschriebenen Ereignisse sowie die zugehörigen Layoutinformationen definiert. Eine Mehrzweck-Verbraucheranwendung verwendet APIs von Trace Data Helper (TDH), um die Ereignismetadaten abzurufen, die Ereignisse zu decodieren und sie anzuzeigen.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Guid="{9e814aad-3204-11d2-9a82-006008a86939}" />
        <EventID>0</EventID>
        <Version>2</Version>
        <Level>0</Level>
        <Task>0</Task>
        <Opcode>1</Opcode>
        <Keywords>0x0</Keywords>
        <TimeCreated SystemTime="2006-12-18T12:26:27.887309500Z" />
        <Correlation 
            ActivityID="{00000000-0000-0000-0000-000000000000}" />
        <Execution ProcessID="3396" ThreadID="3260" ProcessorID="0" 
            KernelTime="390" UserTime="195" />
        <Channel />
        <Computer />
    </System>
    <EventData>
        <Data Name="UniqueProcessKey">0xFFFFFA800143FA80</Data>
        <Data Name="ProcessId">0x10EC</Data>
        <Data Name="ParentId">0xD44</Data>
        <Data Name="SessionId">1</Data>
        <Data Name="ExitStatus">0</Data>
        <Data Name="UserSID">guest</Data>
        <Data Name="ImageFileName">notepad.exe</Data>
        <Data Name="CommandLine">notepad</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Opcode>Start</Opcode>
        <Provider>MSNT_SystemTrace</Provider>
        <EventName xmlns=
            "http://schemas.microsoft.com/win/2004/08/events/trace">
            Process</EventName>
        </RenderingInfo>
        <ExtendedTracingInfo xmlns="
            http://schemas.microsoft.com/win/2004/08/events/trace">
        <EventGuid>{3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c}</EventGuid>
        </ExtendedTracingInfo>
</Event>
Für viele bedeutet eine Ablaufverfolgung die Sammlung von Ereignissen von bestimmten, interessanten Anbietern. In dieser Denkweise ist eine Ereignisablaufverfolgungssitzung in einer konzeptionellen Sammlung eng mit einem oder mehreren Anbietern verbunden, und die Sitzung an sich (das Protokollierungsmodul) wird oft übersehen. Die ETW-Architektur ermöglicht eine dynamischere und flexiblere Ablaufverfolgungs- und Ereignisverwaltung. Sitzungen und Anbieter werden hier getrennt. Ein Controller startet und beendet ETW-Sitzungen und lässt dynamisch Anbieter zu Sitzungen zu. Folglich kann ein Controller eine Gruppe Anbieter für eine Sitzung zulassen, einige von ihnen nach einer Weile deaktivieren und einen weiteren Anbieter später für dieselbe Sitzung aktivieren. Sitzungen laufen im Kernel ab und sind nicht statisch an Anbieter gebunden. Ebenso wissen Anbieter normalerweise nicht, von welchen Sitzungen ihre Ereignisse protokolliert werden. Es gibt umfangreiche Anwendungen und Dienste, die gleichzeitig Anbieter, Controller und Verbraucher sind. APIs für alle Vorgänge werden für Anbieter, Controller und Verbraucher bereitgestellt, und Anwendungen können alle möglichen Kombinationen dieser Rollen einnehmen. Im Allgemeinen implementieren Entwickler jedoch nur Ereignisanbieter und verwenden mitgelieferte Tools, um Ablaufverfolgungen zu sammeln und anzuzeigen.
Einer der Vorteile der Trennung von Anbietern und Ablaufverfolgungssitzungen ist, dass Ablaufverfolgungen immun gegen Anwendungsprobleme wie Abstürze oder Hängen werden. Vor einem Absturz von Anbietern protokollierte Ereignisse werden im Kernelspeicher oder in einer Ablaufverfolgungsdatei gespeichert, was beim Debuggen von Anwendungsanomalien sehr nützlich sein kann.
Wie schon erwähnt, werden Ereignisse von Entwicklern, IT-Administratoren und Verwaltungstoolentwicklern zum Debuggen, Überwachen, Diagnostizieren und zur Kapazitätsplanung eingesetzt. Die üblichen, auf Ereignissen basierenden Analysemethoden können in folgende Verfahren eingeteilt werden.
Scannen Benutzer scannen durch die Ereignissicherung, um ein einziges wichtiges Ereignis oder ein kleines Muster bekannter Ereignisse zu finden. Scannen wird normalerweise eingesetzt, wenn Ereignisse zum Debuggen von Fehlerfällen verwendet werden, die Endbenutzerproblemen ähneln, oder um im Ereignisprotokoll nach bedeutenden Fehlern zu suchen.
Deltaanalyse ETW zeichnet Zeitstempel und CPU-Nutzungszahlen für jedes Ereignis auf, z. B. eine einfache Deltaanalyse der folgenden Form:
Property (Event B)-Property (Event A)
Daher wird eine Antwortzeit- und CPU-Nutzungsstatistik von Anwendungsaktivitäten ermöglicht. Wenn zwei Ereignisse den Anfang und das Ende einer Aktivität festlegen, kann so mit einem großen Satz Ereignissen, die von Anwendungen im Produktionsmodus gesammelt wurden, eine Zusammenfassung von Antwortzeit- und CPU-Nutzungsstatistik erstellt werden.
Statistische Analyse Manchmal ist es sehr aufschlussreich hinsichtlich des Softwareverhaltens, einfach bestimmte Ereignisse zu zählen.
Statusmechanismus und Ressourcenüberwachung Ein ausreichender Satz Ereignisse aktiviert die Konstruktion eines Statusmechanismus und daraufhin einer auf Ablaufverfolgung basierten Simulation. Da die Mehrheit der Haupt-OS-Aktivitäten mit ETW-Ereignissen instrumentiert ist, können zum Beispiel OS-Ablaufverfolgungen zur Entwicklung eines Statusmechanismus verwendet werden, der den Verlauf von Planer, Speicher, E/A-Aktivitäten und so weiter verfolgt.
End-to-End-Ablaufverfolgung Große Anwendungen bestehen oft aus einer Anzahl verteilter Komponenten, die über komplizierte Zusammenschaltungen integriert sind. Sie umfassen vielfach mehrere Computer, von denen jeder eine unterschiedliche Rolle einnimmt. Eine auf Anforderungsverfolgung eingestellte Instrumentation ist einer der Ansätze, um die zunehmenden Schwierigkeiten bei der Diagnose in dieser Art Umgebung zu bewältigen. In diesem Framework sind Instrumentationspunkte an mehreren Stellen der Anwendungen eingefügt, die Aktivitäten zusammen mit der eindeutigen ID für die Anforderung, die gerade abgewickelt wird, aufnehmen. Nachdem dem Sammeln der Ablaufverfolgungen werden Ereignisse, die der gleichen Anforderung entsprechen, während des Ereignisverbrauchs korreliert, sodass Aktivität und Fortschritt dieser Ereignisse verfolgt werden kann. Später kann eine bestimmte Anforderung von Interesse einzeln auf Probleme in verschiedenen Dienstphasen hin analysiert bzw. eine Gruppe Anforderungen in einer statistischen Analyse zusammengefasst werden. Server Performance Advisor (SPA), erhältlich vom Microsoft Download Center, ist ein Serververwaltungs- und Diagnosetool, das eine für End-to-End-Ablaufverfolgung entwickelte Serverinstrumentation einsetzt.

Das einheitliche Ereignisanbietermodell und die zugehörigen APIs
In Windows Vista wird ein neuer Satz von Ereignisanbieter-APIs eingeführt, der leichter zu verwenden ist und gleichzeitig mehr Funktionen und erweiterte Sicherheitsoptionen bietet. Die neuen APIs werden auch dazu eingesetzt, die Ereignisanzeige zu schreiben und damit die Ablaufverfolgungs- und Ereignisprotokolle in einem konsistenten API-Satz zu vereinen. In diesem Abschnitt werden das Modell und die APIs genauer beschrieben. Gegebenenfalls werden die Unterschiede zwischen den neuen und den bestehenden APIs aufgezeigt.
Um ETW-Anbieter zu werden, muss sich eine Softwarekomponente über API EventRegister bei ETW registrieren. EventRegister erfordert eine GUID namens ProviderId, mit der der Anbieter eindeutig identifiziert wird. Jede Softwareentität (Anwendung, freigegebene DLL oder Treiber) kann sich als Anbieter registrieren, da ein Anbieter nicht an eine OS-Entität gebunden sein muss. Die Registrierung findet normalerweise am Einstiegspunkt der Komponente statt: zum Beispiel bei einer DLL-Anfügeroutine oder einer Treibereingabe. Ein Registrierungshandle wird zurückgegeben, der in nachfolgenden, protokollierenden API-Aufrufen verwendet wird. Schließlich wird am Ende der Anbieterausführung EventUnregister aufgerufen.
Bei den vorhandenen Anbieter-APIs müssen Anbieter einen Rückruf zum Aktivieren/Deaktivieren der Benachrichtigung bereitstellen. Das bedeutet, dass bei Aktivierung eines Anbieters durch einen Controller die registrierte Rückruffunktion mit der Einstellung zum Aktivieren aufgerufen wird. Einer der Parameter des Rückrufs ist ein Handle für die Sitzung, für die der Anbieter zugelassen ist. Bei Empfang eines aktivierenden Rückrufs legt der Anbieter eine globale Variable (wie TracingOn) fest, um anzuzeigen, ob die Ablaufverfolgung ein- oder ausgeschaltet ist und um den Sitzungshandle zu speichern. Dann verwendet er diesen Sitzungshandle, den er vom Rückruf erhalten hat, bei protokollierenden API-Aufrufen (die auf dem Wert von TracingOn basieren).
Im neuen ETW-Anbietermodell werden die aktivierenden Einstellungen für die Anbieter von ETW gespeichert. Anbieter registrieren also protokollierende Aufrufe und können diese auslösen, ohne vorher zu prüfen, ob sie derzeit aktiviert sind. Innerhalb der protokollierenden API prüft ETW schnell die aktivierenden Einstellungen und sendet Ereignisse nur an Sitzungen, wenn diese aktiviert sind. Wenn sie nicht aktiviert sind, wird der protokollierende Aufruf verworfen. Die Aktivierung/Deaktivierung von Rückrufen ist also im neuen Modell optional. Ein aktivierender Rückruf kann jedoch in einigen Szenarios immer noch erforderlich sein. Eine für einen Statusmechanismus beabsichtigte Instrumentation zum Beispiel erfordert oft einen Snapshot oder Status-Rundown-Ereignisse am Anfang und Ende der Ablaufverfolgung.
Die protokollierende API, EventWrite, nimmt einen Registrierungshandle auf (im Gegensatz zu einem Sitzungshandle im alten Modell). Die Verwendung eines Registrierungshandles in protokollierenden Aufrufen macht die aktivierenden Einstellungen transparent für Anbieter. Da der Handle, der beim Protokollieren verwendet wird, im neuen Modell ein nicht transparenter Handle ist, kann ETW jetzt Multicasting von Ereignissen durchführen. Das heißt, ein Anbieter kann zu mehr als einer ETW-Sitzung zugelassen werden, was im alten Modell mit Sitzungshandle nicht möglich war.
ETW stellt getrennte APIs bereit, EventEnabled und EventProviderEnabled, die testen, ob der Anbieter aktiviert ist. Obwohl die protokollierenden APIs bereits vor dem Schreiben von Ereignissen die Aktivierung prüfen, ist für Anbieter bei aktivierter Ablaufverfolgung bisweilen zusätzliche Arbeit nötig. Ein solches Szenario beinhaltet das Sammeln und Erstellen von Informationsereignisdaten, die nicht unbedingt für die Programmausführung erforderlich sind. Mit diesen APIs kann ein Anbieter jederzeit herausfinden, ob Ablaufverfolgung ggf. aktiviert ist.
Wie bereits erklärt, können Benutzer jedem Ereignis veränderliche Kontextdaten hinzufügen. Die protokollierende API nutzt einen Scatter/Gather-Mechanismus zur Aufnahme ereignisspezifischer Datenelemente. Anrufer übergeben zusätzliche Ereignisdatenelemente durch die Konstruktion eines Arrays von Datenbeschreibungen. Eine Datenbeschreibung ist eine Struktur mit Zeiger- und Größenfeldern. Folglich fügen Benutzer für jedes Datenelement, das protokolliert werden soll, eine Datenbeschreibung hinzu. Mit einem Makro (EventDataDescCreate) ist die Konstruktion einer Datenbeschreibung ganz einfach. ETW kopiert dann während des Protokollierens von Benutzern bereitgestellte Inhalte in seine Sitzungspuffer.
Im entsprechenden Ereignismanifest sollte das Layout eines Ereignisses durch das Tag <Template> angegeben werden. Ein Template (eine Vorlage) beschreibt vom Benutzer angegebene Kontextdaten, die zu jedem Ereignis gehören. Das Layout kann durch die Vorlage definiert werden und einzelne Datenfelder enthalten, wie Ganzzahlen und Zeichenfolgen, oder komplizierte Datenstrukturen wie z. B. ein Array von Strukturen. Eine Vorlage ist nicht für alle Ereignisse erforderlich. Wenn keine Vorlage angegeben ist, wird angenommen, dass das Ereignis keine vom Benutzer bereitgestellten Daten enthält. Im Manifest kann eine Vorlage von mehreren Ereignissen genutzt werden, z. B. kann ein Start- und Stoppereignis die gleichen Kontextinformationen haben. Wenn eine Verbraucheranwendung auf ein Ereignis trifft, sucht sie über die TDH-APIS eine Ereignisvorlage und decodiert die veränderlichen Ereignisdaten entsprechend. Anbieter, die die alten APIs verwenden, geben Layoutinformationen über eine WMI-Schnittstelle (Windows Management Instrumentation) und verwaltete Objektformate (Managed Object Formats, MOFs) an.
Abbildung 3 enthält ein Beispiel für einen Anbietercode, der die neuen Ereignis-APIs für die Registrierung und Protokollierung verwendet. Dies ist ein Anbieter des Benutzermodus, der Anbieter-APIs im Benutzermodus nutzt. Ein entsprechender Satz Anbieter-APIs für den Kernelmodus ist ebenso verfügbar. Das erste Ereignis in Abbildung 3 schreibt zwei von Benutzern bereitgestellte Datenelemente. Eins ist vom Typ ULONG und das andere eine mit NULL beendete WCHAR-Zeichenfolge. EventDataDescCreate wird aufgerufen, um das zugehörige Datenbeschreibungsarray zu erstellen. Zusätzlich zur hier gezeigten API EventWrite gibt es zwei weitere protokollierende APIs: EventWriteString und EventWriteTransfer. EventWriteString ermöglicht das einfache Protokollieren einer Zeichenfolge ohne Manifest. Beim Aufrufen von EventWriteString markiert ETW den Header mit der Angabe, dass die Ereignisdaten aus einer WCHAR-Zeichenfolge bestehen, die mit einer einzigen NULL endet. Wenn ein Verbraucher dies im Header sieht, behandelt er die Benutzerdaten als Zeichenfolge, ohne über TDH nach dem Ereignisschema suchen zu müssen. Mit EventWriteString können Zeichenfolgen schnell und ohne Ändern des Manifests protokolliert werden.
#include <myevents.h>   // Header generated from manifest. 
                        // Contains MyProviderId and event descriptors.

REGHANDLE MyProvRegHandle;
ULONG MyInteger;
PWCHAR MyString;
ULONG MyStringLength;
EVENT_DATA_DESCRIPTOR DataDescriptor[2];

...

// Register the ETW provider.
Status = EventRegister(&MyProviderId,      // ProviderId (GUID)
                       NULL,               // Optional Callback 
                       NULL,               // OPtioanl Callback Context
                       &MyProvRegHandle);  // Registration Handle

...

// Construct DataDescriptor and write an event with 
// MyInteger and MyString.
EventDataDescCreate(&DataDescriptor[0],    // DataDescriptor
                    &MyInteger,            // Pointer to the data
                    sizeof(ULONG));        // Size of data
EventDataDescCreate(&DataDescriptor[1], &MyString, MyStringLength);

Status = EventWrite(MyProvRegHandle,       // Registration Handle
                    MyEventDescriptor1,    // EventDescriptor
                    2,                     // DataDescriptor array size
                    DataDescriptor);       // DataDescriptor array

...

// Write another event with no user data.
if (EventEnabled(MyProvRegHandle, MyEventDescriptor2)) {
    // Do extra work if enabled and write event.
    ...

    Status = EventWrite(MyProvRegHandle, MyEventDescriptor2, 0, NULL);
}

...

// Unregister the ETW provider. 
Status = EventUnregister(MyProvRegHandle);  
Mit den APIs EventWriteTransfer und EventActivityIdControl erreichen Sie die benötigte End-to-End-Ablaufverfolgungsinstrumentation. Wie bereits beschrieben, ist End-to-End-Ablaufverfolgung eine Instrumentationsmethode für Serveranwendungen, die für mehrere Benutzeranforderungen gleichzeitig verschiedene Aktivitäten ausführen. Zum Beispiel verlässt eine Anforderung zur Skriptausführung auf einer Webseite einen Clientcomputer und kommt in der Vermittlungsschicht auf einem Server an. Dann geht sie durch den HTTP-Treiber, IIS, das ASP.NET-Modul und vielleicht noch einen Exchange-Server auf einem anderen Computer. Das Ziel der End-to-End-Ablaufverfolgung ist, alle wichtigen Aktivitäten über ETW-Ereignisse bezüglich dieser Anforderung für eine spätere Debugging- und Leistungsanalyse aufzuzeichnen. Dafür ist eine eindeutige ID erforderlich, die einzelne Anforderungen identifizieren kann. Die Korrelation kann mit dieser eindeutigen Aktivitäts-ID während des Verbrauchs durchgeführt werden.
Durch ETW wird diese Anforderung erfüllt, da eine ActivityId für jedes Ereignis eingeführt wird. Jedes Ereignis, das mit der neuen API protokolliert wird, nimmt die momentan gültige, im Ausführungsthread gespeicherte Aktivitäts-ID automatisch zur Kenntnis. Die Aktivitäts-ID ist in der XML-Sicherung im Tag <Correlation ActivityId> im Abschnitt <System> sichtbar. Mit der API EventActivityIdControl kann der Anbieter eine Aktivitäts-ID für den Ausführungsthread abrufen, festlegen und erstellen. Die Aktivitäts-ID kann mit der Anforderung über mehrere Komponenten in Gebrauch bleiben. Leider ist es aufgrund öffentlicher Protokolleinschränkungen, Entwurfseinschränkungen und so weiter in einigen Fällen nicht möglich, die Aktivitäts-ID weiterzugeben. Die API EventWriteTransfer schreibt ein Übertragungsereignis, mit dem eine Übertragung von Aktivitäts-IDs angezeigt wird. Zusätzlich zu den Parametern von EventWrite übernimmt EventWriteTransfer zwei weitere Argumente: ActivityId und RelatedActivityId.
Jedes Ereignis ist mit der Anbieter-ID versehen. Zusätzlich wird ihm eine Entität namens Ereignisbeschreibung zugewiesen, die die Standardereignisinformationen definiert und weitere Identifikation und Semantiken bereitstellt. Entwickler bestimmen die Ereignisbeschreibungen für Instrumentationspunkte während der Instrumentationsentwurfsphase und schreiben entsprechende Einträge im Ereignismanifest. Dann generiert der Nachrichtencompiler einer Entwicklungsumgebung aus dem vorhandenen Manifest Ereignisbeschreibungen in einer Headerdatei. Diese Ereignisbeschreibungen werden dann in Quellcodedateien eingefügt und verwendet. Programmiertechnisch ist eine Ereignisbeschreibung eine Struktur, die aus den folgenden Feldern besteht: ID, Version, Kanal, Ebene, Opcode, Task und Schlüsselwörter:
typedef struct _EVENT_DESCRIPTOR {
    USHORT Id;
    UCHAR Version;
    UCHAR Channel;
    UCHAR Level;
    UCHAR Opcode;
    USHORT Task;
    ULONGLONG Keyword;
} EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR;
Eine Ereignis-ID wird verwendet, um ein Ereignis in einem Anbieter eindeutig zu identifizieren. Wenn ein Ereignis im Manifest definiert ist, ist die Ereignis-ID der einzig erforderliche Eintrag. Wenn ein Verbraucher auf ein Ereignis trifft, verwendet er seine Anbieter-ID (GUID) und Ereignis-ID (USHORT), um das Manifest für das Ereignis zu finden. Ebenso bietet eine Version die Möglichkeit, Ereignisse zu ändern und in späteren Veröffentlichungen mit denselben Semantiken und derselben Ereignis-ID zu erweitern. Deshalb kann ein Ereignis durch eine Ereignis-ID, die Version und die Anbieter-ID eindeutig identifiziert werden.
Ein Kanal definiert eine Gruppe von Ereignissen für ein Zielpublikum. Ein Kanal gehört einem der folgenden vier Typen an: admin, operativ, analytisch oder debug. Ereignisse, die für einen Adminkanal ausgelöst werden, ziehen Aktionen nach sich. Beim Empfang eines Ereignisses sollte der Administrator sofort wissen, warum das Ereignis ausgelöst wurde und was zu tun ist. Ereignisse, die für einen operativen Kanal verursacht werden, werden an Überwachungstools höherer Ebenen und Supportpersonal weitergeleitet. Sie bieten ausführlicheren Kontext und kommen häufiger vor als Ereignisse des Adminkanals. Ereignisse für den Admin- und den operativen Kanal werden automatisch an das Ereignisprotokoll gesendet und in der Ereignisanzeige angezeigt. Ein analytischer Kanal besteht für traditionelle Ablaufverfolgung, die für Supportexperten oder Diagnose- und Problembehandlungstools gedacht ist. Ein Debugkanal sollte für Debugnachrichten verwendet werden und Ereignisse enthalten, die normalerweise von Entwicklern genutzt werden. Ereignisse für analytische und Debugkanäle sind standardmäßig nicht aktiviert. Durch Kanäle können Ereignisse, die für verschiedene Zwecke und Zielgruppen gedacht sind, mit nur einem Satz APIs hinzugefügt werden.
Beim Aktivieren eines Anbieters kann ein Controller eine Ebene (1-Byte-Ganzzahl) und Schlüsselwörter (8-Byte-Masken) angeben. Die Ebene und die Schlüsselwörter werden verwendet, um der ETW-Instrumentation Dimensionen hinzuzufügen. Die Ebene wird so entworfen, dass eine Filterung basierend auf dem Schweregrad oder der Ausführlichkeit von Ereignissen möglich ist. Das Schlüsselwort ist so konzipiert, dass damit die Unterkomponenten eines Anbieters angegeben werden. Entwickler können zum Beispiel Ereignisse in informative Ereignisse und kritische Fehler einteilen. Ebenso können sie Unterkomponenten der Anwendung verschiedene Schlüsselwörter zuweisen. Durch selektives Aktivieren mit verschiedenen Ebenen und Schlüsselwörtern kann der Ablaufverfolgungscontroller Anbieter nur zum Protokollieren von Fehlerereignissen von Unterkomponente B zulassen, oder zum Protokollieren aller Ereignisse der Unterkomponenten A und C und so weiter. Für Anbieter, die die alten APIs verwenden, besteht ein Schlüsselwort aus 4 Bytes, und eine Filterung nach Ebene und Schlüsselwort muss explizit im Anbietercode festgelegt werden. Beachten Sie Folgendes: Wenn ein Controller eine bestimmte Ebene aktiviert, werden alle Ereignisse mit einem gleichen oder niedrigeren Ebenenwert (einem gleichen oder höheren Schweregrad) ebenso aktiviert. Ebenen und Schlüsselwörter können zwar benutzerdefiniert sein und Ereignissen durch Entwickler zugewiesen werden, aber es gibt trotzdem vordefinierte Ebenen, wie in Abbildung 4 gezeigt.
<levels>
    <level name="win:LogAlways" symbol="WINEVENT_LEVEL_LOG_ALWAYS" 
        value="0" message="$(string.level.LogAlways)"> Log Always 
    </level>
    <level name="win:Critical" symbol="WINEVENT_LEVEL_CRITICAL" value="1" 
        message="$(string.level.Critical)"> Only critical errors </level>
    <level name="win:Error" symbol="WINEVENT_LEVEL_ERROR" value="2" 
        message="$(string.level.Error)"> All errors, includes win:
        Critical </level>
    <level name="win:Warning" symbol="WINEVENT_LEVEL_WARNING" value="3" 
        message="$(string.level.Warning)"> All warnings, includes
        win:Error </level>
    <level name="win:Informational" symbol="WINEVENT_LEVEL_INFO"
        value="4" 
        message="$(string.level.Informational)"> All informational 
        content, including win:Warning </level>
    <level name="win:Verbose" symbol="WINEVENT_LEVEL_VERBOSE" value="5" 
        message="$(string.level.Verbose)"> All tracing, including 
        previous levels </level>
</levels>
Tasks und Opcode werden verwendet, um jedem Ereignis zusätzliche Informationen anzufügen. Eine Task gibt eine gemeinsame logische Komponente oder Task an, die instrumentiert wird. Die Task stellt oft die wichtigsten Schritte auf höherer Ebene dar, die eine Komponente ausführt, um ihren Zweck zu erfüllen. Ein Opcode gibt den bestimmten Vorgang an, der beim Schreiben des Ereignisses durchgeführt wird. Der Windows-Kernelanbieter gruppiert zum Beispiel alle Datei-E/A-Vorgangsereignisse in einer Task „FileIO“. Opcode zeigt an, welcher Vorgang durchgeführt wurde, z. B. Erstellen, Öffnen, Lesen und Schreiben. Im Unterschied zu ID, Version, Kanal, Ebene und Schlüsselwort werden Tasks und Opcode nur zum Hinzufügen von Informationen verwendet. Sie haben daher keine Auswirkung auf die Steuerung der Instrumentation oder das Suchen von Metadaten.
Die Ereignisbeschreibungen und Layouts sind im Ereignismanifest angegeben. Entwickler schreiben das Ereignismanifest beim Entwerfen der Instrumentation. Ein Ereignismanifest wird in XML geschrieben, wobei benutzerdefinierte Kanäle, Tasks, Opcodes, Ebenen und Schlüsselwörter in entsprechenden XML-Tags angegeben werden. In ETW vordefinierte Kanäle, Ebenen und Opcodes können ebenso verwendet werden. Die vordefinierten Kanäle verweisen jedoch auf globale Kanäle und sollten nur für Ereignisse genutzt werden, die auf Admin zielen. Die verschiedenen Metadatenfelder werden für jedes Ereignis kombiniert und in einem <Event>-Tag definiert, das eindeutig mit einer Ereignis-ID verbunden ist. Ein Ereignis kann auch eine Nachrichtenzeichenfolge beinhalten, die mit ersetzten Werten aus den Ereignisdaten angezeigt wird, wenn das Ereignis von einem Verbraucher gelesen wird. Abbildung 5 zeigt ein XML-Fragment eines Beispielereignismanifests. Später werden wir eine Schritt-für-Schritt-Anleitung zum Entwerfen der Ereignisinstrumentation und der Instrumentation an sich vorstellen.
<provider name="Microsoft-Windows-Kernel-Registry" 
    guid="{70eb4f03-c1de-4f73-a051-33d13d5413bd}" 
    symbol="RegistryProvGuid"
    resourceFileName="%SystemRoot%\System32\advapi32.dll" 
    messageFileName="%SystemRoot%\System32\advapi32.dll">
  <channels>
    <channel name="Microsoft-Windows-Kernel-Registry/Analytic" 
        chid="RegistryEvents" symbol="REG_Events" type="Analytic" 
        isolation="System">This channel contains registry 
        events.</channel>
  </channels>
  <opcodes>
    <opcode value="32" name="CreateKey" symbol="" />

    ...

  </opcodes>
  <keywords>
    <keyword name="CreateKey" symbol="" mask="0x1000" />

    ...

  </keywords>
  <templates>
    <template tid="tid_RegOpenCreate">
      <data name="BaseObject" inType="win:Pointer" 
         outType="win:HexInt64" />
      <data name="KeyObject" inType="win:Pointer" 
          outType="win:HexInt64" />
      <data name="Status" inType="win:UInt32" 
          outType="win:HexInt32" />
      <data name="Disposition" inType="win:UInt32" />
      <data name="BaseName" inType="win:UnicodeString" 
          outType="xs:string" />
      <data name="RelativeName" inType="win:UnicodeString" 
          outType="xs:string" />
    </template>

    ...

  </templates>
  <events>
    <event value="1" symbol="ETW_REGISTRY_EVENT_CREATE_KEY" 
        template="tid_RegOpenCreate" opcode="CreateKey" 
        channel="RegistryEvents" level="win:Informational" 
        keywords="CreateKey" 
        message="$(string.Registry.RegOpenCreate)"/>

        ...

      </events>
    </provider>

      ...

  <localization>
    <resources culture="en-US">
      <stringTable>
        <string id="Registry.RegOpenCreate" 
            value="Registry key %6 was created with status %3." />
      </stringTable>
    </resources>
  </localization>
Verwaltete ETW-Anbieter-APIs werden auch im Microsoft® .NET Framework 3.5, Codename „Orcas“, verfügbar sein. Verwaltete Verbraucher- und Controller-APIs sind derzeit in der Planungsphase. System.Diagnostics.Eventing enthält die Klasse EventProvider. EventProvider bietet Methoden für alle oben beschriebenen Funktionalitäten für systemeigene Anwendungen. Benutzer müssen die Klasse mit einer Anbieter-GUID instanziieren und die Klasseninstanz zur Protokollierung von Ereignissen nutzen. EventDescriptor ist eine Struktur, die den Ereignisbeschreibungen in den systemeigenen APIs entspricht. Anders als im systemeigenen Fall werden für verwaltete Anwendungen keine EventDescriptors generiert. Zurzeit wird jedoch ein Tool in Betracht gezogen, das Code für eine bessere Leistung und Überprüfung generieren kann. Ein Beispiel für die Nutzung von EventProvider ist in Abbildung 6 aufgeführt.
using System.Diagnostics.Eventing;
...

static void Main(string[] ArgRead)
{
    int MyInteger;
    string MyString;

    ...

    // Construct event descriptor.
    EventDescriptor Event1 = new EventDescriptor(5, 0, 0, 2, 0, 0, 0);

    // Instantiate event provider.
    EventProvider etwProvider = new EventProvider(
        new Guid("d58c126f-b309-11d1-969e-0000f875a5bc"));

    ...

    // Write an event with MyInteger and MyString.
    etwProvider.WriteEvent(ref Event1, MyInteger, MyString);

    ...
}
Außerdem bietet ETW auf Windows Vista verbesserte Sicherheitsoptionen für Anbieter. Standardmäßig kann sich jeder Anbieter registrieren und Ereignisse schreiben. Entwickler können jedoch Einschränkungen für eine GUID erstellen, sodass nur autorisierte Benutzer einen Anbieter mit dieser GUID registrieren können. Ein Anbieter kann auch angeben, wer ihn aktivieren kann. Außerdem ermöglicht es ETW einem Controller, eine Sitzung als sicher zu bezeichnen. Das heißt, dass sie Ereignisse nur von einer bestimmten Gruppe Benutzer empfängt.
Sobald der Binärinhalt mit der Ereignisanbieterinstrumentation kompiliert ist, wird der Anbieter installiert. Benutzer können dann mit dem Tool logman, einer integrierten Controlleranwendung, Ereignisse vom Anbieter sammeln. Der unten aufgeführte Befehl logman.exe gibt zwei Aufrufe an ETW-Steuer-APIs aus, die eine ETW-Sitzung namens mysession starten und einen Anbieter aktivieren:
> logman start mysession -p <provider name> -o mytest.etl -ets
Die Sitzung mysession schreibt Ereignisse in eine Datei namens mytest.etl. Es gibt mehrere Optionen für logman.exe, mit denen Protokolliermodi, Pufferkonfigurationen und weiteres angepasst werden können. An dieser Stelle kann <provider name> der Anbietername im Manifest oder in der GUID sein, die der Anbieter verwendet, um sich bei der API EventRegister zu registrieren. Wenn die Anbieter-GUID 11223344-5566-7788-99aa-bbccddeeff00 ist, sieht die tatsächliche Befehlszeile wie folgt aus:
> logman start mysession 
-p {11223344-5566-7788-99aa-bbccddeeff00} 
-o mytest.etl -ets
ETW ermöglicht es einem Controller, einen Anbieter vorläufig zu aktivieren, bevor dieser registriert und ausgeführt wird. Dadurch können Benutzer Startup-Ablaufverfolgungen für DLLs und Treiber sammeln, für die das Laden der Binärbilder nicht leicht zu steuern ist. Ein Controller startet eine Sitzung und aktiviert einen Anbieter, bevor der Anbieter mit der Ausführung beginnt. Sobald der Anbieter sich registriert, wird er aktiviert.
Wenn Ereignisse nach Bedarf gesammelt wurden, kann die Sitzung mit der Stoppoption in logman.exe beendet werden.
> logman stop mysession -ets
Eine Ablaufverfolgungsdatei namens mytest.etl müsste jetzt in dem Verzeichnis vorhanden sein, in dem der Befehl logman ausgeführt wurde. Tracerpt.exe kann dazu verwendet werden, die Ereignissicherung von dieser Datei abzurufen:
> tracerpt mytest.etl
Dieser Befehl erstellt eine Sicherungsdatei (standardmäßig dumpfile.xml) und eine Textzusammenfassungsdatei (standardmäßig summary.txt). Die Zusammenfassungsdatei enthält eine kurze Zusammenfassung der Ereignisstatistik. Die Sicherungsdatei enthält XML-Sicherungen der Ereignisse, wie z. B. die in Abbildung 2 gezeigte. Die Datenfelder des Ereignisheaders werden im Abschnitt <System> angezeigt. Prozess-ID, Thread-ID, Prozessor-ID und die CPU-Nutzung sind im Tag <Execution> innerhalb von <System> angegeben. Der Abschnitt <System> zeigt außerdem die Werte der Ereignisbeschreibungsfelder des Ereignisses an. Die Namen der Ausgabedateien können als Optionen des Befehls tracerpt.exe vom Benutzer angegeben werden. Es gibt noch weitere GUI-Tools auf Windows Vista, die Ablaufverfolgungen sammeln und anzeigen können. Wir kommen später auf diese zurück.
Auf Windows Vista gibt es bereits Hunderte von installierten Ereignisanbietern. Benutzer können die Liste dieser Anbieter mit PerfMon, der Ereignisanzeige oder mit dem Befehl logman.exe sehen:
> logman query providers

Entwurfs- und Implementierungsrichtlinien
In diesem Abschnitt beschreiben wir die Schritte zur Erstellung der Manifestdatei, die Ereignisse definiert, zur Instrumentierung von Code mit ETW-API-Aufrufen und zur erfolgreichen Entwicklung und Installation des Ereignisanbieters.
Entwerfen des Instrumentationsmanifestes Das Instrumentationsmanifest ist eine Datei im XML-Format, die den Ereignisanbieter und die an ETW zu protokollierenden Ereignisse definiert. Jedes Ereignis hat einen Abschnitt für Standardmetadaten und einen für veränderliche Ereignisdaten. Das Manifest kann entweder manuell oder mit dem in SDK verfügbaren Manifestgeneratortool (ecmangen.exe) erstellt werden. Die Schritte:
  1. Erstellen Sie einen Ereignisanbieter und bestimmen Sie seine Anbieter-ID, eine GUID.
  2. Definieren Sie die logischen Tasks der Komponente und die bestimmten Instrumentationspunkte innerhalb der logischen Tasks. Dies definiert die Tasks und Opcodes für die Ereignisse, die der Anbieter schreibt.
  3. Definieren Sie die Unterkomponenten, die Ereignisse protokollieren, und weisen Sie jeder Unterkomponente ein Schlüsselwort zu. Dies ermöglicht Controllern, Ereignisse nach Wahl zu aktivieren.
  4. Identifizieren Sie das jeweilige Zielpublikum der Ereignisse, die Sie entwerfen, und definieren Sie Kanäle für jedes Zielpublikum.
  5. Erstellen Sie die verschiedenen Konstrukte, die die veränderlichen Benutzerkontextdaten definieren. Dies wird im Abschnitt <templates> vorgenommen.
  6. Stellen Sie alles zusammen und definieren Sie Ereignisse im Abschnitt <events> des Manifestes. Weisen Sie jedem Ereignis eine symbolische Kennung, einen Schweregrad, Schlüsselwörter, einen Kanal, eine Task, einen Opcode und eine Vorlage zu. Eine lokalisierbare, ereignisspezifische Nachricht kann ebenso hinzugefügt werden.
Instrumentieren des Codes mit der ETW-API Nachdem die Ereignisse im Manifest definiert wurden, schreiben Sie mit den einheitlichen APIs Ereignisse an ETW. Generieren Sie für systemeigene Anwendungen zunächst eine Headerdatei, die die Ereignisdefinitionen des Manifestes enthält, damit sie dem Anbietercode hinzugefügt werden kann. Verwenden Sie dann die ETW-APIs, um die vorher entworfenen Ereignisse zu schreiben. So sieht der Prozess aus:
  1. Führen Sie den Nachrichtencompiler (mc.exe) auf dem oben beschriebenen Manifest aus. Dies generiert die Headerdatei, die Ereignisbeschreibungsstrukturen für die Ereignisse enthält, wobei jede Strukturinstanz denselben Namen wie die symbolische Kennung des Ereignisses hat. Der Nachrichtencompiler erstellt auch die Ressourcenzeichenfolgedatei. Die generierte Headerdatei muss in den Anbietercode eingefügt werden.
  2. Bevor Sie Code schreiben, um Ereignisse auszulösen, muss ein Anbieter sich mit der im Manifest definierten Anbieter-ID registrieren, indem er die Funktion EventRegister aufruft. Ein von EventRegister zurückgegebener Registrierungshandle sollte gespeichert werden, damit er für die Protokollierung von API-Aufrufen und den entsprechenden Aufruf von EventUnregister verwendet werden kann.
  3. Rufen Sie EventWrite auf, um die im Manifest definierten Ereignisse zu protokollieren. Die ereignisspezifischen Daten werden von einem Datenbeschreibungsarray übergeben, wie in Abbildung 3 dargestellt. (Entwickler müssen sicherstellen, dass die Datenfelder genau den jeweiligen Ereignisvorlagen entsprechen, die im Manifest angegeben wurden). Übergeben Sie die richtige Ereignisbeschreibungsstruktur, die in der Headerdatei für das Ereignis definiert wurde.
  4. Rufen Sie nach Protokollieren aller notwendigen Ereignisse EventUnregister auf und übergeben Sie den Registrierungshandle.
Kompilieren der instrumentierten Binärdateien Die Manifestinformationen, die die Ereignisse definieren, sollten während des Buildprozesses kompiliert und der ausführbaren Anbieterbinärdatei als Ressource angefügt werden. Alle lokalisierbaren Zeichenfolgen werden aus diesem kompilierten Manifest herausgenommen und in einer separaten Ressourcendatei abgelegt, die getrennt kompiliert und verlinkt werden muss. Wenn die Anbieterbinärdatei bereitgestellt ist, müssen die Manifestinformationen auf dem System installiert werden, damit sowohl Controller als auch Verbraucher den Ereignisanbieter und die Ereignisdefinitionen finden können. Alle erforderlichen Tools sind systemeigen auf Windows Vista oder in SDK verfügbar. Folgende Schritte sind nötig:
  1. Wenn es lokalisierbare Nachrichtenzeichenfolgen für diese Ereignisse gibt, ist es u. U. erforderlich, rc.exe auszuführen, um die Ressourcendatei in eine RES-Datei zu kompilieren.
  2. Wenn Visual Studio® verwendet wird, kann der Entwickler durch einen Befehl vor dem Build rc.exe ausführen lassen, um die kompilierte RES-Ressourcendatei zu generieren und diese in das Projekt einzufügen.
  3. Verknüpfen Sie die kompilierte Ressourcendatei entweder mit cl.exe oder link.exe (für Benutzer von Visual Studio ist dies Schritt 2), und kompilieren Sie die Anwendung oder den Treiber.
  4. Führen Sie beim Installieren des Anbieters das Tool wevtutil.exe mit der Option -im aus, um das Manifest zu installieren, das die Ereignisse definiert. Dies ermöglicht Controllern, die Ereignisanbieter zu entdecken und Verbrauchertools, die Informationen für die richtige Decodierung der Ereignisse zu finden.

Tools und Unterstützung
Bis jetzt haben wir logman.exe, einen Befehlszeilencontroller, und tracerpt.exe, ein allgemeines Verbrauchertool, verwendet. In logman.exe gibt es auch eine Option, mit der Sammlungen auf Remotecomputern geplant werden können. Mit tracerpt.exe ist es außerdem möglich, Ereignisse im CSV-Format zu sichern und mit der Option -report Ressourcenverbrauchsberichte für einige der bekannten Kern-OS-Ereignisse zu generieren. Abbildung 7 zeigt die Hotfiletabelle, die von tracerpt.exe nach der Verarbeitung und Korrelation einiger bekannter Kern-OS-Ereignisse auf Basis einer Entwicklungsmethode mit Statusmechanik erstellt wird.
Abbildung 7 Von tracerpt erstellter Hotfilebericht (Klicken Sie zum Vergrößern auf das Bild)
Der Zuverlässigkeits- und Leistungsmonitor (RPM, Reliability and Performance Monitor – beinhaltet in Windows Vista außerdem PerfMon) bietet eine grafische Schnittstelle für die Sammlung von Ablaufverfolgungen. Mit der Schnittstelle für Ereignisablaufverfolgungssitzungen können Benutzer eine Ablaufverfolgungssitzung einrichten, zu aktivierende Anbieter auswählen und ETW-Sitzungen starten und beenden. Abbildung 8 zeigt die Liste zu aktivierender Anbieter in RPM. Mit RPM wird das Konzept des Data Collector Set eingeführt, in dem alle erforderlichen Informationen hinsichtlich Ereignisablaufverfolgungen, Leistungsindikatoren und Konfigurationen von Datensammlungen (Registrierungs- und WMI-Klassen) in einem einzigen Sammlungssatz kombiniert werden. Benutzer können mit Anbietern, die für Ablaufverfolgungs- und Indikatordaten aktiviert sind, einen Datensammlungssatz erstellen. Danach werden die Einstellungen des Sammlungssatzes in RPM gespeichert, sodass Benutzer die Datensammlung einfach starten und beenden können, ohne jedes Mal bestimmte Quellen angeben zu müssen. Diese Funktion unterstützt allgemeine Diagnoseszenarios, in denen Benutzer die Anbieter angeben können, von denen Ablaufverfolgungen und Indikatoren für bekannte Diagnoseszenarios gesammelt werden sollen.
Abbildung 8 Ereignisablaufverfolgungsanbieter in RPM (Klicken Sie zum Vergrößern auf das Bild)
Die Ereignisanzeige bietet noch eine weitere Möglichkeit zum Sammeln und Anzeigen von Ereignissen. Die neuen Ereignis-APIs wurden auch für Ereignisse entworfen, die an das Ereignisprotokoll gerichtet sind. Ereignisse in Admin- sowie operativen Kanälen werden automatisch an die Ereignisanzeige weitergeleitet und dort angezeigt, damit sie hinsichtlich wichtiger Softwarestatus überwacht werden können. Die Ereignisanzeige umfasst auch Funktionalitäten für analytische und Debugereignisse. Die Option „Ansicht“ ermöglicht es, alle verfügbaren analytischen und Debugkanäle anzuzeigen. Benutzer können mit einem Klick mit der rechten Maustaste die jeweilige Ablaufverfolgungssammlung aktivieren. In Abbildung 9 hat ein Benutzer mit der rechten Maustaste auf einen analytischen Kanal des Anbieters von Registrierungsereignissen geklickt, um die Sammlung von Ablaufverfolgungen zu aktivieren.
Beispielcode für Anbieter-, Controller- und Verbraucher-APIs ist in Softwareentwicklungskits verfügbar. In Beispielanbietern, die die neuen Anbieter-APIs verwenden, sind Manifeste für die Ereignisse enthalten, die sie protokollieren. Ein Beispieltreiber ist ebenso verfügbar.
Abbildung 9 Schnittstelle der Ereignisanzeige für die Sammlung analytischer Ereignisse (Klicken Sie zum Vergrößern auf das Bild)

Schlussbemerkung
Wir haben das einheitliche Ereignisanbietermodell und die neuen APIs für ETW vorgestellt, die in Windows Vista enthalten sind. Unser Ziel ist, die APIs bei Entwicklern einzuführen und ihnen ein Nutzungsbeispiel und allgemeine Richtlinien bereitzustellen. Ablaufverfolgung ist vielen Entwicklern noch unbekannt, und wir hoffen, dass dieser Artikel Einsichten in eine der wichtigsten Instrumentations- und Diagnoseinfrastrukturen auf Windows-Plattformen bietet. Innerhalb der wenigen Jahre seit der Einführung als allgemeines Ablaufverfolgungstool im Windows 2000-Betriebssystem wurde ETW von einer Reihe Komponenten und Anwendungen als Basis für Ablaufverfolgungs- und Verwaltbarkeitsfunktionen eingesetzt, und dieser Trend setzt sich wahrscheinlich fort.
Wir erwarten, dass eine größere Anzahl Entwickler demnächst Ereignisinstrumentationstechnologie einsetzen wird, um zuverlässigere, leistungsstärkere und einfacher verwaltbare Anwendungen zu erstellen. Instrumentation hilft nicht nur den Entwicklern dabei, ihre Anwendungen zu debuggen, sondern auch den Personen, die Anwendungen bereitstellen und verwalten. Ferner wird sich Instrumentation bei der Kapazitätsplanung, Trendanalyse und bei der Identifikation von Engpässen als nützlich erweisen. ETW stellt eine nützliche Infrastruktur zur Ablaufverfolgung bereit, mit der Anwendungen Instrumentation zur Behandlung aller oben genannten Szenarios bieten können. Unserer Meinung nach wird diese Technologie grundlegende Auswirkungen darauf haben, Anwendungen in Zukunft verwaltbarer und diagnostizierbarer zu gestalten.

Dr. Insung Park ist Entwicklungsleiter für das Windows Instrumentation Platform-Team. Er hat mehrere Artikel zur Leistungsanalyse, Anforderungsverfolgung, Instrumentationstechnologie und Programmiermethodik sowie -unterstützung veröffentlicht. Sie können ihn unter der folgenden E-Mail-Adresse anschreiben: insungp@microsoft.com.

Ricky Buch ist Program Manager im Windows Instrumentation Platform-Team. Er arbeitet im Bereich Ereignisablaufverfolgung für Windows und an Bibliothekstechnologien für Leistungsindikatoren. Ricky Buch kann unter ricky.buch@microsoft.com

Page view tracker