Monday 22 September 2008

Microsoft Enterprise Library #1 – Logging Application Block

This all started as a means to evaluate different logging techniques. A colleague of mine found the enterprise library in his searches and referred it to me so I decided it was worth looking into rather than going with my gut instinct and using Log4Net and Spring.Net. After my initial investigation into the logging application block I found a few things that I took for granted that Log4Net does out of the box (I’ll cover these below) but other than that it was a powerful logging engine that was far more easy to setup and manage changes through a graphical user interface. More importantly the enterprise library seemed to offer integration of logging with other important areas of the application that we are also currently evaluating solutions for, like exception handling, validation and caching. This blog entry is the first in several designed to evaluate the use of the application blocks included in the Microsoft Enterprise Library 4.0.

Step 1 - Download and Install the Enterprise Library 4.0

You can find the Library Installer here. I used the default settings when installing and had no problems with that. You will need to note the installation directory.

Step 2 - Setting up a Logging Block

First you need a project. I’ve created a console application and called it ApplicationBlocksTechDemo. Once you’ve got your project created you’ll need to add all the references and do a quick test to see if the block is working. I don’t want to re-invent the wheel with this post so I suggest if you don’t know how to setup the block then you should use this tutorial from Vikas Goyal. It’s very simple and straight forward and will give you the starting point for this guide. It is worth mentioning that in Enterprise Library 4.0 the Microsoft.Practices.ObjectBuilder seems to be called Microsoft.Practices.ObjectBuilder2. You will also need to browse for the DLL files directly; they are in the bin directory of your Enterprise Library installation directory. Add the references to your project for:

  • Microsoft.Practices.EnterpriseLibrary.Common
  • Microsoft.Practices.EnterpriseLibrary.Logging
  • Microsoft.Practices.ObjectBuilder2

Once these are added you’ll be able log the most basic of information, by default it will log to the event log. If you’re building an enterprise application you’ll almost certainly want to capture logs to many different locations so this tutorial will show you how to do that. At this point you should also add an App.config file to your project. Your project solution should look something like this now.

 

 

Step 2 - Adding the Logging Application Block In the bin directory of the Enterprise Library install directory you will find the EngLibConfig.exe file. Run the file and open the Config file for your solution that you just added. Right click the project and add a new logging application block, the default settings will be added. Save your changes and go back to your project. Your App.config file will ask to be re-loaded, when you choose yes you’ll be able to see the configuration that has been added. In my opinion this is part of the power of the Logging Application Block, you don’t need to edit the XML directly, so I close my logging Config region in my App.config.

Step 3 Adding My Requirements Before adding my requirements into the block, I need to understand the application block sections. These are:

  1. Filters – You can filter out log messages before they reach the distributor.
  2. Category Sources – These are the types of log messages you are capturing, with each one specifying the trace listener it will log to.
  3. Special Sources – Another way to capture the messages and send them to trace listeners.
  4. Trace Listeners – Output forms for the logs.
  5. Formatters – The format of the output.
My requirements are simple, I want to:
  1. Send errors to the event log
  2. Send warnings to an email address
  3. Log all messages to a log file using a simple one line format.

Step 4 - The Event Log

First remove the event log listener from the General category. Next Right click the category sources and add a new category, I called mine Error. Right click the category once it’s created and create a new trace listener reference. Choose the Formatted EventLog TraceListener (added by default) and save the Config file. Your Logging Application Block should look something like this. In your application add some code to create an error, it’s very simple:

 
 
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.ObjectBuilder2;
 
namespace ApplicationBlocksTechDemo
{
class Program
{
 static void Main(string[] args)
 {
  Console.WriteLine("Logging tool starting");
  Logger.Write("Error Message", "Error", 1, 1,
   System.Diagnostics.TraceEventType.Error);
  Console.ReadLine();
 }
}
}
 

When you check your application event log you’ll see an error after running your application now.

Step 5 - Send Warnings to an Email Address

Your requirements will probably be different to mine as mine are setup to show off some of the features that I like with the Enterprise Library, but if you want to email warnings to someone this is how it’s done. We don’t have a warning category yet, so add one in. I called mine Warning. We now need to create a Trace Listener to allow us to send warnings to an email address. Right click the Trace Listeners and add a new Email Trace Listener. Set all the parameters, they’re pretty straight forward. Right click your Warning category and add a new trace listener reference to your email trace listener.

 

Add in a line of code to log a Warning

Logger.Write("Warning Message", "Warning", 1, 1,
System.Diagnostics.TraceEventType.Warning);

and run your program. Warnings are now sent by email to the user specified.

Step 6 - Logging to a File

Lastly we want to log everything to a file, even our errors and warnings we’ve handled already. Also, we only want each log entry to take up one line so that we can review the information a little more easily. We’ll comma separate the fields so we can open up the log in Excel for reviewing if required. We also don’t want our log file growing out of proportion so that it gets to a size that is impossible to read. The first thing we need to do is add a new formatter. Right click the formatters and choose to add a new one, I called mine LogFileCSV Formatter. You can edit the template once it’s added, mine looks like this:

{category},{timestamp},{priority},{machine},{message}

Now we need a new Trace Listener, add a new one of type “Rolling Flat File Trace Listener”. This will create a new file based on the rules you choose at the intervals you set. The options are pretty straight forward, I chose mine to create a new file every 1000Kbs and to move the old one to a timestamp pattern of yyyy-MM-dd. Choose your new formatter as the formatter option and make sure you remove the header and footer if you want it to show only one line. Finally under Special Sources add the new trace listener to the All Events option, this will log every event into your log file.

Finished

Looking back over my project, I’ve added in the framework to complete all my requirements without writing a single line of code. My requirements were incredibly basic, but there is no reason why it should take more than this to create your logging framework.

Log4Net Comparison

I’ve always used Log4Net in the past, and I will do so again for small projects that don’t require an enterprise level solution. But why would I use the Logging Application Block over Log4Net for an enterprise level solution. Here are some reasons. 1. Speed I setup a test where two different applications would log 10 000 messages to a file and 10 000 messages to the event log in exactly the same format. I tried to make the code as efficient as possible in both cases. The Logging Application Block completed this task in a little over one second, the Log4Net test took a little over 8 seconds. Most of this was accessing the event log in both cases, logging to file was far quicker as you would expect. 2. No XML editing Using the Logging Application Block you can utilize the graphical interface and are not required to edit the XML Config at all. For small projects dealing with XML is easy as your logging isn’t required to do much, but the more complex your requirements become the harder it is to sift through the XML. The Logging Application block excels here. Why would you use Log4Net over the Logging Application Block? 1. Smaller Footprint Log4Net is certainly smaller. If this is an issue for you then perhaps Log4Net is the better option. 2. Tracing back to source If you wish to trace back to the source (log the class or function that threw the exception) then Log4Net handles this natively. You would have to implement this yourself in the Logging Application Block (though admittedly it is not very difficult and the time you would have to spend writing XML for Log4Net would easily cover it).

Final Notes

No matter which logging framework you choose I highly recommend that you abstract it from the rest of your code and hide the implementation so that you can switch without any trouble should the need arise. The Logging Application Block is remarkably simple to implement and even if it is a sledge hammer I wouldn’t want to break up a block of concrete with a chisel. Interoperability with the other Application Blocks in the Enterprise Library will be something that I will investigate very shortly, this promises to be the main reason I wish to use the Logging Application Block.

8 comments:

jbarber said...

I have been looking for a good demo of the Enterprise Library 4 configuration of the Logging. Everything I found was older version, which are the same. Thanks for the nice post

Anonymous said...

I completely agree with your point of abstracting the logging framework. This is very important if your libs are to be used in multiple applications. I use SpringTail which is a simple logging framework abstraction located on codeplex. http://www.codeplex.com/SpringTail

i3Desi said...

Thanks for the post. I was looking how to use Logging Application block to send emails and your examples were perfect. Also, Do you know if we can use Logging Application Block to log unhandled exceptions in the applications?

Odd said...

Yes and no. You can use the Exception Application Block to handle your exceptions, but you have to pass them to it yourself. If youc atch your exceptions at the highest level of your application to effectively catch unhandled exceptions and then pass them to the exception block, you can then pass them down to the logging block for logging.

DotNetDvlpr said...

You should definitely take a look at The Object Guy's Logging Framework.

Small footprint. Easy to implement. Easy to extend. Intuitive API.

John Michel said...

Let me second the comment about The Object Guy's Logging Framework. It fits the bill for almost any project.

Zian said...

The blog post should indicate that the Enterprise Library classes are listed by name in the Add References dialog so any searches for "Microsoft.Practices.[fill-in-the-blank" will turn up empty inside Visual Studio.

Example:
Microsoft.Practices.EnterpriseLibrary.Common is named "Enterprise Library Shared Library".

Anonymous said...

If you have 2 or more trace listeners in Logging application block which are for the same category and events, and first of them fail, the rest will not log anything. In log4net the rest after failed will log.