Logging made easy (or Log4net for beginners)

Download Sample  (EasyLogging.zip)

Log4net is the best tool for implementing logging inside your application. It is fast, provides all the necessary appenders and an open source community behind its development. But, even with all these functionalities, it is not recommended to embed log4net code inside your application code. Rather, you must abstract it behind a customized Logger class so that you can replace it with any other tool without replacing the references in all the places within your code. I am sure that most of the teams are already following this practice but in case you are starting with Log4net or a novice programmer then don’t forget this practice. For more information about log4net, read this article. http://www.ondotnet.com/pub/a/dotnet/2003/06/16/log4net.html

 

In this short article, I will demonstrate how to integrate log4net into your application by following 3 simple steps. The information in this article may not be sufficient for every possible scenario but I found these applicable for most of the projects.

 

1)      Add reference to the log4net.dll. This is very simple and I am sure that everybody knows how to add a reference in VS.NET.

 

2)      Copy the following class code and paste it inside your application in a new class. This singleton class abstracts the log4net library and provides simple methods for your application.

 

Logger.cs

    1 using System;

    2 using log4net;

    3 using System.Diagnostics;

    4 using System.IO;

    5 

    6 [assembly:log4net.Config.DOMConfigurator()]

    7 [assembly: log4net.Config.Domain()]

    8 

    9 namespace WinGhost

   10 {

   11     /// <summary>

   12     /// Summary description for Logger.

   13     /// </summary>

   14     public class Logger

   15     {

   16         log4net.ILog log = log4net.LogManager.GetLogger("Logging");

   17 

   18         private static volatile Logger _current = null;

   19         private static object syncRoot = new object();

   20 

   21         private Logger()

   22         {}

   23 

   24         public static Logger Current

   25         {

   26             get

   27             {

   28                 if (_current == null)

   29                 {

   30                     lock(syncRoot)

   31                     {

   32                         if (_current == null)

   33                         {

   34                             _current = new Logger();

   35                         }

   36                     }

   37                 }

   38 

   39                 return _current;

   40             }

   41         }

   42 

   43         public void Debug(string message)

   44         {       

   45             if (this.log.IsDebugEnabled)

   46                 this.log.Debug("[" + DateTime.Now.ToString() + "] " + ExtractInfo(message));

   47         }

   48 

   49         public void Info(string message)

   50         {           

   51             if (this.log.IsInfoEnabled)

   52                 this.log.Info("[" + DateTime.Now.ToString() + "] " + ExtractInfo(message));

   53         }

   54 

   55         public void Error(string message, System.Exception e)

   56         {

   57             if (this.log.IsErrorEnabled)

   58                 this.log.Error("[" + DateTime.Now.ToString() + "] " + ExtractInfo(message), e);

   59         }

   60 

   61         public void Error(string message)

   62         {

   63             if (this.log.IsErrorEnabled)

   64                 this.log.Error("[" + DateTime.Now.ToString() + "] " + ExtractInfo(message));

   65         }

   66 

   67         private string ExtractInfo(string message)

   68         {

   69             StackFrame frame1 = new StackFrame(2, true);

   70             string methodName = frame1.GetMethod().ToString();

   71             string fileName = Path.GetFileName(frame1.GetFileName());

   72             string[] textArray1 = new string[6] { "File:", fileName, " - Method:", methodName, " - ", message } ;

   73 

   74             return string.Concat(textArray1);

   75         }

   76     }

   77 }

3)      Copy the following configuration settings and copy it into web.config or app.config depending on your application settings.

 

*.Config

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configuration>

xml version="1.0" encoding="utf-8" ?>

<configuration>

configuration>

<configSections>

<configSections>

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,

log4net-net-1.0" />

log4net-net-1.0" />

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,

log4net-net-1.0" />

/>

</configSections>

</configSections>

<log4net>

<log4net>

<logger name="Logging"></logger>

<logger name="Logging"></logger>

<root>

<root>

<level value="DEBUG" />

<level value="DEBUG" />

<appender-ref ref="FileAppender" />

<appender-ref ref="FileAppender" />

<appender-ref ref="UdpAppender" />

<appender-ref ref="UdpAppender" />

</root>

</root>

<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">

<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">

<file value="TestLog.txt" />

<file value="TestLog.txt" />

<appendToFile value="false" />

<appendToFile value="false" />

<datePattern value="yyyyMMdd" />

<datePattern value="yyyyMMdd" />

<rollingStyle value="Date" />

<rollingStyle value="Date" />

<staticLogFileName value="true" />

<staticLogFileName value="true" />

<layout type="log4net.Layout.PatternLayout">

<layout type="log4net.Layout.PatternLayout">

<conversionPattern value="%n[%t] %m%n" />

<conversionPattern value="%n[%t] %m%n" />

</layout>

</layout>

</appender>

</appender>

<appender name="FileAppender" type="log4net.Appender.FileAppender">

<appender name="FileAppender" type="log4net.Appender.FileAppender">

<file value="TestLog.txt" />

<file value="TestLog.txt" />

<appendToFile value="false" />

<appendToFile value="false" />

<layout type="log4net.Layout.PatternLayout">

<layout type="log4net.Layout.PatternLayout">

<conversionPattern value="%n[%t] %m%n" />

<conversionPattern value="%n[%t] %m%n" />

</layout>

</layout>

</appender>

</appender>

<appender name="UdpAppender" type="log4net.Appender.UdpAppender">

<appender name="UdpAppender" type="log4net.Appender.UdpAppender">

<param name="RemoteAddress" value="127.0.0.1" />

<param name="RemoteAddress" value="127.0.0.1" />

<param name="RemotePort" value="8080" />

<param name="RemotePort" value="8080" />

<layout type="log4net.Layout.XmlLayout">

<layout type="log4net.Layout.XmlLayout">

<param name="Prefix" value="" />

<param name="Prefix" value="" />

</layout>

</layout>

</appender>

</appender>

</log4net>

</configuration>

</configuration>

</log4net>

</configuration>

configuration>

 

 

NOTE: The above files are also provided in the sample attached with this article.

 

After following these steps, you are ready to use logging in your application and a simple statement like

 

Logger.Current.Debug(…) or Logger.Current.Error(…) prints the message to the appropriate output depending on the settings specified in the configuration file. If you are following the settings mentioned in step 3, then you‘ll find a file named “TestLog.txt” in your bin directory. Before you start to log every little condition to log file, please classify the different conditions where you need to use Debug or Error method. I personally use Error(…) for logging exceptions or error messages and Debug(…) for everything else. This way, you can turn off Debug(…) messages by replace

<level value="DEBUG" /> with

<level value="ERROR" />

 

Other Tools:

Here are some other tools are I use frequently with log4net.

 

BareTail: BareTail is a real time viewer for log files (or any text file).

http://www.baremetalsoft.com/baretail/index.php

 

Log4Net Viewer: A very nice log viewer for lo4net, especially useful in situations where you don’t have control over your deployment environment. There is a UdpAppender section in my configuration file so you can test it with the sample project without making any changes.

Tip: Use the log filter text box to filter messages from any file, method.

http://www.devintelligence.com/Log4NetViewer/

 

Resources:


Log4net FAQ:
http://log4net.sourceforge.net/release/1.2.0.30316/doc/manual/faq.html

Using log4net:
http://www.ondotnet.com/pub/a/dotnet/2003/06/16/log4net.html

Configuration:

http://logging.apache.org/log4net/release/manual/configuration.html

Examples:

http://logging.apache.org/log4net/release/example-apps.html

Other Interesting Links:
How To Capture Web Events In log4net

[NEW] A realistic log4net config

 

 

3 Comments

  • Great article... except for lock(typeof(LOgger))... scary man. scary. Numerous articles about NOT locking on the TYPE because of implicit deadlocks that can occur between the framework and the locked type.



    You'd want to use a static S_syncObject for locking:



    private static object S_syncLock = new object();



    change the lock(typeof(Logger)) to lock(S_syncObject)



    remember you want locks to be as granular as possible, locking on a type severely violates that principal (and of course no principals are absolute, but the point is made...)

  • Thanks Eric for pointing out the lock problem.



    The code has been updated to reflect Eric's suggestion.

  • Thanks for link! In next version (0.0.8) of log4net viewer will be added support for FileAppender and DbAppender.

Comments have been disabled for this content.