Log4Net for noobs
Log4Net is a fairly old framework for logging, but it still serves it's purpose well! A couple of years back I wrote a tutorial on how to use Log4Net, today I stumbled across it, and I am quite pusseled that it is still as relevant today as it was back then. For those looking for a quick tutorial on how to use Log4Net, enjoy:
To use Log4Net, we need the log4net.dll library, which can be downloaded from http://logging.apache.org/log4net/.
Log 4Net can be used log both informal and error messages, Log4Net groups the messages in the following levels (ordered hierarchically):
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
Setting up log4Net
Log 4Net is configured easily through usage of the App.config file which is automatically loaded for .Net applications. The configuration part specific for Log4Net is structured like:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net debug="false">
<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
<param name="File" value="saps-log.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<priority value="ALL" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ConsoleAppender"/>
</root>
<category name="DataBinding.Program">
<priority value="ALL" />
</category>
<category name="DataBinding.Form1">
<priority value="WARN"/>
</category>
</log4net>
This examples shows how to log into two separate locations:
- One LogFileAppender, which appends to the saps-log.txt file, not deleting if already present
- ConsoleAppender, which logs to the console
Seen in this example there are different levels of debugging information on separate classes or namespaces, eg. DataBinding.Form1 class we only display messages of level WARN and above. Whereas we log all messages for rest components.
In most cases we turn this the other way, log only ERROR and FATAL, and can turn on more granular information when needed.
To initialize log4Net from the configurations in App.cofig, specify the following in your main method:
log4net.Config.XmlConfigurator.Configure();
Using log4net in a class
To use Log4Net in one of your classes, you specify the following static variable:
private static readonly ILog log;
Which can be initalized in two separate ways, either through Refelection or directly with a hardcoded identifier for the current class. The two different initalizations is as follows:
private static readonly ILog log = LogManager.GetLogger("DataBinding.Program");
or
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
If you don’t need to have another identification for the logger that the class name, you should use the Reflecition type, If you however need a separate idenfication or more granularity you could use the first version, where you spesify a string instead of a Type.
Logging with log4net
So to finally use log4Net to log, we put in logging information wherever suitable:
string myFileName = @"C:\ThisFileDont.Exist";
try
{
log.Info("Reading from file " + myFileName);
System.IO.StreamReader sr = new System.IO.StreamReader(myFileName);
Console.WriteLine(sr.ReadToEnd());
}
catch (Exception e)
{
log.Error("An error occured reading the file : " + e.ToString());
}
To code will output the following to our log file:
2006-12-11 13:32:51,344 [9] INFO DataBinding.Form2 - Reading from file C:\ThisFileDont.Exist
2006-12-11 13:32:51,360 [9] ERROR DataBinding.Form2 - An error occured reading the file : System.IO.FileNotFoundException: Could not find file 'C:\ThisFileDont.Exist'.
File name: 'C:\ThisFileDont.Exist'
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
at System.IO.StreamReader..ctor(String path)
at DataBinding.Form1.OpenStream() in C:\src\prototyper\DataBinding\Form2.cs:line 27