TRENZ : Logging mit NLog

 

Allgemeines

In allen Websites, Web-Services, externen (easyLogic-) Prozessen etc. soll ein einheitliches Vorgehen zum Loggen von Fehlern und Debug-Informationen angewandt werden.

Dazu soll als Standard NLog eingesetzt werden:  http://nlog-project.org/

Dokumentation https://github.com/nlog/NLog/wiki,  speziell zu Config-Files: https://github.com/nlog/NLog/wiki/Configuration-file

Vorteile

  • NLog übernimmt technische Details des Loggings (Dateizugriff, Archivierung etc.)
  • NLog hat unterschiedliche Log-Level:  ausführliche "DEBUG"-Informationen zur Entwicklungszeit; im Produktivbetrieb nur reduziertes Logging von Fehlern / Warnungen
  • Der Umfang des Loggings kann zur Laufzeit per Konfigurationsdatei angepasst werden, ohne dass neu kompiliert werden muss
  • Es kann verschiedene Ziele geben, an die Log-Output geschrieben wird (Logfiles, Datenbanken, E-Mail usw.)

Einbinden in ein Projekt

NLog kann in 3 einfachen Schritten integriert werden:

1. NLog als NuGet-Package einbinden:

  • im Allgemeinen verwenden wir die aktuellste stabile Version

 

2. NLog.config hinzufügen:

Die angehängte Datei als "NLog.config" in das Projekt einbinden. Wichtig: "Build-Action: Copy Always" setzen!

 

NLog.config

 

 

Mit dieser beispielhaften Logdatei können zwei Arten von Logs geschrieben werden:

  • (farbiges) Logging auf der Console (sofern es sich um eine Console-App handelt)
  • Textfile im /log - Verzeichnis unterhalb des Application-Verzeichnisses (also zb. /wwwroot/WebApplication1/log  oder /prozess/bin/release/log).   Es wird täglich ein neues Logfile erzeugt und max. 30 Tage aufbewahrt (rolling log file).

3. Logstatements im Code einfügen:

In jeder Klasse, in der Logging erfolgen soll, muss ein Logger definiert werden:

 
private static Logger log = LogManager.GetCurrentClassLogger(); 

 

Mittels log.Debug(), log.Info(), log.Warn(),  log.Error() die gewünschte Information loggen, z.B. so:

global.asax.cs
public class Global : HttpApplication
{ 
       private static Logger log = LogManager.GetCurrentClassLogger();  
 
       void Application_Start(object sender, EventArgs e)
       {
           log.Info("Application starting");            
 
           // Code, der beim Anwendungsstart ausgeführt wird
           AreaRegistration.RegisterAllAreas();
           GlobalConfiguration.Configure(WebApiConfig.Register);
           RouteConfig.RegisterRoutes(RouteTable.Routes);       
           
           try
           {
			 log.Debug("Try to initialize the application."); 
			 Initialize(); 
           }               
           catch (Exception ex)
           {
               log.Error(ex); 
           }
 
           log.Info("Startup done."); 
       }
 
       private void Initialize()
       {
           int x = 0;
           int y = 1 / x; 
       }

4. Ergebnis

log.txt
2017-03-08 15:47:40.2254|1|INFO|WebApplication1.Global|Application starting 
2017-03-08 15:47:41.0085|1|DEBUG|WebApplication1.Global|Try to initialize the application. 
2017-03-08 15:47:41.0465|1|ERROR|WebApplication1.Global|System.DivideByZeroException: Es wurde versucht, durch 0 (null) zu teilen.
   bei WebApplication1.Global.Initialize() in c:\users\nweseloh\documents\visual studio 2015\Projects\WebApplication1\WebApplication1\Global.asax.cs:Zeile 47.
   bei WebApplication1.Global.Application_Start(Object sender, EventArgs e) in c:\users\nweseloh\documents\visual studio 2015\Projects\WebApplication1\WebApplication1\Global.asax.cs:Zeile 34. 
2017-03-08 15:47:41.0555|1|INFO|WebApplication1.Global|Startup done. 

 

Anhang / Referenz

Log-Level

Die unterschiedlichen Log-Level sollten nach folgenden Grundregeln benutzt werden:

Levelwird genutzt für...
TRACE
  • SEHR detaillierte Ausgabe, um spezielle Fälle bis ins Detail zu analysieren (nur in Ausnahmefällen zur Entwicklungszeit zu nutzen)
DEBUG
  • allgemeine Informationen, die zur Entwicklungszeit benötigt werden
  • detaillierte Informationen im Livebetrieb sammeln, um komplizierte Fehler zu debuggen
  • das Verhalten einer Klasse / Methode oder gewisse Benutzeraktionen im Detail nachvollziehen
  • ist im Produktivbetrieb in der Regel deaktiviert, da DEBUG-Logs sehr umfangreich sein können!
INFO
  • Informationen über den Zustand des Gesamtsystems oder wichtiger Komponenten anzeigen (Application gestartet, gestoppt, Cache initialisiert, ...)
WARN
  • unerwartete Zustände (z.B.: "es wurde versucht, einen Container mit ID 0 zu öffnen"), die im normalen Programmablauf nicht vorgesehen sind 
  • die Ursache für WARNINGS im Log-File sollten immer untersucht + behoben werden
ERROR
  • alle Exceptions und sonstigen Fehlerfälle
  • Ursachen für ERRORs im Log-File müssen untersucht + behoben (bzw. sinnvoll behandelt) werden!

 

Beispieldatei: NLog.config

 

NLog.config
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      
      >

  <targets>
    
    <!-- if a console is available: log to a colored console window -->
    <!-- just replace all Console.WriteLine() with Log.Debug() or Log.Info() or Log.Error(). -->
    <target name="console" xsi:type="ColoredConsole"
        layout="${longdate}|${threadid}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring:when=not equals('${message}','${exception:format=tostring}')}"
        detectConsoleAvailable="true"
      />

    <!-- in addition, write to a rolling log file. each day is logged to a separate log file. files older than 30 days are deleted. -->
    <!-- logs are placed in a /logs subdirectory of your application.  -->        
    <target name="file" xsi:type="File"
        layout="${longdate}|${threadid}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring:when=not equals('${message}','${exception:format=tostring}')}"
        fileName="${basedir}/logs/_current.log"
        archiveFileName="${basedir}/logs/log.{#}.log"
        archiveNumbering="Date"
        archiveEvery="Day"
        archiveDateFormat="yyyy-MM-dd"
        maxArchiveFiles="30"
      />  

  </targets>

  <rules>
    
    <!-- 
    Too much log output? You can change minLevel to "Info", and only allow "Debug" log for specific classes, like this: 
    --> 
    <!-- 
    <logger name="*" minlevel="Info" writeTo="file" />
    <logger name="My.Namespace.With.Interesting.Class" minlevel="Debug" writeTo="file" />
    -->    
    
    <logger name="*" minlevel="Debug" writeTo="file" />    
    <logger name="*" minlevel="Debug" writeTo="console" />


  </rules>
</nlog>

 

 

 

Attachments:

NLog_01.png (image/png)
NLog.config (application/octet-stream)
NLog_02.png (image/png)
NLog.config (application/octet-stream)