Add logging to your application using log4net

Add logging to your application using log4net

Logging is a feature that every application will need at some point during its lifetime, if not during development and testing then certainly when it has gone live. Despite this, developers often neglect to build it in from the start and then end up hurriedly shoehorning it in at the last minute. As a result the logging infrastructure is limited in its flexibility and usefulness.

Even if logging is integrated from the start, developers often choose to build their own logging code, using classes in the System.IO namespace to simply write some timestamps and messages out to a text file. Whilst there is nothing wrong with this, employing a dedicated logging framework can both cut down on development time and offer a rich set of features to play with. This article will provide an introduction to one such framework: log4net.

Introduction

log4net is an open source logging tool produced by the Apache Logging Services project. As such it is free to use and distribute, and its source code is available for download. The framework itself is built upon four key concepts

  • an appender is responsible for writing log messages to a particular destination, e.g. database, text file, email
  • a logger is made up of one or more appenders and provides methods for logging messages and objects
  • a layout governs the formatting of log messages before they are written by the appender
  • a renderer is used to transform an object into a log message. Users of log4net can create their own renderers to ensure that objects such as exceptions are formatted to their liking

This may seem a lot to digest at first but in reality only two items need to be set up in order to use log4net: an appender and the root logger.

Configuration

To get started with log4net, fire up Visual Studio 2008 and create a new Web Application project. Add a reference to the log4net dll (download from here) and a new XML document called Logging.config, which will be used to contain log4net’s configuration. It is possible to put this directly in the web.config however that would mean resetting the web site each time the logging settings were altered, which is impractical in a live scenario.

The configuration XML begins with a root log4net node, followed by one or more appender nodes. The simplest appender to use is the TextFileAppender, which can be set up as follows

<appender name="TextFileAppender" type="log4net.Appender.FileAppender">
  <file value="LoggingDemo.log" />
  <appendToFile value="true" />
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date{yyyy-MM-dd HH:mm:ss.fff} %-5level %message%newline" />
  </layout>
</appender>

As with all appenders, a friendly name (TextFileAppender) must be given, along with the full type name of the appender (log4net.Appender.FileAppender). Within the appender node though, the settings are very much specific to the particular appender. In the case of FileAppender, log4net is configured to append log messages to LoggingDemo.log, in the root of the web site. Had appendToFile been false, a new file would be created each time, which isn’t very useful. The minimal lock is being used so that the file can be deleted without resetting IIS to release it, although this hampers performance a little. The final item of interest is the layout, which will be covered in a later post.

The last piece of config is the most important: setting up the root logger, which is done like this

<root>
  <appender-ref ref="TextFileAppender" />
</root>

The log4net config file must contain at least one logger: the root logger. More loggers can be added underneath the root, building up a hierarchy, although that is beyond the scope of this article. In this example the root logger has been set to use the TextFileAppender, so all logged messages will be sent to the LoggingDemo.log file.

Usage

Now that log4net has been configured it’s time to add some C# to the test web site. First off an assembly-level attribute must be added to the source code, as follows

[assembly: XmlConfigurator(ConfigFile="Logging.config", Watch=true)]

The best place for this code is in AssemblyInfo.cs with all other assembly-level attributes. By adding this log4net becomes aware of where the logging config file is, and whether or not to monitor it for changes. A using statement is also needed to import types from the log4net namespace.

The next task is to get a reference to a logger object, which implements the ILog interface. This can be done by calling LogManager.GetLogger, passing in a type or a name, which helps to identify which logger should be returned. In this example there is only the root logger, so passing in any type is sufficient to retrieve the root logger. Add the following code to the Page_Load method of the Default.aspx page

[chsarp]
ILog log = LogManager.GetLogger(this.GetType());
[/csharp]

Recommended practice is to pass in the current type, that way if a type-specific logger is added later on, no code changes are required.

At this point the ILog object is ready to be used. It is important to decide what logging level is appropriate for the message, choosing one from this list

  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL

For each level of detail there are methods for logging messages, exceptions, and passing in a format string with arguments, in a similar way to using the string.Format function. Check out the ILog interface definition for more details.

For now, just use the Info method and pass in any message, in this case just log the fact that the event has fired, for example

log.Info("Page_Load has fired");

Now run the web site and browse to the page; a log file should be created with a single line containing the log message. Hurrah!

Adjusting the logging level

Let’s return to the concept of logging level. The idea behind this is that, by adjusting the level in the config file, it is possible to see more, or less, messages in the log file. A typical scenario is that an application will run with minimal logging most of the time, recording just FATAL and ERROR level information.

However if a bug is reported it is simple to switch the level to INFO or even DEBUG, which will cause many more messages to be logged and hopefully provide an insight into the problem. The rule of thumb is that, for the level in the config file, all messages are logged at that level, and below. For example if log4net was told to log at the WARN level, all messages at the WARN, ERROR and FATAL levels will be logged.

To alter the logging level in the config file, change the root logger as follows

<root>
  <level value="WARN" />
  <appender-ref ref="TextFileAppender" />
</root>

Now that WARN is being used, run the test project again and this time the INFO message is not written to the LoggingDemo.log file. Note that it is also possible to set the logging level to ALL and NONE in addition to the specific levels mentioned earlier.

That’s it for now. In part two another appender will be added and I’ll also describe how to customise the format of the log messages.

Technorati tags:

Tags: ,

One Response to “Add logging to your application using log4net”

  1. episerver says:

    episerver…

    [...]Add logging to your application using log4net – Coding Cockerel[...]…

Leave a Reply