Autor: Thomas Reinwart 2009-07-29
office@reinwart.com
Logging Möglichkeiten mit .net...............................................................................................................2 Log4net .................................................................................................................................................... 3 Log Appender....................................................................................................................................... 4
Log4net Beispiel Konfiguration............................................................................................................ 5 Microsoft Enterprise Library Logging....................................................................................................... 6
Beispiel Konfiguration.......................................................................................................................... 6
Version History .................................................................................................................................... 8
Links ..................................................................................................................................................... 8
Warum ist Logging in einer Applikation wichtig? Einfach um einen Einblick hinter die Fassade der Anwendung zu haben, etwa was macht eigentlich ein Service am Rechner das ständig 50% CPU Zeit benötigt und um Support leisten zu können. Logging ist mehr als Console.WriteLine("Log");. Man kann unter positiv und negativ Logging unterscheiden. Positiv Logging gibt Statusinformation aus, wie etwa „gestartet am“, „Datei xy gelesen“. Diese Ausgaben sollten laufend erfolgen, aber nicht permanent um das System nicht unnötig mit Informationen zu belasten. Zu den positiv Meldungen gehören je nach eingestellten Log Level auch die Log Debug Informationen. Je nach Umfang der eingefügten Log Debugs im Code kann es hier schon zu System Performance beeinflussenden Zuständen kommen, allerdings wird dies nur der Ausnahmezustand im Zuge einer Fehlersuche vorkommen. Zum Negativ Logging gehören natürlich alle Applikationsfehler oder systemkritischen Zustände, die den Betrieb der eigenen Applikation nicht möglich machen. Die Logging Information selber muss aufschlussreich sein. Also nicht „Ein Fehler ist aufgetreten“ oder „Datei kann nicht gelesen werden“ sondern wenn möglich auch die zusammenhängenden Parameter die eine Exception verursachen. Eine sprechende Meldung wäre anstatt „Datei kann nicht gelesen werden“, denn eigentlichen Grund im Exceptionhandling zu erkennen, der sein könnte „Datei xy ist nicht vorhanden“. Ein gutes Logging erspart viel Zeit die Fehler nachzustellen und zu debuggen. Nicht in ein Logging gehören sensible Daten wie Passwörter, man weiß nie welchen Personen ein Logfile im Supportfall gesendet wird. Wohin eine Loginformation geschrieben werden soll hängt von der Applikation selber, oder etwa der Unternehmens Policy ab, wie die zahlreichen Anwendungen zentral über deren Log Mechanismen überwacht werden können. (Bsp. Eventlog Überwachen mit Microsoft Operation Manager -MOM) Das Logging sollte daher außerhalb der eigenen Anwendung konfigurierbar sein, um nicht nachkompilieren und neu ausliefern zu müssen. Der Logvorgang kann so eingerichtet sein, dass es der User merkt oder auch komplett im Hintergrund vor sich geht (Achtung sensible Daten), etwa per Mail oder SMS an den Hersteller. Bei einem Logger stehen mehrere, auch parallele Möglichkeiten der Ausgabe zur Verfügung, auch Filtern der Loglevels ist ein Thema. Logging muss von Anfang an bei der Implementierung vorgesehen werden und nicht nachträglich an den bereits bekannten kritischen Stellen eingefügt werden.
Natürlich kann man selber auch in Files und Eventlogs loggen. Allerding muss man auch Log Szenarien wie Mandantenfähigkeit oder thread safe Operationen bedenken, um einen Überblick zu bewahren und ohne die eigentliche Applikation auszubremsen. Über zwei Möglichkeiten bestehender und bewährter Logging Komponenten für .net möchte ich hier berichten.
Lizenz: Apache License, Version 2.0
Log4net besteht aus der Basis Komponente und den Appendern. Ein Log Appender stellt eine spezielle Log Funktion dar. Die Konfiguration ist XML basierend.
Über die externe XML Konfiguration können die Log Appender und ihre Eigenschaften zur Laufzeit angepasst werden, ohne dass die eigene Applikation neu gestartet wird. D.h. ich kann die Logging Level eines Appenders verändern -etwa den Loglevel von Error auf All stellen, um einen Fehler auf die Spur zu kommen. Beim Instanziieren wird log4net das Configfile bekanntgegeben, über den Filewatcher erkennt es die Änderungen am File und verwendet die aktuelle Config. Die Logger Konfiguration muss nicht in der App.Config bzw. Web.Config definiert werden, dies kann bzw. mach sogar Sinn es in einem eigenem XML File zu hinterlegen. Wenn es in der Web.Config steht, würde beim Speichern der Web.Config die IIS Session restartet werden.
XmlConfigurator.ConfigureAndWatch(configfilename);
Auch das Log Layout kann zu jedem Appender konfiguriert werden.
Bsp:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %c [%x] -%m%n " />
</layout>
Log Ausgabe: 2009-06-03 07:33:36,888 [3004] INFO DefaultLogging – Beispiel Logausgabe
Unterstützt die Frameworks:
In der eigenen Applikation werden an passenden Stellen im Code Log Aufrufen hinzugefügt.
Bsp:
Log.Info("Datei wird geladen");
Log.Warn(string.Format("Die Datei {0} kann nicht gefunden werden",fileinfo));
catch (Exception ex) {
Log.Error(ex); }
Log Core Levels:
Level | Nutzen wenn | ||||
---|---|---|---|---|---|
ALL | Gibt immer alles aus, Level unabhängig. | ||||
DEBUG | Entwickler Infos, Fehlersuche. | ||||
INFO | Positiv Logging | ||||
WARN | Warnungen, Komponente kann aber weiterarbeiten | ||||
ERROR | Fehler, unhandled Exceptions | ||||
FATAL | Fatale Fehler | ||||
OFF | Logging komplett abdrehen |
Appender | Log Event Ausgabe in Form von | ||||
---|---|---|---|---|---|
AdoNetAppender | Datenbanklogging (MS SQL Server, MS Access, Oracle, IBM DB2, SQLite, …) | ||||
AnsiColorTerminalAppender | ANSI Terminal | ||||
AspNetTraceAppender | asp Seite | ||||
ColoredConsoleAppender | Farbe auf Console (Dos Fenster) | ||||
ConsoleAppender | Console | ||||
EventLogAppender | Windows Eventlog | ||||
FileAppender | Dateilogging | ||||
LocalSyslogAppender | Syslog Service (Unix) | ||||
MemoryAppender | Memory Buffer | ||||
NetSendAppender | Windows Messenger Service | ||||
OutputDebugStringAppender | Debugger | ||||
RemoteSyslogAppender | Remote Syslog Service (UDP network) | ||||
RemotingAppender | .net remoting | ||||
RollingFileAppender | Rotierendes Dateilogging, konfigurierbar Anzahl Files und Größe | ||||
SmtpAppender | SMTP Email Versand | ||||
TelnetAppender | Telnet | ||||
TraceAppender | .net trace | ||||
UdpAppender | UDP datagrams über UDP Client |
Es können auch eigene Log Appender erstellt werden, etwa einen SMS Appender.
Beispiel und Beschreibung einer Log Konfiguration:
Im <root> wurde in diesem Beispiel festgelegt, dass es alle (ALL) Events betrifft die an den LogRollingFileAppender und an den ForwardingAppender weitergeleitet werden. Im LogRollingFileAppender wird alles entsprechend dieser Appender Konfiguration geloggt. Im ForwardingAppender festgelegt, dass alle Log Events ab inklusive dem Level WARN (Warn, Error und Fatal) alle Events an den SmtpAppender weitergeleitet werden. Wie man erkennen kann, lässt sich hier mit eine Log Level / Appender Hierarchie erstellen.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <!--<section name = "log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net-net-1.1" /> --> <section name="log4net" type="System.Configuration.IgnoreSectionHandler" /> </configSections>
<!--This section contains the log4net configuration settings -->
<log4net> <!--Define some output appenders --> <appender name="ForwardingAppender" type="log4net.Appender.ForwardingAppender" >
<threshold value="WARN"/>
<appender-ref ref="SmtpAppender" /> </appender> <!--Setup the root category, add the appenders and set the default level --> <root>
<level value="ALL" /> <appender-ref ref="LogRollingFileAppender" /> <appender-ref ref="ForwardingAppender" />
</root> <!--Define some output appenders --> <appender name="LogRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="c:\temp\My_UnitTest.log" /> <param name="AppendToFile" value="true" /> <param name="MaxSizeRollBackups" value="9" /> <param name="MaximumFileSize" value="10MB" /> <param name="RollingStyle" value="Size" /> <param name="StaticLogFileName" value="true" /> <layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Start]\r\n" /> <param name="Footer" value="[End]\r\n" /> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] -%m%n" />
</layout> </appender> <appender name="LogFileAppender" type="log4net.Appender.FileAppender" >
<file value="c:\temp\My_UnitTest.log" /> <appendToFile value="true" /> <layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%n%d [%t] %-5p %c -%m" />
</layout> </appender> <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value= "" /> <from value= "" /> <subject value= "Logger" /> <smtpHost value= "" /> <bufferSize value= "20" /> <!--records --> <lossy value= "false" /> <layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%n%date [%t] %-5p %c -%m" /> </layout> </appender>
</log4net> </configuration>
Die XML Konfiguration ist überschaubar einfach. Ein GUI Konfiguration gibt es von log4net (Apache.org) selber nicht, aber im Internet findet man Editoren für log4net.
Lizenz: Microsoft Public License (Ms-PL)
Voraussetzungen:
Log Möglichkeiten | Log Event Ausgabe in Form von | ||||
---|---|---|---|---|---|
Database Trace Listener | Datenbank | ||||
Email TraceListener | SMTP Email | ||||
FlatFile TraceListener | Single file | ||||
Formatted EventLog TraceListener | Eventlog | ||||
Msmq TraceListener | Microsoft Message Queue | ||||
Rolling Flat File Trace Listener | Rolling file | ||||
System.Diagnostics TraceListener | Event | ||||
WMI TraceListener | WMI | ||||
XML Trace Listener | XML |
<?xml version="1.0" encoding="utf-8"?> <configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
<listeners>
<add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListe nerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
traceOutputOptions="LogicalOperationStack" filter="All" type="LogSample.Tests.Logging.DebugTraceListener, LogSample.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Debug Trace Listener" initializeData="" formatter="Text Formatter" />
<add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnostic sTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
traceOutputOptions="LogicalOperationStack" filter="All" type="System.Diagnostics.ConsoleTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
name="System.Diagnostics TraceListener" initializeData="" /> </listeners> <formatters>
<add template="{severity} {timestamp} {category} {message}" type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="Text Formatter" /> </formatters> <categorySources>
<add switchValue="All" name="General"> <listeners> <add name="Debug Trace Listener" /> </listeners>
</add> </categorySources> <specialSources>
<allEvents switchValue="All" name="All Events" /> <notProcessed switchValue="All" name="Unprocessed Category"> <listeners> <add name="Debug Trace Listener" />
</listeners> </notProcessed> <errors switchValue="All" name="Logging Errors & Warnings">
<listeners> <add name="Debug Trace Listener" /> </listeners> </errors> </specialSources> </loggingConfiguration> </configuration>
Die Konfiguration nach einer ähnlichen Logik wie bei log4net aufgebaut.
Konfiguration mittels GUI Die Konfiguration kann mittels GUI Unterstützung bearbeitet werden. Es kann mehrere Config Files parallel offen haben. Diverse Listener können einfach über das Kontextmenü hinzugefügt werden, die notwendigen Parameter eingefügt werden. Fehler im Gerüst des Configfiles sind damit ausgeschlossen.
1.0: 2005/01
1.1: 2005/06: .NET Framework 1.1
2.0: 2006/01: .NET Framework 2.0
3.0: 2007/04: .NET Framework 3.0
3.1: 2007/05: kleinere Erweiterungen und Policy injection application blocks
4.0: 2008/05: Unity Application Blocks, Visual Studio 2008
4.1: 2008/10: Aktuelle Version für .net 3.5 und Visual Studio 2008 Sp1
5.0: 2010 ?
Enterprise Library 4.1 – October 2008 (for .NET Framework 3.5 and Visual Studio 2008)
http://msdn.microsoft.com/en-us/library/dd203099.aspx