Logging mit der Enterprise Library (Teil 1)

Die Enterprise Library ist eine Sammlung von wiederverwendbaren Applikationsblöcken, die Entwickler bei Standardaufgaben unterstützen sollen. Es handelt sich dabei um einen Satz wiederverwendbarer Softwarekomponenten, die dort Application Blocks genannt werden. Die Enterprise Library wird vom Patterns & Practices Team von Microsoft entwickelt. Das Framework steht unter der Apache License 2.0 und kann somit in eigenen Projekten unentgeltlich genutzt werden. Die Enterprise Library ist für das Softwaredesign hilfreich, weil sie fertige Lösungen für häufige Designfragen in Unternehmensanwendungen bereitstellt (wie Logging oder Fehlerbehandlung). Der Einsatz der einzelnen Application-Blocks muss natürlich geplant und durchdacht werden, aber mit ihren Möglichkeiten gibt sie einen Rahmen vor. Darüber hinaus steht der komplette Quellcode zur Verfügung und kann beliebig erweitert werden. Wie man dies machen kann werde ich in einem eigenen Beitrag genauer beschreiben.

Eine der besten Eigenschaften der Enterprise Library ist sicherlich die komplette Konfigurierbarkeit über die Konfigurationsdatei der Applikation. Im Gegensatz zu vielen anderen Bibliotheken ist auch eine komfortable Konfigurationssoftware enthalten, sodass die XML-Dateien nicht mehr von Hand bearbeitet werden müssen. Das erleichtert zum einen Einarbeitung ungemein und zum anderen werden Fehler vermieden, da diese Software die Eingaben auch validieren kann. Diese Konfigurationsdateien können ziemlich komplex werden und sollten nur dann manuell editiert werden, wenn man genau weiß was man tut.

Aber wofür kann man die Enterprise Library nun einsetzen? Für immer wiederkehrende Aufgaben (crosscutting concerns) in der Entwicklung professioneller Software, vor allem im Enterprise-Umfeld. Das folgende Schaubild gibt einen Überblick über die einzelnen Application-Blocks (Funktionalitäten) und deren Abhängigkeiten:

EntLib6
Bestandteile Enterprise Library 6.0 (Quelle: [2], Seite 9)

Enterprise Library Application Blocks

Application BlockBeschreibung
Data AccessDieser Application Block baut auf ADO.NET auf und bietet eine
vereinfachte Schnittstelle zum Abrufen und Speichern von Daten.
Exception HandlingErlaubt den flexiblen Umgang mit Exceptions, zum Beispiel deren Logging, der Benachrichtigung von Anwendern und dem Ersetzen von Exceptions.
LoggingBietet Standardfunktionalität zum Loggen an.
Policy InjectionDamit können Policys automatisch den Objektinstanzen zugewiesenwerden, die sich dann um Querschnittsaufgaben kümmern, zum Beispiel der Validierung übergebener Parameter.
UnityMithilfe dieses Application Blocks steht ein leichtgewichtiger IoC (Inversion of Control)-Container bereit, der Constructor-, Property und Method-Injection beherrscht.
ValidationDamit können Sie Validierungsregeln definieren, gegen die
Geschäftsobjekte geprüft werden.

Der Logging Application Block

Logging erfüllt im Allgemeinen zwei Hauptanforderungen:

  • Überwachung der Applikation
  • Bereitstellung von Informationen

Die protokollierten Informationen können in den folgenden Situationen hilfreich sein:

  • sind Fehler innerhalb der Applikation aufgetreten
  • sind evtl. einzelne System ausgefallen (in verteilten Anwendungen)
  • im Falle von unerwarteten Ergebnissen
  • warum dauert ein Prozess länger als sonst (z.B. Berechnungen)

Der Logging Application Block ist eine sehr flexible und konfigurierbare Lösung, die man zum Speichern von Log-Nachrichten in eine Vielzahl von Logging-Zielen (Textdateien, Datenbanken, Windows Event Log, …) verwenden kann. Darüber hinaus können Log-Meldungen kategorisiert und gefiltert werden. Dabei wird die Logging-Funktionalität abstrahiert, mit dem Ziel den Anwendungscode konsistent zu halten, unabhängig davon welches Logging-Ziel verwendet wird (d.h. für die Verwendung ist es vollkommen egal ob in eine Textdatei oder Datenbank protokolliert wird). Alle Parameter, die für das Logging relevant sind können konfiguriert und angepasst werden.

Das folgende Schaubild verdeutlicht den Logging-Prozess und die verwendeten Objekte des Logging Application Blocks:

EntLib_LoggingProcess
Logging-Prozess und verwendete Objekte (Quelle: [2], Seite 95)

Schritte des Logging-Prozesses

SchrittBeschreibung
Log-Meldung erzeugenDer Benutzer erstellt eine LogWriter-Instanz und ruft eine der Überladungen der Write-Methode auf. Alternativ kann der Benutzer explizit eine neue LogEntry-Instanz erstellen, füllt diese mit den erforderlichen Informationen und übergibt diese dann der LogWriter-Instanz. Schlussendlich übernimmt der Logging Application Block die weitere Verarbeitung.
Log-Meldung filternDer Logging Application Block filtert die Log-Meldungen basierend auf den Konfigurationseinstellungen. Dabei werden Eigenschaften wie Priorität oder Kategorie des Log-Eintrags für den Filter verwendet. Es wird auch überprüft, ob das Logging aktiviert ist. Diese Filter können jede weitere Verarbeitung der Log-Einträge verhindern. Das ist zum Beispiel dann nützlich, wenn zusätzliche Debug-Informationen ein- oder ausgeschaltet werden sollen ohne den Anwendungscode ändern zu müssen.
Auswahl der Trace-SourceTrace sources fungieren als Bindeglied zwischen den Log-Einträgen und den Log-Zielen (Textdatei, Datenbank, usw.). Es gibt eine trace source für jede Kategorie, die in der Konfiguration hinterlegt wird. Darüber hinaus gibt es drei fest eingebaute trace sourcen:

  • All Events -> zum abarbeiten aller Log-Meldungen

  • Unprocessed Category -> Log-Einträge, für die eine ungültige Kategorie angegeben ist

  • Logging Errors & Warnings -> Einträge, die nicht verarbeitet werden können (z.B. Fehler beim Schreiben in ein Log-Ziel -> DB nicht erreichbar)

Auswahl des Trace-ListenersJede trace source hat eine oder mehrere trace listener definiert. Diese trace listener sind für die Formatierung und das Wegschreiben in das konfigurierte Ziel des Log-Eintrags verantwortlich. Es gibt vorderfinierte trace listener und die Möglichkeit eigene trace listener zu implementieren.
Log-Meldung formatierenZu jedem trace listener kann ein "Log message formatter" definiert werden, z.B. der "Text formatter" verwendet eine Template, welches Platzhalter enthält um die entsprechende Log-Meldung zu formatieren.

Schauen wir uns nun den Logging Application Block genauer an. Zunächst muss dieser einmal installiert werden. Dafür bietet sich NuGet an, da neben dem eigentlichen Logging Application Block noch einige Referenzen benötigt werden (siehe dazu da oben abgebildete Schaubild). Innerhalb von NuGet sieht das dann folgendermaßen aus:

NuGet_Installation_Logging_Application_Block

Hinweis: Nachteil dieser Methode ist, dass das Konfigurationstool der Enterprise Library nicht automatisch installiert wird. Dieses Tool ist nur im Komplettpaket enthalten. Das Komplettpaket kann über die Projektseite http://entlib.codeplex.com/ heruntergeladen werden. Wenn man das Komplettpaket installiert bzw. entpackt hat ist das Konfigurationstool im Installationsordner zu finden:

EntLib_Config_Tool

Das Konfigurationstool kann dann in Visual Studio eingebunden, so dass eine Konfigurationsdatei bequem über des Kontextmenü mit diesem Tool geöffnet werden kann. Dazu geht man wie folgt vor:

Ein Rechtsklick auf die Datei „app.config“ und im Kontextmenü „Öffnen mit …“ auswählen:

EntLib_Config_Tool_VS_Integration_1

In diesem Dialog kann man über den Button „Hinzufügen …“ ein neues Programm zum Bearbeiten der Dateien hinzufügen. In unserem Fall fügen wir einen Verweis auf die Datei „EntLibConfig.exe“ der Enterprise Library hinzu (die Datei befindet sich im Installationsordner der Enterprise Library).

EntLib_Config_Tool_VS_Integration_2

Nach erfolgreicher Installation ist der Logging Application Block auch direkt verwendbar und muss zunächst konfiguriert werden. Dazu öffnet man die „app.config“ des entsprechenden Projekts mit dem Konfigurationstool und fügt im ersten Schritt den entsprechenden Application Block hinzu den man verwenden möchte.

LoggingApplicationBlock_Config_1

Folgenden Konfigurationsmöglichkeiten stehen für den Logging Application Block zur Verfügung:

EintragBedeutung
CategoriesHier können verschiedene Log-Kategorien hinterlegt werden, z.B. General, DiskFiles, Database, usw.
Special-CategoriesAuch beim Loggen selbst können Fehler auftreten. Solche werden hier behandelt. Aber auch Kategorien, die nicht unter Category Sources eine Entsprechung finden, werden unterhalb dieses Knotens verarbeitet.
Logging FiltersHier können Sie Filter definieren, die sich auf den gesamten Logging Application Block auswirken, beispielsweise das gesamte Logging ein- oder ausschalten.
Logging Target ListenersEs können beliebige Trace Listeners definiert und flexibel mit den Kategorien verbunden werden.
Log Message FormattersDas Format des Log-Eintrags kann in Grenzen selbst festgelegt werden. Dies kann mithilfe des Text Formatters in lesbarer Form erfolgen oder mithilfe des Binary Formatters in binärem Format.

In der Standardkonfiguration ist bereits eine Logging-Kategorie namens „General“ angelegt. Für diese Kategorie möchten wir nun ein zusätzliches Logging-Ziel konfigurieren. Dabei stehen die folgenden Logging-Ziele (geben an in welcher Form Informationen protokolliert/geloggt werden) zur Verfügung:

EintragBedeutung
CustomHier kann man eine Klasse angeben, die zuvor von CustomTraceListener abgeleitet wurde.
DatabaseBevor dieser Trace Listener genutzt werden, muss das Script zur Erzeugung des Datenbankschemas ausgeführt werden. Dieses Skript befindet sich im Installations-Ordner der Enterprise Library und hat den folgenden Namen "CreateLoggingDatabase.sql". Dieses Skript kann man entweder manuell ausführen oder die dazugeörige Bach-Datei ("CreateLoggingDb.bat") ausführen.
EmailDamit werden E-Mails über SMTP versendet.
Flat FileWie der Name schon sagt, werden hier Log-Informationen in eine einfache Textdatei geschrieben.
Formatted Event LogNutzt das Windows-Eventlog, um Log-Einträge zu speichern. Dies hat den Vorteil, dass die Log-Einträge an einer zentralen Stelle gesammelt werden (sowohl für die einzelnen Anwendungen als auch Log-Einträge des Betriebssystems).
MSMQDamit werden die Einträge in eine Warteschlange des MSMQDienstes geschrieben.
Rolling Flat FileHiermit werden alte Einträge überschrieben, abhängig von den getroffenen Einstellungen (Größe, Anzahl alter Dateien, usw.). Die Logdatei kann also niemals zu groß werden.
WMIEs wird ein WMI-Ereignis generiert, sobald ein Log-Eintrag erzeugt wird.

In folgendem Beispiel wird eine Textdatei als neues Logging-Ziel konfiguriert:

LoggingApplicationBlock_Config_2

Nachdem ein neues Logging-Ziel konfiguriert wurde kann man dieses dann mit einer Logging-Kategorie und einem LogMessage-Formatter „verbinden“.

LoggingApplicationBlock_Config_3

Bis zu diesem Zeitpunkt haben wir noch keine Zeile Code geschrieben, bisher war alles reine Konfiguration. Das Loggen selbst ist eine relative einfache Sache. Dafür erstellt man einfach über die „LogWriterFactory“ eine neue Instanz und nutzt dort die Methode „Write“, die 19-fach überladen ist. Dazu das folgende Beispiel:

In oben gezeigten Beispiel wird ein neuer Log-Eintrag mit dem Text „Neuer Log-Eintrag“ in der Kategorie „General“ erstellt. Von der Methode Write gibt es wie schon geschrieben 19-Überladungen, auf die ich hier jetzt nicht alle eingehen werden. Weitere Details gibt es im nächsten Beitrag:

Literaturverzeichnis und Weblinks

Abk.Quelle
[1]http://entlib.codeplex.com/
[2]Developer's Guide to Microsoft Enterprise Library, 2nd Edition, Patterns&Practices Team
Fork me on GitHub