Manchmal ist es halt so, dass ein Progamm nicht so ganz funktioniert, wie man es gern hätte oder man wüsste gerne, was ein Programm gerade so macht. Um nicht selber Mechanismen für das Schreiben in Logdateien oder das EventLog zu erstellen kann man ein bestehendes Loggingframework verwenden. Eine nettes Loggingframework ist log4net. Es ist relativ simpel ins eigenen Programm eingebunden und lässt Ausgaben in verschiedene Ziele zu, wie z.B. Eventlog, Datenbank, Textdatei, E-Mail per SMTP oder über .Net Remoting.
Nachfolgend beschreibe ich kurz und einfach, was zu tun ist um die eigene Anwendung etwas kommunikationsfreudiger zu machen. Weitere Details findet ihr in den Links am Ende des Posts.
Mein Programm sieht so aus:
1: using System;
2:
3:
4: //Legt die Konfiguration auf die Extension "log4net" fest.
5: //Die Konfiguration sollte also Application.exe.log4net benannt werden.
6: [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "log4net", Watch = true)]
7: namespace logMal
8: { 9: class Program
10: { 11: //Erstellt den Logger
12: private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
13:
14: static void Main(string[] args)
15: { 16: log.Info("Anwendung gestartet"); 17:
18: try
19: { 20: Convert.ToInt32("log4net"); 21: }
22: catch (Exception ex)
23: { 24: log4net.ThreadContext.Properties["EventID"] = 4711;
25: log.Error(ex.ToString());
26:
27: }
28: log.Info("Anwendung beendet"); 29:
30: }
31: }
32: }
Wichtig ist zunächst, einen Verweis auf die log4net.dll zu erstellen. In Zeile 6 wird dann die Konfigurationsdatei bzw. deren Endung angeben. Man kann entweder mittels "ConfigFile" die komplette Konfigurationsdatei angeben oder mittels "ConfigFileExtension" die Endung der Konfigurationsdatei. Wird die Logdatei wie im Beispiel konfiguriert erwartet log4net die Konfigurationsdatei mit dem Namen Programm.exe.log4net.
In Zeile 12 wird der Logger erstellt, in Zeile 16, 25 und 28 werden dann die Logmeldungen über den Logger ausgeben, dabei werden versch. Kategorien angegeben (Error und Info). Für die Ausgaben in das EventLog kann noch die EventID angegben werden (siehe Zeile 24).
Das war es dann auch schon mit der Anwendung, interessant wird es dann jetzt in der Konfiguration:
1: <?xml version="1.0" encoding="utf-8" ?>
2: <!-- This section contains the log4net configuration settings
3: Diese Datei muss "neben" der .exe liegen
4: -->
5: <log4net>
6: <!-- Define some output appenders -->
7:
8: <!--EventLogAppender schreibt Meldungen ins Eventlog-->
9: <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
10:
11: <layout type="log4net.Layout.SimpleLayout" />
12:
13: <mapping>
14: <level value="ERROR" />
15: <eventLogEntryType value="Error" />
16: </mapping>
17: <mapping>
18: <level value="DEBUG" />
19: <eventLogEntryType value="Information" />
20: </mapping>
21:
22: </appender>
23:
24: <!-- RollingFileAppender schreibt eine Logdatei
25: Die Logdatei kann entweder nach Datum oder Größe überschrieben werden
26: -->
27: <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
28: <file value="logfile.log" />
29: <appendToFile value="true" />
30: <maximumFileSize value="100KB" />
31: <maxSizeRollBackups value="2" />
32:
33: <layout type="log4net.Layout.PatternLayout">
34: <param name="Header" value="[Header]\r\n" />
35: <param name="Footer" value="[Footer]\r\n" />
36: <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" />
37: </layout>
38:
39: </appender>
40:
41: <!-- Versenden von Mails -->
42: <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
43: <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
44: <subject value="%-5level %logger" />
45:
46: <to value="you@me.co.uk" />
47: <from value="me@me.co.uk" />
48: <smtpHost value="localhost" />
49: </appender>
50:
51: <!-- Setup the root category, add the appenders and set the default level -->
52: <!-- Reihenfolge All < Debug < Info < Warn < Error < Fatal < Off -->
53: <root>
54: <level value="DEBUG" />
55: <appender-ref ref="RollingFile" />
56: <appender-ref ref="EventLogAppender" />
57: <appender-ref ref="SmtpAppender" />
58: </root>
59: </log4net>
In einer Konfiguration können mehrere Appender angegeben werden. Ein Appender gibt immer das Ziel für's Logging an. Ab Zeile 9 wird der EventLogAppender konfiguriert um in das Eventlog (wär hätte das gedacht) zu schreiben. Für die Ausgabe wird noch ein Layout Pattern angegeben (Zeile 11). Ab Zeile 13 wird dann ein Mapping zwischen den log4net Kategorien und den EventLog Kategorien erstellt.
Der zweite Appender wird ab Zeile 27 definiert und ist ein RollingFileAppender. Dieser Appender schreibt eine Logdatei, die entweder nach Größe (im Beispiel 100KB, siehe Zeile 30) oder nach Datum begrenzt werden kann. Die "maxSizeRollBackups" gibt an, wie viele Dateien erhalten bleiben bevor eine Datei überschrieben wird. Um das Logverzeichnis nicht zu überfüllen ist das ein sehr guter Mechanismus.
Ein weiterer Appender wird ab Zeile 41 definiert. Über den SMTP Appender (wer zählt, wie oft ich Appender in diesem Post geschrieben habe und mir den Wert per Mail schickt, bekommt ein Eis) können die Meldungen direkt per Mail versendet werden. Es müssen nur die notwendigen Paramter für eine Mail (Subject, to, from, smtpHost) sowie der Mailtext angegeben werden und schon wird die Mail versendet.
In der Ausgabe 2/2005 der dotnetpro gibt es eine interessanten Artikel über das Loggen mittels log4net. Hier gibt es auch eine List der verfügbaren Appender, der verfügbaren Layouts sowie der Formatierungsparameter.
Ab Zeile 53 werden noch allgemeine Parameter konfiguriert. In Zeile 54 wird festgelegt, was geloggt werden soll. Bei "All" wird alles geloggt, bei "Error" werden nur die Fehler und darunterliegende (siehe Zeile 52) Meldungen geloggt.
Es ist auch möglich, für verschiedene Klassen verschiedene Appender anzugeben. Dazu muss unterhalb des <root> Elements ein Logger Element angegeben werden.
1: <logger name="MeinNamespace.MeineKlasse">
2: <level value="ALL" />
3: <appender-ref ref="RollingLogFileAppender" />
4: </logger>
So ist es möglich für die Klasse1 ins Eventlog zu posten und für Meldungen aus Klasse2 in eine Logdatei.
Interessant wäre noch zu wissen, ob und wie es möglich ist, pro Level verschiedene Appender anzugeben. Also bis Level "Warn" wird in eine Datei geschrieben und "Error" Meldungen werden per E-Mail gesendet. Falls da jemand noch Tipps für mich hat, wäre ich sehr dankbar.
Das war ein Schnellüberblick auf das log4net Framework aber ich denke damit bekommt man einen schnellen Einstieg.
Links:
log4net Homepage: http://logging.apache.org/log4net/
log4net Download: http://logging.apache.org/log4net/download.html
log4net SDK: http://logging.apache.org/log4net/release/sdk/index.html
log4net Configuration Examples: http://logging.apache.org/log4net/release/config-examples.html
dotnetpro 02/2005 "Logging mit log4net": http://www.dotnetpro.de/articles/onlinearticle1567.aspx
Downloads:
Program.cs (937,00 bytes)
logMal.exe.log4net (1,94 kb)