Logging

When developing an application it’s possible to use debug mode to figure out why something is wrong, but when it’s time to deploy the application something else has to be integrated. To solution to this is logging. Implementing good logging functionality will make the Operations people who have to deploy your application happy as well, because they can integrate it into existing monitoring systems.

Enterprise Library was used to implement a flexible logging solution. Thanks to the Logging and Instrumentation Application Block it’s possible to integrate logging into your code, but decide where to output the log externally from the application. This way it’s possible to log to a flat file, a database, an email address, the event log, a message queue, WMI and custom implementations, without having to change code.

A Logging project was added to start, to provide some helper constants:

[csharp] using System;

namespace MediaService.Logging { public struct Priority { public const Int32 Lowest = 0; public const Int32 Low = 1; public const Int32 Normal = 2; public const Int32 High = 3; public const Int32 Highest = 4; } / Priority /

public struct Category { public const String Player = "Player"; public const String Remoting = "Remoting"; public const String Data = "Data"; public const String SqlServer = "SqlServerData"; } / Category / } / MediaService.Logging / [/csharp]

After this, a reference to the Logging project was added together with a reference to Microsoft.Practices.EnterpriseLibrary.Logging. A reference to the Enterprise Library Configuration Application Block was needed as well.

At this point it was possible to log messages by using the following construct:

[csharp] if (randomSong == null) { Logger.Write("Unable to select a random song.", Category.Player, Priority.High, 1, Severity.Error); } else { Logger.Write(String.Format("Fetched song: {0} (Random).", randomSong.Path), Category.Player, Priority.Low, 1, Severity.Information); } [/csharp]

Similar code had been added throughout the code to provide meaningful feedback. The only thing left was configuring where the log output had to go.

Using the Enterprise Library Configuration tool, an existing App.config was loaded and the Logging and Instrumentation Application Block was added. Under Client Settings, LoggingEnabled was to True.

A new category had to be added, called Player, by right clicking on Categories and selecting New – Category. This is the name that was used in the code to specify which log the output belongs to. It was possible to define multiple categories.

To define where the output had to go to, a new sink was added, called Player Flat File Sink, by right clicking on Sinks and selecting New – Flat File Sink. Player.log was chosen as a filename, without a header.

Formatters are used to define how a single log entry had to look. By default a Text Formatter was provided, which included extensive information. To have an overview log file, a new formatter was added by right clicking Formatters and selecting New – Text Formatter. The template for this Simple Text Formatter was the following:

[code] {severity} [{timestamp}]: {message} [/code]

Finally a new destination was added by right clicking the Player category and selecting New – Destination. This destination was configured to use the Simple Text Formatter together with the Player Flat File Sink.

After this, the loggingconfiguration.config and loggingdistributorconfiguration.config files had to be copied in the Post-build event as well. At this point, the application had implemented a flexible logging strategy, where an administrator could easily decide to turn logging on or off and where the log output had to go to and which template had to be used.