bonn-to-code.netbonn-to-code.netbonn-to-code.netbonn-to-code.net
Logging
(mit log4net)
Logging
(mit log4net)
17.02.2009
Thomas Mentzel
EMail: thomas.mentzel@logica.com
Website: http://www.logica.com/de
bonn-to-code.netbonn-to-code.net
AgendaAgenda
Captain's log, USS Enterprise
Do It Yourself
Buy it, don‘t make it
Mehr ist Mehr ist Mehr ist Mehr
bonn-to-code.netbonn-to-code.net
„Captain's log, USS Enterprise“„Captain's log, USS Enterprise“
„Eine Logdatei (engl. log file) beinhaltet das
automatisch erstellte Protokoll aller oder
bestimmter Aktionen von Prozessen auf
einem Computersystem. […]
Wichtige Anwendungen finden sich vor allem
im Bereich der Prozess-Kontrolle und im
Automatisierungsbereich. Prinzipiell werden
alle Aktionen mitgeschrieben, für die ein
späteres Audit erforderlich ist oder sein
könnte. […]“ - Wikipedia
bonn-to-code.netbonn-to-code.net
LoggenLoggen
Zentrale Komponenten wie Controller
Datenbankoperationen / Persistenzschicht
Zwischenergebnisse bei Algorithmen
Hinweis: Visual Studio Output Window ist
sehr langsam, also nicht wundern!
bonn-to-code.netbonn-to-code.net
Vorteile (Entwicklung)Vorteile (Entwicklung)
Debuggen ohne Breakpoint
Ablaufkontrolle
Blick unter die Motorhaube beim Fahren
Integrieren in die normale Arbeit
bonn-to-code.netbonn-to-code.net
Vorteile (Kunden)Vorteile (Kunden)
Nützliche objektive Informationen
Detailierte Fehlerverfolgung
Reproduzieren des Fehlers
Fehleranalyse beim Kunden
bonn-to-code.netbonn-to-code.net
Loggen?Loggen?
...
2009-02-13 11:12:41,372 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:41,512 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,184 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,200 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
...
...
2009-02-13 11:12:44,403 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,434 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,434 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst
...
2009-02-13 11:12:10,184 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren der Datenbank
2009-02-13 11:12:10,184 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes
2009-02-13 11:12:10,215 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes
2009-02-13 11:12:10,215 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes
bonn-to-code.netbonn-to-code.net
Loggen!Loggen!
2009-02-13 11:12:08,762 [1] DEBUG Vap.Psm.Datenzugriff.DBInit [(null)] - Erstellen der Prozedur/View
'Vap.Psm.Datenzugriff.Sql.SVAktualisiereBefAlterChance.prc.init.sql'
2009-02-13 11:12:08,778 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von IF EXISTS (SELECT *
FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[SVAktualisiereBefAlterChance]') AND
OBJECTPROPERTY(id,N'IsProcedure') = 1)
2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von CREATE PROCEDURE
[SVAktualisiereBefAlterChance]
2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.DBInit [(null)] - Erstellen der Prozedur/View
'Vap.Psm.Datenzugriff.Sql.SVAktualisierePerskat.prc.init.sql'
2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von IF EXISTS (SELECT *
FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[SVAktualisierePersKat]') AND OBJECTPROPERTY(id,N'IsProcedure') =
1)
2009-02-13 11:12:08,809 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von CREATE PROCEDURE
[SVAktualisierePersKat]
bonn-to-code.netbonn-to-code.net
Demo 1: Einfaches LoggenDemo 1: Einfaches Loggen
Logging einer Math-Klasse
Logging über die Ausgabe- und Debug-Konsole
Logging einfach abschaltbar
bonn-to-code.netbonn-to-code.net
NachteileNachteile
KISS Prinzip verletzt
DRY Prinzip verletzt
OCP verletzt
Abstufung der Fehler (Level)
bonn-to-code.netbonn-to-code.net
Do It YourselfDo It Yourself
Erweiterbarkeit der Ausgabe
Datei, Datenbank, …
Fehler-Kontext
Einfache Einbindung
Wenig Code (eine Zeile)
Kategorisierung der Fehler
Error, Info, Debug
Fatal, Warn
bonn-to-code.netbonn-to-code.net
Demo 2: Logging Framework SelbstbauDemo 2: Logging Framework Selbstbau
Logging Bibliothek
Wiederverwendbar
Erweiterbar
Einfach zu benutzen
bonn-to-code.netbonn-to-code.net
Erweiterbarkeit der Ausgabe
Datei, Datenbank, …
Fehler-Kontext
Einfache Einbindung
Wenig Code (eine Zeile)
Kategorisierung der Fehler
Error, Info, Debug
Fatal, Warn
Do It Yourself (Review)Do It Yourself (Review)
IAppender
ILog
Logger Factory
Static Instance
ILog.{LogLevel}
Log-Level
bonn-to-code.netbonn-to-code.net
Buy it, don‘t make itBuy it, don‘t make it
Fertige Frameworks …
sind günstiger als selbst erstellte
enthalten mehr Features
sind vielfach bewährt
sind besser dokumentiert
haben eine gute Architektur
bonn-to-code.netbonn-to-code.net
log4netlog4net
Apache Logging Project
http://logging.apache.org/log4net/index.html
Apache License, Version 2.0
bonn-to-code.netbonn-to-code.net
Log4net FeaturesLog4net Features
Mehrere Logging Ziele (Appender)
XML Konfiguration
Modular und Erweiterbar
Logger Hierarchie
bonn-to-code.netbonn-to-code.net
Logging in 5 MinutenLogging in 5 Minuten
Referenz hinzufügen: log4net.dll
Assembly.cs: XML Konfiguration benutzen
[assembly: XmlConfigurator()]
bonn-to-code.netbonn-to-code.net
Logging in 5 MinutenLogging in 5 Minuten
App.config
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
bonn-to-code.netbonn-to-code.net
Logging in 5 MinutenLogging in 5 Minuten
Quellcode
// logger.snippet –über „logger“ erreichbar in der IDE
#region Log4Net
/// <summary>
/// log4net Klassen-Logger
/// </summary>
private static readonly log4net.ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
// log.snippet –über „log“ erreichbar in der IDE
if (log.IsErrorEnabled) log.Error("...");
if (log.IsDebugEnabled) log.Debug("...", exception);
bonn-to-code.netbonn-to-code.net
Demo 3: log4net IntegrationDemo 3: log4net Integration
Logging mit log4net
Integration
Math.cs
AssemblyInfo.cs
Konfiguration
app.config
bonn-to-code.netbonn-to-code.net
Logger HierarchieLogger Hierarchie
Kinder erben die Konfiguration ihrer Väter
Namespace („.“) bildet Hierarchie
Konfiguration der Kinder überschreibbar
<logger name="BonnToCode.Logging.Demo.Math">
<level value="Info" />
</logger>
bonn-to-code.netbonn-to-code.net
ErweiterbarkeitErweiterbarkeit
IAppender
Ausgabeziel
ILayout
Aussehen der Ausgabe
bonn-to-code.netbonn-to-code.net
Toolbox LoggerToolbox Logger
Ziel: Logging in eine optionale Toolbox
IAppender: ToolboxAppender-Klasse
Inherits AppenderSkeleton
Static Instanz der Logging Form
Formular: LoggingForm-Klasse
Formular mit TextBox für die Meldungen
Methode „Append“ für Fehlermeldungen
XML Konfiguration (ToolboxAppender)
bonn-to-code.netbonn-to-code.net
Demo 3: log4net Erweiterung IDemo 3: log4net Erweiterung I
log4net Erweiterung
ToolBox Appender
Einbinden in Konfiguration
bonn-to-code.netbonn-to-code.net
Toolbox Logger PropertiesToolbox Logger Properties
Ziel: Breite und Höhe der Toolbox über die
Konfiguration festlegen
ToolboxAppender: Properties einfügen
public int Height
{ get; set; }
public int Width
{ get; set; }
XML Appender Konfiguration erweitern
<appender […]>
<height value="300" />
<width value="200" />
<layout […]>
[…]
</layout>
</appender>
bonn-to-code.netbonn-to-code.net
Demo 3: log4net Erweiterung IIDemo 3: log4net Erweiterung II
log4net Erweiterung
Toolbox Appender Properties
Properties in Konfiguration
bonn-to-code.netbonn-to-code.net
Fragen?Fragen?

Logging mit log4net

  • 1.
  • 2.
    bonn-to-code.netbonn-to-code.net AgendaAgenda Captain's log, USSEnterprise Do It Yourself Buy it, don‘t make it Mehr ist Mehr ist Mehr ist Mehr
  • 3.
    bonn-to-code.netbonn-to-code.net „Captain's log, USSEnterprise“„Captain's log, USS Enterprise“ „Eine Logdatei (engl. log file) beinhaltet das automatisch erstellte Protokoll aller oder bestimmter Aktionen von Prozessen auf einem Computersystem. […] Wichtige Anwendungen finden sich vor allem im Bereich der Prozess-Kontrolle und im Automatisierungsbereich. Prinzipiell werden alle Aktionen mitgeschrieben, für die ein späteres Audit erforderlich ist oder sein könnte. […]“ - Wikipedia
  • 4.
    bonn-to-code.netbonn-to-code.net LoggenLoggen Zentrale Komponenten wieController Datenbankoperationen / Persistenzschicht Zwischenergebnisse bei Algorithmen Hinweis: Visual Studio Output Window ist sehr langsam, also nicht wundern!
  • 5.
    bonn-to-code.netbonn-to-code.net Vorteile (Entwicklung)Vorteile (Entwicklung) Debuggenohne Breakpoint Ablaufkontrolle Blick unter die Motorhaube beim Fahren Integrieren in die normale Arbeit
  • 6.
    bonn-to-code.netbonn-to-code.net Vorteile (Kunden)Vorteile (Kunden) Nützlicheobjektive Informationen Detailierte Fehlerverfolgung Reproduzieren des Fehlers Fehleranalyse beim Kunden
  • 7.
    bonn-to-code.netbonn-to-code.net Loggen?Loggen? ... 2009-02-13 11:12:41,372 [1]INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:41,512 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,184 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,200 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst ... ... 2009-02-13 11:12:44,403 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,434 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,434 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst 2009-02-13 11:12:44,450 [1] INFO Vap.Psm.Basisklassen.Controller [(null)] - Controller.ReportProgress wird ausgelöst ... 2009-02-13 11:12:10,184 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren der Datenbank 2009-02-13 11:12:10,184 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes 2009-02-13 11:12:10,215 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes 2009-02-13 11:12:10,215 [1] DEBUG Vap.Psm.Basisklassen.SqlCommandCache [(null)] - Initialisieren des Comand Objektes
  • 8.
    bonn-to-code.netbonn-to-code.net Loggen!Loggen! 2009-02-13 11:12:08,762 [1]DEBUG Vap.Psm.Datenzugriff.DBInit [(null)] - Erstellen der Prozedur/View 'Vap.Psm.Datenzugriff.Sql.SVAktualisiereBefAlterChance.prc.init.sql' 2009-02-13 11:12:08,778 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[SVAktualisiereBefAlterChance]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) 2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von CREATE PROCEDURE [SVAktualisiereBefAlterChance] 2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.DBInit [(null)] - Erstellen der Prozedur/View 'Vap.Psm.Datenzugriff.Sql.SVAktualisierePerskat.prc.init.sql' 2009-02-13 11:12:08,793 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[SVAktualisierePersKat]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) 2009-02-13 11:12:08,809 [1] DEBUG Vap.Psm.Datenzugriff.Internal.DBBase [(null)] - Ausführen von CREATE PROCEDURE [SVAktualisierePersKat]
  • 9.
    bonn-to-code.netbonn-to-code.net Demo 1: EinfachesLoggenDemo 1: Einfaches Loggen Logging einer Math-Klasse Logging über die Ausgabe- und Debug-Konsole Logging einfach abschaltbar
  • 10.
    bonn-to-code.netbonn-to-code.net NachteileNachteile KISS Prinzip verletzt DRYPrinzip verletzt OCP verletzt Abstufung der Fehler (Level)
  • 11.
    bonn-to-code.netbonn-to-code.net Do It YourselfDoIt Yourself Erweiterbarkeit der Ausgabe Datei, Datenbank, … Fehler-Kontext Einfache Einbindung Wenig Code (eine Zeile) Kategorisierung der Fehler Error, Info, Debug Fatal, Warn
  • 12.
    bonn-to-code.netbonn-to-code.net Demo 2: LoggingFramework SelbstbauDemo 2: Logging Framework Selbstbau Logging Bibliothek Wiederverwendbar Erweiterbar Einfach zu benutzen
  • 13.
    bonn-to-code.netbonn-to-code.net Erweiterbarkeit der Ausgabe Datei,Datenbank, … Fehler-Kontext Einfache Einbindung Wenig Code (eine Zeile) Kategorisierung der Fehler Error, Info, Debug Fatal, Warn Do It Yourself (Review)Do It Yourself (Review) IAppender ILog Logger Factory Static Instance ILog.{LogLevel} Log-Level
  • 14.
    bonn-to-code.netbonn-to-code.net Buy it, don‘tmake itBuy it, don‘t make it Fertige Frameworks … sind günstiger als selbst erstellte enthalten mehr Features sind vielfach bewährt sind besser dokumentiert haben eine gute Architektur
  • 15.
  • 16.
    bonn-to-code.netbonn-to-code.net Log4net FeaturesLog4net Features MehrereLogging Ziele (Appender) XML Konfiguration Modular und Erweiterbar Logger Hierarchie
  • 17.
    bonn-to-code.netbonn-to-code.net Logging in 5MinutenLogging in 5 Minuten Referenz hinzufügen: log4net.dll Assembly.cs: XML Konfiguration benutzen [assembly: XmlConfigurator()]
  • 18.
    bonn-to-code.netbonn-to-code.net Logging in 5MinutenLogging in 5 Minuten App.config <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> </configSections> <log4net> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> </layout> </appender> <root> <level value="DEBUG"/> <appender-ref ref="ConsoleAppender" /> </root> </log4net>
  • 19.
    bonn-to-code.netbonn-to-code.net Logging in 5MinutenLogging in 5 Minuten Quellcode // logger.snippet –über „logger“ erreichbar in der IDE #region Log4Net /// <summary> /// log4net Klassen-Logger /// </summary> private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion // log.snippet –über „log“ erreichbar in der IDE if (log.IsErrorEnabled) log.Error("..."); if (log.IsDebugEnabled) log.Debug("...", exception);
  • 20.
    bonn-to-code.netbonn-to-code.net Demo 3: log4netIntegrationDemo 3: log4net Integration Logging mit log4net Integration Math.cs AssemblyInfo.cs Konfiguration app.config
  • 21.
    bonn-to-code.netbonn-to-code.net Logger HierarchieLogger Hierarchie Kindererben die Konfiguration ihrer Väter Namespace („.“) bildet Hierarchie Konfiguration der Kinder überschreibbar <logger name="BonnToCode.Logging.Demo.Math"> <level value="Info" /> </logger>
  • 22.
  • 23.
    bonn-to-code.netbonn-to-code.net Toolbox LoggerToolbox Logger Ziel:Logging in eine optionale Toolbox IAppender: ToolboxAppender-Klasse Inherits AppenderSkeleton Static Instanz der Logging Form Formular: LoggingForm-Klasse Formular mit TextBox für die Meldungen Methode „Append“ für Fehlermeldungen XML Konfiguration (ToolboxAppender)
  • 24.
    bonn-to-code.netbonn-to-code.net Demo 3: log4netErweiterung IDemo 3: log4net Erweiterung I log4net Erweiterung ToolBox Appender Einbinden in Konfiguration
  • 25.
    bonn-to-code.netbonn-to-code.net Toolbox Logger PropertiesToolboxLogger Properties Ziel: Breite und Höhe der Toolbox über die Konfiguration festlegen ToolboxAppender: Properties einfügen public int Height { get; set; } public int Width { get; set; } XML Appender Konfiguration erweitern <appender […]> <height value="300" /> <width value="200" /> <layout […]> […] </layout> </appender>
  • 26.
    bonn-to-code.netbonn-to-code.net Demo 3: log4netErweiterung IIDemo 3: log4net Erweiterung II log4net Erweiterung Toolbox Appender Properties Properties in Konfiguration
  • 27.