Das sogenannte Logging, also das Mitprotokollieren



Ähnliche Dokumente
Technische Dokumentation SilentStatistikTool

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Exception Handling, Tracing und Logging

Nach der Anmeldung im Backend Bereich landen Sie im Kontrollzentrum, welches so aussieht:

Artikel Schnittstelle über CSV

Folgende Einstellungen sind notwendig, damit die Kommunikation zwischen Server und Client funktioniert:

Java: Vererbung. Teil 3: super()

Nachricht der Kundenbetreuung

SANDBOXIE konfigurieren

OP-LOG

Die Installation des GeoShop Redirector für IIS (Internet Information Server, Version 4.0, 5.0 und 6.0) umfasst folgende Teilschritte:

Folge 18 - Vererbung

Programmieren in Java

Inkrementelles Backup

Enigmail Konfiguration

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Über die Internetseite Hier werden unter Download/aktuelle Versionen die verschiedenen Module als zip-dateien bereitgestellt.

ICS-Addin. Benutzerhandbuch. Version: 1.0

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

Bedienungsanleitung. Matthias Haasler. Version 0.4. für die Arbeit mit der Gemeinde-Homepage der Paulus-Kirchengemeinde Tempelhof

FritzCall.CoCPit Schnelleinrichtung

FlowFact Alle Versionen

Der vorliegende Konverter unterstützt Sie bei der Konvertierung der Datensätze zu IBAN und BIC.

Installation des edu- sharing Plug- Ins für Moodle

MSXFORUM - Exchange Server 2003 > SMTP Konfiguration von Exchange 2003

2. Word-Dokumente verwalten

Guide DynDNS und Portforwarding

Handbuch PCI Treiber-Installation

VIDA ADMIN KURZANLEITUNG

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Übung: Verwendung von Java-Threads

Installationsanleitungen

icloud nicht neu, aber doch irgendwie anders

Urlaubsregel in David

Auto-Provisionierung tiptel 30x0 mit Yeastar MyPBX

Anwendungshinweis Nr. 12. Wie konfiguriere ich redundante Serververbindungen

Software Engineering Klassendiagramme Assoziationen

OLXTeamOutlook 1.5 für Outlook 2003, 2002/XP, 2000 und 97/98

FTP-Server einrichten mit automatischem Datenupload für

FuxMedia Programm im Netzwerk einrichten am Beispiel von Windows 7

Delegatesund Ereignisse

Handbuch B4000+ Preset Manager

2. Die eigenen Benutzerdaten aus orgamax müssen bekannt sein

Zählen von Objekten einer bestimmten Klasse

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

etermin Einbindung in Outlook

CMS.R. Bedienungsanleitung. Modul Cron. Copyright CMS.R Revision 1

Für die Einrichtung des elektronischen Postfachs melden Sie sich wie gewohnt in unserem Online-Banking auf an.

Qt-Projekte mit Visual Studio 2005

5.2 Neue Projekte erstellen

Lexware professional und premium setzen bis einschließlich Version 2012 den Sybase SQL-Datenbankserver

Log xmllog textlog Log() start(filename) add(message) end() instance() Abbildung 7-10: Die Protokollierungs-API mit einer einfachen Fassade

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

TechNote. Produkt: TWINFAX 7.0 (ab CD_24), TWINFAX 6.0 Modul: SMTP, T611, R3 Kurzbeschreibung: Briefpapier- und Mailbodyunterstützung

.NET Code schützen. Projekt.NET. Version 1.0

So funktioniert die NetWorker 7.5 Eigenschaft zum Sichern umbenannter Verzeichnisse ( Backup renamed Directories )

Seite 1 von 14. Cookie-Einstellungen verschiedener Browser

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Aufrufen des Konfigurators über eine ISDN- Verbindung zur T-Eumex 628. Eine neue ISDN-Verbindung unter Windows XP einrichten

O UTLOOK EDITION. Was ist die Outlook Edition? Installieren der Outlook Edition. Siehe auch:

! " # $ " % & Nicki Wruck worldwidewruck

Das Leitbild vom Verein WIR

Memeo Instant Backup Kurzleitfaden. Schritt 1: Richten Sie Ihr kostenloses Memeo-Konto ein

Anleitung zur Konfiguration eines NO-IP DynDNS-Accounts mit der TOOLBOXflex-3.2

FrogSure Installation und Konfiguration

Abwesenheitsnotiz im Exchangeserver 2010

Objektorientierte Programmierung. Kapitel 12: Interfaces

Handbuch. timecard Connector Version: REINER SCT Kartengeräte GmbH & Co. KG Goethestr Furtwangen

Einrichtung -Account

Datensicherung. Beschreibung der Datensicherung

Um ein solches Dokument zu erzeugen, muss eine Serienbriefvorlage in Word erstellt werden, das auf die von BüroWARE erstellte Datei zugreift.

Mediumwechsel - VR-NetWorld Software

Eine Anwendung mit InstantRails 1.7

INSTALLATION VON INSTANTRAILS 1.7

Arbeiten mit dem Outlook Add-In

DynDNS Router Betrieb

ARAkoll 2013 Dokumentation. Datum:

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Local Control Network Technische Dokumentation

EasyWk DAS Schwimmwettkampfprogramm

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

SEMINAR Modifikation für die Nutzung des Community Builders

Tutorial -

Anleitung für Autoren auf sv-bofsheim.de

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Eine Einführung in die Installation und Nutzung von cygwin

Stepperfocuser 2.0 mit Bootloader

FORUM HANDREICHUNG (STAND: AUGUST 2013)

License Management SDK

einrichtung in den kaufmännischen Programmen der WISO Reihe

Lizenzen auschecken. Was ist zu tun?

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Erstellen eines Formulars

Anleitung zum Login. über die Mediteam- Homepage und zur Pflege von Praxisnachrichten

HowTo: Ereigniseinrichtung

Handbuch für Redakteure

Transkript:

Logging von.net-anwendungen mit Windows-Mitteln Am laufenden Band Betreiber komplexer Systeme sind darauf angewiesen, jederzeit Informationen über den Zustand ihrer Anwendung abrufen zu können. Mit dem Semantic Logging Block der Enterprise Library lässt sich das ETW dazu einsetzen. Auf einen Blick Holger Zaman ist Senior Consultant bei Saxonia System. Er lebt und arbeitet in Hamburg. Sein Schwerpunkt ist das Entwickeln von Backend-Anwendungen mit.net. Sie erreichen ihn unter holger.zaman@saxsys.de. Inhalt Das Event-Tracing von Windows für eigenes Logging. Auf Ereignisse lauschen in getrennten Prozessen. Events über Filter sammeln. dnpcode A1407Logging Das sogenannte Logging, also das Mitprotokollieren von bestimmten Daten aus einer Software, während diese läuft, gehört zu den wichtigsten Instrumenten eines Programmierers, um auf den Zustand einer zu entwickelnden Software schließen zu können. Dazu muss der Entwickler an den gewünschten Punkten des Programms entsprechende Aufrufe einbauen. Inzwischen gibt es etliche Frameworks, die ihn dabei unterstützen, unter anderem auch von Microsoft mit der Enterprise Library. Semantic Logging Block In der Enterprise Library 6 hat Microsoft die Bibliothek um einen neuen Block erweitert: um den Semantic Logging Block oder auch kurz SLB. Laut Insung Park und Ricky Buch liegt sein großer Vorteil darin, anwendungs- oder gar unternehmensweit sowohl formal als auch semantisch einheitliche Logging-Informationen zu erzeugen [1]. Diesem Umstand verdankt der SLB das Semantic im Namen. Einheitliche Angaben ließen sich auch mit anderen Logging-Frameworks erzielen. Der Grund, sich dennoch mit dem SLB eingehender zu beschäftigen, liegt darin, dass das Erheben dieser Daten und das Bereitstellen derselben in verschiedenen Prozessen ablaufen können. Das hat den unschätzbaren Vorteil, dass eine einmal erstellte Information auch dann noch gespeichert und ausgewertet wird, wenn der Quellprozess schon längst beendet ist. Event Tracing for Windows Der SLB basiert auf einem Subsystem des Betriebssystems Windows, dem Event Tracing for Windows kurz ETW [2, 3], und verknüpft quasi drei Akteure. Der erste ist der Provider; er erzeugt Logging-Informationen in der Terminologie des ETW Ereignisse (Events) genannt und sendet diese an den ETW. Damit ist sein Part in dem Spiel bereits erschöpft. Der zweite Akteur ist ein Consumer, der die Events vom ETW entgegennimmt und verarbeitet. Als dritter Part steuert ein Controller, ob und wenn ja welche Events an welchen Consumer weitergereicht werden. Der Provider verfügt über eine Ereignisquelle (EventSource), die er beauftragt, Events an den Listing 1 Eine einfache Ereignisquelle für das Windows Event Tracing. /// Einfache EventSource class GrundausstattungEventSource : EventSource /// Trace-Event /// <param name="nachricht">die /// Nachricht des Events</param> public void Trace(string nachricht) WriteEvent(1,nachricht); ETW zu senden. Eine Sitzung (Session) bezeichnet eine Zuordnung eines Providers oder genau genommen seiner Events zu einem oder mehreren Consumern. Eine Session ist temporär; ihre Parameter Name der Ereignisquelle, Filter et cetera lassen sich ändern, ohne dass der Provider-Prozess davon betroffen ist. Das gilt natürlich nur für den Betrieb in einem anderen Prozess (Out-of-Process-Betrieb). Das API für den ETW befindet sich in der Windows-Datei adavapi32.dll. Bislang hat Microsoft den.net-entwicklern den Zugriff auf den ETW verwehrt, doch das hat sich mit.net 4.5 geändert. Nun steht allen Entwicklern die Möglichkeit zur Verfügung, eigene Ereignisquellen zu implementieren und zu betreiben, ohne in die Tiefen des Betriebssystems und der Datei adav api32.dll eintauchen zu müssen. Die Ereignisquelle Um als Provider mit dem ETW kommunizieren zu können, ist eine Ereignisquelle nötig. Erstellen lässt sie sich durch Ableitung von der Klasse 84 7.2014 www.dotnetpro.de

EventSource aus dem Namensraum System.Diagnostics. Eine solche Klasse kann mehrere Ereignisse anbieten. Implementiert werden diese als Methode der Ereignisquelle. Listing 1 zeigt ein Beispiel für eine einfache Ereignisquelle. Sie bietet die Methode Trace() an, die eine einfache Nachricht in das Log schreibt. Der Provider ist eine einfache Konsolenanwendung, die in Listing 2 zu sehen ist. Die Methode Main() erstellt zuerst die Ereignisquelle als statische Eigenschaft der Klasse, danach wird ein Listener vom Typ ObservableEventListener aus dem Namensraum Microsoft.Practices.Enterprise Library.SemanticLogging eingerichtet. Seine Aufgabe ist es, auf die Ereignisse zu lauschen und diese an die angeschlossenen Senken weiterzuleiten, also an die Consumer; der Listener übernimmt die Aufgabe des Controllers. Nach Erstellen des Listeners wird diesem mitgeteilt, auf welche Quelle er lauschen soll. Dies geschieht durch den Aufruf der Methode EnableEvents(), der die Instanz der Quelle sowie der Level der eingehenden Events übergeben werden. Der Level ist in diesem Fall nicht an das Ereignis selbst gebunden, sondern wird vom Listener bereitgestellt. Nun fehlt nur noch die Angabe der Ereignissenken, also der Consumer. In diesem Fall sollen die Events nur über die Konsole ausgegeben werden, daher wird im Listener der Consumer LogToCon sole registriert. Ein Aufruf von eventsource. Trace() sendet die Events an den Listener, der diese an den Consumer weiterreicht. Das Ergebnis ist in Abbildung 1 zu sehen. Die Formatierung der Ausgabe ist alles andere als übersichtlich und leider fehlt ein ganz entscheidender Hinweis, nämlich der Name der Quelle. Dieser lässt sich mit einer einfachen, benutzerdefinierten Senke implementieren. Listing 2 Ein einfacher Provider. using Microsoft.Practices.EnterpriseLibrary.SemanticLogging; class Program /// Die EventSource private static GrundausstattungEventSource eventsource get; set; static void Main(string[] args) eventsource = new GrundausstattungEventSource(); using(var listener = new ObservableEventListener()) listener.enableevents(eventsource,eventlevel.informational); listener.logtoconsole(); eventsource.trace("start der Anwendung"); eventsource.trace("die Anwendung arbeitet."); eventsource.trace("anwendung wird beendet."); listener.disableevents(eventsource); eventsource.dispose(); [Abb. 1] Ausgabe der Events über die Konsole. Eine einfache Senke Jede Senke erbt von IObserver<EventEntry>. Der Listener leitet den ursprünglichen Event aus dem ETW als Instanz der Klasse EventEntry aus dem Namensraum Microsoft.Practices.EnterpriseLibrary.SemanticLogging an sie weiter. In der Methode OnNext() der Schnittstelle IObserver<T> erfolgt die Ausgabe des Events. Listing 3 zeigt die Implementierung einer einfachen, benutzerdefinierten Senke. Die Registrierung des Consumers am Listener erfolgt durch eine Erweiterungsmethode für IObserver<EventEntry>. Listing 4 enthält eine Implementierung dieser Methode. Anstelle der Senke Log ToConsole() verwendet Listing 4 LogTo GrundausstattungEventSink(), und schon wirkt die Ausgabe auf der Konsole viel aufgeräumter und ansprechender, wie Abbildung 2 zeigt. Getrennte Prozesse Bislang lief der Listener in ETW-Terminologie der Consumer im gleichen Prozess wie der Provider. Das allerdings sollte in produktiven Anwendungen nicht der Standard sein. Um das Risiko zu minimieren, Informationen beim Absturz einer Anwendung zu verlieren, sollte der Liste- www.dotnetpro.de 7.2014 85

Logging von.net-anwendungen mit Windows-Mitteln Listing 3 Eine einfache eigene Ereignissenke. using System; using Microsoft.Practices.EnterpriseLibrary.SemanticLogging; public sealed class GrundausstattungEventSink : IObserver<EventEntry> /// Stellt neue Daten für den Beobachter bereit. /// <param name="value">die aktuellen Benachrichtigungsinformationen.</param> public void OnNext(EventEntry value) if(value!= null) var ursprünglicheschriftfarbe = Console.ForegroundColor; switch(value.schema.level) case EventLevel.Critical: Console.ForegroundColor = ConsoleColor.Red; break; case EventLevel.Error: Console.ForegroundColor = ConsoleColor.Yellow; break; default: Console.ForegroundColor = ConsoleColor.Green; break; Console.WriteLine("Quelle: 0",value.Schema.ProviderName); Console.WriteLine("Event: 0", value.eventid); Console.WriteLine("Level: 0",value.Schema.Level); Console.WriteLine("Datum: 0",value.GetFormattedTimestamp( "dd.mm.yyyy - HH:mm:ss")); Console.WriteLine("Meldung: 0",value.FormattedMessage); Console.ForegroundColor = ursprünglicheschriftfarbe; ner in einem anderen Prozess auf der gleichen Maschine laufen, vorzugsweise in einem NT-Dienst. Darüber hinaus bietet diese Betriebsart die Möglichkeit, Einstellungen der Session zu ändern, ohne den Provider neu starten zu müssen. Für so einen Out-of-Process-Betrieb stellt der Semantic Logging Block eine eigene Implementierung in Semantic Logging-svc.exe zur Verfügung. Der Listener lässt sich damit in einem Konsolenprozess oder in einem NT-Dienstprozess betreiben. Die Konfiguration des Listeners erfolgt über eine XML-Datei. Ihr Name wird in der SemanticLogging-svc.exe.config im Abschnitt appsettings unter dem Schlüssel EtwConfigurationFileName eingetragen. Die eigentliche Konfigurationsdatei ist recht übersichtlich. Im einfachsten Fall geht es darum, dem Listener eine Reihe von Senken bekannt zu machen und jeder Senke eine Event-Quelle zuzuweisen. In Listing 5 ist die Konfiguration für die Ausgabe der Events der Beispielquelle auf der Konsole des Prozesses zu sehen. Starten Sie dazu zuerst die Datei SemanticLogging-svc.exe mit dem Parameter -console und führen Sie danach das Testprogramm Grundausstattung.exe von der Heft-CD dieser dotnetpro aus. Sie sehen dann einerseits das bereits bekannte Bild, nämlich die Ausgabe des Events auf der Konsole von Grundausstattung.exe; mit einer kleinen Verzögerung erscheinen auf der Konsole von SemanticLogging-svc.exe die Events aus Grundausstattung.exe. So viel als Einführung zu den Grundzügen des Logging mit dem Semantic Logging Block und dem ETW. Mehr dazu finden Sie unter den angegebenen Quellen im Internet. /// Benachrichtigt den Beobachter, dass beim Anbieter ein Fehlerzustand aufgetreten ist. /// <param name="error">ein Objekt, das zusätzliche Informationen zum Fehler bereitstellt.</param> public void OnError(Exception error) /// Benachrichtigt den Beobachter, dass der Anbieter aufgehört hat, Pushbenachrichtigungen zu senden. public void OnCompleted() Unter der Haube: ETW und.net Das letzte Beispiel hat die Events sowohl auf der Konsole von Grundausstattung.exe als auch auf der von SemanticLogging-svc. exe ausgegeben. Im ersten Fall übermittelte die Klasse EventSource die Basisklasse von GrundausstattungEventSource das Ereignis über einen internen proprietären Dispatcher-Mechanismus an den zuvor installierten Listener in Grundausstattung.exe. Im zweiten Fall wird das Ereignis über ETW veröffentlicht und auch davon entgegengenommen. Um ein Ereignis entgegennehmen zu können, muss das Windows-Event-Tracking etwas über die Struktur des Events wissen. Um sich zu informieren, benötigt 86 7.2014 www.dotnetpro.de

es ein Instrumentation Manifest [4]. Dies ist ein mehr oder weniger komplexes XML-Dokument, das dem ETW über eine Funktion aus der Datei adav api32. dll übergeben wird. Normalerweise hat der Entwickler damit aber nichts zu tun, wenn er seine Klasse von der Klasse EventSource ableitet die Basis Event Source übernimmt das Erstellen und Veröffentlichen des Manifests. Betrachten Sie Ihre eigene EventSource- Klasse fortan nicht nur als Schnittstelle zum ETW, sondern auch als Vorlage, aus der sich per Reflektion ein Manifest erzeugen und als XML-Dokument an ETW weiterreichen lässt. Das Erzeugen des Manifests und seine Weitergabe erfolgt bei jeder Instanzierung des EventSource-Objekts. Um Ressourcen zu sparen, empfiehlt es sich, die eigene EventSource der Anwendung über das Singleton-Muster zur Verfügung zu stellen am besten auch noch mit Lazy- Initialisierung. Leider hat das Erstellen des Manifests seine Tücken. Deshalb soll die Klasse GrundausstattungEventSource ein wenig aufgepeppt werden. Auf der Konsole von Grundausstattung.exe taucht als Quelle der Name der Klasse auf, also GrundausstattungEventSource das ist unter Umständen nicht besonders aussagekräftig. Versehen Sie nun Ihre Klasse mit dem Attribut [EventSource] und geben Sie diesem einen aussagekräftigen Namen mit: [EventSource(Name = "dotnetpro-grundausstattung")] und schon erscheint auf der Konsole von Grundausstattung.exe dieser definierte Name als Quelle des Events. Im Out-of-Process-Listener SemanticLogging-svc.exe tut sich dagegen allerdings nichts. Um das zu ändern, müssen Sie in der Konfigurationsdatei den Namen der Quelle in dotnetpro-grundausstattung ändern und schon funktioniert es wieder. Sie müssen lediglich die geänderte Konfiguration speichern. SemanticLoggingsvc.exe beobachtet die Konfigurationsdatei und lädt sie automatisch nach, wenn.net Änderungen daran festgestellt hat. Das funktioniert in beiden Betriebsmodi als Konsolenanwendung oder als NT-Dienst einwandfrei. Sollte die Konfigurationsdatei Fehler enthalten, so sind in der Ereignisanzeige unter Windows- Protokolle Anwendungen hilfreiche Informationen zu finden. Im nächsten Schritt erhält die Klasse GrundausstattungEventSource eine neue [Abb. 2] Farbiges Logging mit der eigenen Ereignissenke. Listing 4 Damit wird die Senke aktiviert. using System; using Microsoft.Practices.EnterpriseLibrary.SemanticLogging; /// Erweiterung IObservable public static class GrundausstattungEventSinkRegistrierung /// Erweiterungsmethode zur Registrierung eines EventSinks vom Typ /// GrundausstattungEventSink /// <param name="eventstream">der EventStream</param> /// <returns>die SinkSubscription</returns> public static SinkSubscription<GrundausstattungEventSink> LogtoGrundausstattungEventSink(this IObservable<EventEntry> eventstream ) var sink = new GrundausstattungEventSink(); var subscription = eventstream.subscribe(sink); return new SinkSubscription<GrundausstattungEventSink>(subscription,sink); Listing 5 Die Konfiguration von SemanticLogging-svc.exe. <?xml version="1.0"?> <configuration xmlns="http://schemas.microsoft.com/practices/2013/entlib/semanticlogging/etw" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://schemas.microsoft.com/practices/2013/entlib/ semanticlogging/etw SemanticLogging-svc.xsd"> <traceeventservice/> <sinks> <consolesink name="consoleeventsink"> <sources> <eventsource name="grundausstattungeventsource" level="logalways" /> </sources> <eventtextformatter header="+=========================================+"/> </consolesink> </sinks> </configuration> www.dotnetpro.de 7.2014 87

Logging von.net-anwendungen mit Windows-Mitteln Listing 6 Die neue Methode für die Quelle. /// Einfache EventSource [EventSource(Name="dotnetpro-Grundausstattung")] class GrundausstattungEventSource : EventSource /// Trace-Event /// <param name="nachricht">die Nachricht des Events</param> public void Trace(string nachricht) WriteEvent(1,nachricht); public void Trace(string format, params object[] args) var nachricht = string.format(format, args); Trace(nachricht); Listing 7 Der Einsatz von Keywords. [Event(2, Message = "Exception: [0] 1", Level = EventLevel.Critical, Keywords = Keywords.Exception)] public void Failure(string extype, string exmessage) if (IsEnabled(EventLevel.Critical, Keywords.Exception)) WriteEvent(2, extype, exmessage); Trace()-Methode, die einen Format-String und Parameter entgegennehmen kann, wie es Listing 6 zeigt. Die daraus erzeugte Nachricht soll wieder als Event veröffentlicht werden. Wenn Sie nun Grundausstattung.exe starten, überrascht die Meldung Nicht unterstützter Typ Object[] in Ereignisquelle. Das liegt daran, dass jede Methode in einer von EventSource abgeleiteten Klasse vom Parser, der das Manifest erstellt, als Event betrachtet wird. Die Typen der Parameter einer Methode als Ereignisquelle sind beschränkt und Object[] gehört nicht dazu. Welche Typen zugelassen sind, zählt der Kasten Die Payload auf. Sie können die soeben erstellte Methode mit dem Attribut [NonEvent] kennzeichnen, dann überspringt der Parser die Methode. Die Payload Ein Event, der an den ETW gesendet wird, besteht aus einem Header und der Payload. Die Payload enthält die Nutzdaten des Events. Header und Payload dürfen die Größe von 64 KB nicht übersteigen, ansonsten kommt es beim Bereitstellen des Events an den ETW zu einer Ausnahme. Folgende Typen sind als Payload eines Events zulässig: Boolean Int8 UInt8 Int16 UInt16 Int32 UInt32 Int64 UInt64 Float Double FILETIME UnicodeString Guid Den Event konfigurieren Das Gegenteil von [NonEvent] ist das Attribut [Event]. Es teilt dem Parser Metainformationen über die Methode als Event mit. Der einzige obligatorische Parameter des Attributs ist Id, der die ID des Events angibt. Diese muss in der Event- Quelle eindeutig sein. In der Methode setzen Sie mit Write Event() aus der Basisklasse EventSource den Event an das ETW ab. Achten Sie dabei darauf, dass die Event-ID, die Sie der Methode mitgeben, der Event-ID in der Konfiguration des Attributs entspricht. Der folgende Code zeigt die einfachste derartige Implementierung. [Event(1)] public void Trace(string nachricht) WriteEvent(1, nachricht); Das Attribut [Event] hat aber noch mehr zu bieten. Da es sich dabei um die Mitteilung einer eher banalen Information handelt, wird der Level des Events im Attribut explizit auf EventLevel.Informational gesetzt; dies ist der Standard-Level [1]. Um die Nachricht mit ein paar Informationen über die Umgebung anzureichern, wird die Methode Trace() um die Angabe des Prozess- und des Rechnernamens erweitert. Dies sieht dann so aus: [Event(1, Level = EventLevel.Informational)] public void Trace(string nachricht, string processname, string machine) WriteEvent(1, nachricht, prozess,rechner); Die Angaben nachricht, prozess und rechner werden in die Payload des Events gestellt. Die Payload enthält alle vom Entwickler als Parameter an den Event über- 88 7.2014 www.dotnetpro.de

[Abb. 3] Manifest einer EventSource. gebenen Werte. Auch hier gelten wieder die erwähnten Einschränkungen, siehe abermals den Kasten Die Payload. Die Nachricht des Events ist allerdings noch leer. Das Attribut bietet die Möglichkeit, in einem Format-String die auszugebende Nachricht zu formatieren. Für diese Zeichenkette gelten die Regeln, die von String.Format() bekannt sind. Leider kann bei der Konfiguration eines Events einiges schiefgehen. Damit sich die Event-Implementierung automatisiert testen lässt, stellt der SLB mit der Klasse EventSourceAnalyzer ein Tool zur Verfügung, um das eigene EventSource-Objekt auf Regelkonformität zu prüfen. Der Aufruf der Prüfung erfolgt über die statische Methode InspectAll(), der eine Instanz des Objekts übergeben wird. Wenn Sie sich das Manifest Ihrer Event- Source betrachten wollen, können Sie das mithilfe der statischen Methode GenerateManifest() aus der Basisklasse Event Source tun. Abbildung 3 zeigt das Manifest der hier beschriebenen Event-Quellen- Klasse. Mehr zum Thema Manifest finden Sie unter [4]. Hört mich jemand? Aber was passiert, wenn für die Event- Quelle keine entsprechende Session ein- Listing 8 Eine Instanz mit dem EventSourceImplementer erzeugen. using System; using EventSourceProxy; namespace Dev class Program static void Main(string[] args) try var eventsource = EventSourceImplementer.GetEventSource <MeineEventSourceSpezialisiert>() as MeineEventSourceSpezialisiert; eventsource.trace("hallo ETW","Dev","Mein Rechner"); eventsource.dispose(); catch (Exception ex) Console.WriteLine(ex.Message); finally Console.WriteLine("Finito"); Console.ReadKey(); www.dotnetpro.de 7.2014 89

Logging von.net-anwendungen mit Windows-Mitteln gerichtet wurde, die auf die Ereignisse lauscht? Nichts. Bei Meldungen, die einen kritischen Zustand der Anwendungen signalisieren, ist das allerdings inakzeptabel. Leider kann eine Event-Quelle keine Session erzwingen, aber sie kann prüfen, ob es eine Session gibt, die für sie zuständig ist, und gegebenenfalls darauf reagieren. Dazu stellt die Basisklasse Event Source die Methode IsEnabled() mit zwei Überschreibungen zur Verfügung. Beide prüfen, ob für das EventSource-Objekt eine Session zur Verfügung steht. Zwar ist der ETW ein ziemliches Arbeitstier auf dem System des Autors wurden 100000 Events in 58 Millisekunden an den ETW gesendet und in eine Datenbank geschrieben, dennoch, oder gerade deshalb, sollten Sie nicht unnötig Ressourcen in Anspruch nehmen. Daher empfiehlt es sich auch bei unkritischen Meldungen, abzufragen, ob es eine Session dazu gibt, und den Event nur dann zu veröffentlichen, wenn dies der Fall ist. Wider die Informationsflut Damit wertvolle Informationen nicht im Wust der weniger relevanten untergehen, Listing 9 lässt sich ein Event mit einem Filter versehen. Filter lassen sich grob in zwei Kategorien einteilen: solche, die bereits im ETW dafür sorgen, dass ein Event nicht an den Consumer weitergeleitet wird, und solche, deren Auswertung der Consumer übernimmt. Zur ersten Kategorie gehört der Filter Keywords. Schlüsselbegriffe werden in der EventSource-Klasse als eingebettete Klasse implementiert, die den Namen Keywords tragen muss. Innerhalb der Klasse werden die Schlüsselbegriffe dann als Konstanten vom Typ EventKeywords aus dem Namensraum System.Diagnostics. Tracing definiert. Die Werte der Schlüsselbegriffe müssen einer Zweierpotenz entsprechen also 1, 2, 4, 8, 16, 32 und so weiter. Dadurch lassen sich bis zu 64 Werte für eine EventSource-Klasse implementieren. Die Klasse kann mit einer Überschreibung der Methode IsEnabled() aus der Basisklasse abfragen, ob es für die Event Source einen Consumer gibt, der auf ein Event mit dem angegebenen Level und dem angegebenen Schlüsselwert wartet, wie es Listing 7 zeigt. Die Schlüsselwerte eines Events werden wie oben schon über das Attribut [Event] bekannt gemacht. Es besteht natürlich die Möglichkeit, mehrere Werte mit dem Oder-Operator zu verknüpfen. Die Filter OpCodes und Tasks sind nur durch den Consumer auszuwerten. Nähere Informationen zu den Keywords, Tasks und OpCodes finden sich unter [1] und [4]. Eine für alle Der Name der Event-Quelle, den das gleichnamige Attribut angibt, bezeichnet semantisch die Anwendung, die das Ereignis abgesetzt hat. Soll nun eine EventSource-Klasse unternehmensweit in verschiedenen Anwendungen eingesetzt werden, stehen Sie vor dem Problem, dass alle Events aller Anwendungen als Quelle immer die gleiche EventSource ausweisen. Es müsste also die Möglichkeit geben, je nach Anwendung den Namen der Event- Quelle zu spezialisieren. Leider lässt sich der Name der Quelle zur Laufzeit nicht ändern. Auch eine Ableitung von einer benutzerdefinierten, abstrakten EventSource-Klasse mit der Spezifizierung des Namens im [EventSource]- Eine EventSource-Instanz mit dem Template generieren. using System; using EventSourceProxy; namespace EventSources [EventSource(Name = "LoggingEventSourceTemplate")] public abstract class LoggingEventSourceTemplate<TEventSource> : EventSource where TEventSource :LoggingEventSourceTemplate<TEventSource>, new() /// Standardkonstruktor protected LoggingEventSourceTemplate() : base(true) /// Singleton-Instanz [NonSerialized] private static readonly Lazy<TEventSource> instance = new Lazy<TEventSource>(eventSourceFactory); /// Fabrikmethode zur Erstellung der EventSource /// <returns>die EventSource</returns> private static TEventSource eventsourcefactory() TEventSource eventsource = null; try eventsource = EventSourceImplementer. GetEventSource<TEventSource>() as TEventSource; catch (Exception ex) LoggingFailure.Log.Failure(ex); if(eventsource == null) LoggingFailure.Log.Failure( "Die EventSource konnte nicht erstellt werden."); return eventsource; /// Zugriff auf das Singleton public static TEventSource Log get return instance.value; 90 7.2014 www.dotnetpro.de

Attribut führt nicht zum Ziel in diesem Fall weist das Manifest keinerlei Events auf. Der Versuch, über die EventSource in den ETW zu schreiben, wird mit einer Ausnahme vom Typ Index OutOfRange quittiert. Die Überprüfung des Event Source- Objekts mit EventSourceAnalyzer. InspectAll() ergibt, dass keine Methode mit dem Attribut [Event] ausgestattet wurde. Nach dem Stand der Dinge bleibt nun nichts anderes übrig, als für jede Anwendung eine eigene EventSource-Klasse von EventSource abzuleiten. Zum Glück gibt es Abhilfe in Gestalt eines NuGet-Pakets namens EventSource Proxy von Jon Wagner [5]. Neben etlichen Merkmalen, die das Arbeiten mit Event Source-Objekten erleichtern, stellt diese Erweiterung eine generische Methode Get EventSource() in EventSourceImplementer zur Verfügung, die aus einer spezialisierten Event-Quelle ein brauchbares regelkonformes EventSource-Objekt erzeugt. In Listing 8 sehen Sie den Einsatz des EventSourceImplementer. Die Klasse MeineEventSource ist von EventSource aus System.Diagnostics.Tracing abgeleitet. Der Name der Event-Quelle lautet dotnetpro. Sie bildet die abstrakte Basisklasse für MeineEventSourceSpezialisiert, deren Name dotnetpro-spezial ist (siehe auch Listing 10). Eine direkte Verwendung von MeineEventSource führt zu den bereits beschriebenen Problemen. Überlassen Sie allerdings die Instanzierung des Event Source-Objekts der Methode EventSource Implementer.GetEventSource(), stellt sich das gewünschte Ergebnis ein. Auf der CD zum Heft befindet sich in den Quellcodes des Projekts EventSources ein generisches Muster für die Implementierung einer EventSource-Klasse unter LoggingEventSourceProxy. Listing 9 zeigt den Kern der Implementierung zum Erzeugen einer Singleton-Instanz der Event-Quelle. Natürlich müssen in dieser Vorlage noch die einzelnen Events implementiert werden. Das Erstellen einer EventSource-Klasse, deren Name der Name der Anwendung ist, ist dann nur noch eine einfache Ableitung, wie Listing 10 zeigt. Die so erzeugte Instanz lässt sich wie alle EventSource-Instanzen mit EventSourceAnalyzer.Inspect All() prüfen. Das Erzeugen des Manifests via Event Source.GenerateManifest() funktioniert ebenfalls, vorausgesetzt der zweite Parameter gibt das Verzeichnis der Anwendung an. Ein Blick in das Manifest bestätigt, dass eine Event-Quelle für den Provider dotnetpro-spezial erzeugt wurde. Auf der anderen Seite Der SLB stellt Senken für das Speichern der Events in einer Datenbank, einer Datei, einer Azure-Table oder zur Anzeige auf der Konsole zur Verfügung. Benutzerdefinierte Senken können wie in Listing 3 oder unter [1] beschrieben implementiert werden. Für die hauseigenen Senken bringt der SLB zur Konfiguration von SemanticLogging-svc.exe eigene Tags mit. Benutzerdefinierte Senken werden mit dem Tag customsink versehen. Listing 11 zeigt, wie die in Listing 3 implementierte Senke für diesen Zweck konfiguriert wird. Fazit Der SLB und EventSource eröffnen den Weg in das Logging über das Event Tracing for Windows. Gäbe es nicht das NuGet-Paket EventSourceProxy, wäre ein Listing 10 Eine spezialisierte Event-Quelle. using EventSources; namespace DotNetPro.Spezial [EventSource(Name = "dotnetpro-spezial")] public class LocalEventSource : LoggingEventSourceTemplate<LocalEventSource> Listing 11 anwendungs- und unternehmensweiter Einsatz fraglich. So aber füllt dieses Addon eine konzeptionelle Lücke und macht ETW unter.net zu einer attraktiven Alternative für das Logging. Dennoch sind die verfügbaren Klassen und Tools erst der Anfang. Vor allem der Parser, der aus einer benutzerdefinierten EventSource-Klasse ein Manifest erzeugt, bedarf noch der Überarbeitung. [jp] [1] Dr. Insung Park und Ricky Buch, Verbessertes Debugging und Leistungsoptimierung mit ETW, www.dotnetpro.de/sl1406logging1 [2] MSDN, ETW-Ablaufverfolgung, www.dotnetpro.de/sl1406logging2 [3] MSDN, Logging what you mean: Using the Semantic Logging Application Block, www.dotnetpro.de/sl1406logging3 [4] MSDN, Writing an Instrumentation Manifest, www.dotnetpro.de/sl1406logging4 [5] Jon Wagner, EventSourceProxy, www.dotnetpro.de/sl1406logging5 Konfiguration des benutzerdefinierten Consumers für einen Out-of-Process-Einsatz. <?xml version="1.0"?> <configuration xmlns="http://schemas.microsoft.com/practices/2013/entlib/semanticlogging/etw" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://schemas.microsoft.com/practices/2013/entlib/semanticlogging/etw SemanticLogging-svc.xsd"> <traceeventservice/> <sinks> <customsink name="beautifulconsolesink" type="eventsinks.consoleeventsink, EventSinks"> <sources> <eventsource name="dotnetpro-spezial"/> </sources> </customsink> </sinks> </configuration> www.dotnetpro.de 7.2014 91