About Me

Mitch Wheat has been working as a professional programmer since 1984, graduating with a honours degree in Mathematics from Warwick University, UK in 1986. He moved to Perth in 1995, having worked in software houses in London and Rotterdam. He has worked in the areas of mining, electronics, research, defence, financial, GIS, telecommunications, engineering, and information management.
Mitch has worked mainly with Microsoft technologies (since Windows version 3.0) but has also used UNIX. He holds the following Microsoft certifications: MCPD (Web and Windows) using C# and SQL Server MCITP (Admin and Developer). His preferred development environment is C#, .Net Framework and SQL Server. Mitch has worked as an independent consultant for the last 10 years, and is currently involved with helping teams improve their Software Development Life Cycle. His areas of special interest lie in performance tuning

Sunday, April 29, 2007

log4net: .NET Logging Tool

I took a brief look at log4net quite some time ago and have to admit I didn’t look closely enough! log4net is a port of the highly successful java based log4j logging library and is very mature tool. It’s been at the back of my mind to have another look, and my current project provided the opportunity and impetus. Without wanting this to sound like hype, log4net really does provide a one-stop shop for all your logging, tracing and diagnostics in a simple to use package.

It’s very easy to use out of the box, and highly intuitive. It comes with just about every ‘appender’ you could want (an ‘appender’ is a kind of output sink, i.e. a target for your logging messages). You can define the layout of the log messages. It’s extensible, if you require some other type of appender. It comes with the source code. It has excellent documentation. It’s free! If that doesn’t sound like a great deal, well, there’s no satisfying some people!

I’m going to be using and recommending log4net for all new .NET projects I work on.

You can download log4net here. Even though log4net is fully extensible, it is highly likely that it will meet your logging needs straight out of the box.

The excellent documentation contains config-examples for the list of currently supported appenders:

The documentation and tutorials section provide examples of how to configure the various appenders (\examples\net\1.0\Tutorials\ConsoleApp\cs\src, for example).

[Note: OutputDebugString is also worth looking at; it’s a Win32 API call that’s been there since before .NET, and is a nice technique for connecting to live applications and capturing logging on the fly using a separate application to catch debugging messages]

Adding log4net to your VS2005 project

Download log4net from the official site here. Unzip it to create a log4net folder (with the version number appended) containing the binaries, documentation, examples and source code.

Add the log4net assembly to your project

It’s good practice to include third party assemblies under source control as part of a project. That way, performing a get latest on a new PC includes everything.

If your project does not already contain a source-controlled external libs folder for third party assemblies:

Right click on your external libs folder, select “Add Existing Item…” and browse to where you unzipped log4net and choose the release version of log4net.dll (\bin\net\2.0\release\log4net.dll)

Right click on References, select “Add Reference …” and browse to your libs folder and pick the log4net.dll you just added.

Configure log4net: Creating and Specifying the Log4Net Config File

Although it is possible to add your log4net configuration settings to your project’s app.config or web.config file, it is preferable to place them in a separate configuration file. Aside from the obvious benefit of maintainability, it has the added benefit that log4net can place a FileSystemWatcher object on your config file to monitor when it changes and update its settings dynamically.

To use a separate config file, add a file named Log4Net.config to your project and add the following attribute to your AssemblyInfo.cs file:

In the “RollingFileAppender“ defined above, as Phil Haack points out: “Note that the file value (with backslashes escaped) points to ..\Logs\CurrentLog. [In Web Applications] this specifies that log4net will log to a file in a directory named Logs parallel to the webroot. You need to give the ASPNET user write permission to this directory, which is why it is generally a good idea to leave it out of the webroot. Not to mention the potential for an IIS misconfiguration that allows the average Joe to snoop through your logs.”

You will need to add a “using log4net;" statement to each class file. By defining a logger in each class you have the ability to control the logging level on a class by class basis, simply by using the config file.

Once you have instantiated a logger, you can call its logging methods. Each method is named for the logging level. For example:

// In ascending order of severity (descending level of verbosity)

log.Debug("This is a DEBUG level message. The most VERBOSE level.");

log.Info("Extended information, with higher importance than the Debug call");

log.Warn("An unexpected but recoverable situation occurred");

log.Error("An unexpected error occurred, an exception was thrown, or is about to be thrown", ex);

log.Fatal("Meltdown!", ex);

Whether or not a message shows up in your logs depends on how you have configured your appenders and the logging level you have set. If you want to avoid the overhead of string construction and a call to a logging method, you can first test to see if the appropriate level is active:

// If you are concerned about performance, test the appropriate

// log level enabled property (one for each of the log level methods)

if (log.IsInfoEnabled)

log.Info("Performance sensitive Info message");

The format of the logged output can be adjusted in the config file. See the log4net documentation that came in the zipped download (\doc\release\sdk\log4net.Layout.PatternLayout.html).

For web applications, add the following line to the Application_Error method in the Global.asax.cs file:

Log4net also has a mechanism called NDC (which stands for Nested Dynamic Context) where you can add contextual information to the log, allowing you to mark log entries as coming from a certain user or having a specific context. These can be nested in a push/pop stack fashion. For example:

// Push a message on to the Nested Diagnostic Context stack

using(log4net.NDC.Push(this.User.Name))

{

log.Debug("log entry will be tagged with the current user's name");

}

// The NDC message is popped off the stack at the end of the using {} block

The context is added to log messages where the pattern layout contains “[%ndc]”.

Resources / References

If you run into permissions problems configuring logging for ASP.NET, check out Phil Haack’s post on configuring log4net for Web Applications here. His quick and dirty guide is also worth reading.

There is also a very useful log4net dashboard / viewer tool called l4ndash.