|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: You will need to follow the steps in Setting Up Your Development Environment before the project will build. Contents
IntroductionNote: This article is a major re-working of my earlier Getting started with the Logging Application Block article. Whereas that article used Microsoft's Enterprise Instrumentation Framework and the stand-alone Logging Application Block, this article deals with the Logging and Instrumentation Application Block supplied as part of the Enterprise Library. Have you ever encountered a system where the logging is a twisted pile of spaghetti? One where it seems to save trace messages to five different files? Or it requires seven different flags in the registry to control its output? All too often, logging is added to a system in an ad-hoc, as the need arises, manner. When this approach is applied to a large system, with many sub-systems and layers, it can lead to numerous “home grown” logging mechanisms being implemented; each implementation having its own configuration peculiarities and probably logging in different ways (e.g., one subsystem to the Windows Event Log, one to a file in the root directory, one to a database etc.). This article will introduce you to the Logging and Instrumentation Application Block (a part of the Microsoft / Avanade Enterprise Library) and show how it could bring some consistency to an application’s logging. This article is for those who have never encountered the Logging and Instrumentation Application Block, those who are looking to evaluate it, and those who have looked at it and thought it seemed like too much trouble. I will provide an overview of what features the Logging and Instrumentation Application Block provides, followed by a description of how to get the basics working in your environment. The article will not explore too deeply the additional features the new Logging Application and Instrumentation Block provides over the Microsoft Enterprise Instrumentation Framework (EIF) and the original stand-alone Logging Application Block. Nor will it explore the other application blocks provided with the Enterprise Library. BackgroundMany applications, and especially large-scale systems, could benefit from a consistent approach to logging. To help, there are a number of logging libraries available to the .NET developer, such as Log4Net and NSpring. In April 2003, Microsoft released the EIF. As part of Microsoft’s Patterns & Practices initiative, the EIF was extended by the original, stand-alone, Logging Application Block. In January 2005, a new set of application blocks were released together as the Enterprise Library. This library combines many of the preceding stand-alone application blocks (and some new ones) providing a consistent, integrated suite of “best practice” software. The Logging and Instrumentation Application Block is part of that library. The Logging and Instrumentation Application Block provides a simple way for your code to log information in a consistent manner across your managed application. Powerful configuration files allow the filtering, routing and formatting of those “Log Entries” to be determined at run time (rather than at compile time). Log Entries can be generated as discrete events or as part of a traced process. Some of the major improvements over the original stand-alone Logging Application Block are:
When I first looked at the original Logging Application Block, I nearly dismissed it as too much effort. I’m glad I persisted. Due to its automated setup and simplified configuration, the Logging and Instrumentation Application Block is far simpler to start working with and use in a real life project. The BasicsThe Logging and Instrumentation Application Block makes use of four basic concepts to provide a logging framework: Log Entries, Tracers, Sinks and Formatters. Log EntriesA Logger.Write("Hello World");
It is as simple as that. OK, you do have to put in some The above code implicitly creates a
Another overload takes a Additional, context specific information can be added to a TracersWhereas a using (new Tracer("Create New Customer"))
{
Logger.Write("Hello World again");
}
When a All Log Entries written between the
using (new Tracer("Outer most trace", "Outer"))
{
using (new Tracer("A nested trace"))
{
Logger.Write("Hello World inside");
}
using (new Tracer("Another nested trace", "Inner"))
{
Logger.Write("Hello World inside again");
}
}
A number of static methods on the Log SinksWhen a
You can always write your own Custom Log Sink as well. FormattersTo persist a The The message {message} was logged at {timestamp}
would result in an entry in the Log Sink such as: The message Hello World was logged at 08/02/2005 18:08:56
This templated approach means Log Entries can be made user friendly and allows sensitive information to be hidden. The template is read from the configuration files, so can easily be changed. Linking the Basics TogetherHopefully, the section above gives you an insight into the features provided by the Logging and Instrumentation Application Block. What that section doesn’t describe is how There are two more concepts to understand: Categories and Destinations. These are not defined at compile time, but at run time, when the Logging and Instrumentation Application Block reads the configuration files. Therefore, if you need to change how a CategoriesLog Entries can be grouped together into Categories. Each Category can be independently configured to route and format Log Entries in a particular way. Categories can also be used to filter Log Entries, allowing certain Categories to be ignored. A Logger.Write("Hello World once more", "My Category");
LogEntry logEntry = new LogEntry();
logEntry.Category = "My Other Category";
logEntry.Message = "Hello World once more again";
Logger.Write(logEntry);
When a using (new Tracer("My Trace Category"))
{
Logger.Write("Hello World another time");
}
If a DestinationsA Destination is used to determine to which Log Sink a Like Categories, Destinations are defined in your application's configuration files. For each Category, you can specify zero or more Destinations. This means all the Log Entries in a particular Category can be sent to no Log Sinks, one Log Sink or simultaneously to several Log Sinks. Setting Up Your Development EnvironmentFirst off, your system must at least meet the following requirements:
Here are the steps I followed to create a development environment:
All in all, this is a far simpler setup than the previous, stand-alone, Logging Application Block! Instrumenting an ApplicationPerhaps the best way to get to grips with the Logging and Instrumentation Application Block is to try it. The download for this article contains the code for a sample Windows Forms application (LoggingBlockInvestigator.exe) that should allow you to experiment. You may need to delete and re-add its reference to the various Writing Log EntriesThe LoggingBlockInvestigator.exe application writes two Log Entries in the LogEntry logEntry = new LogEntry();
logEntry.Message = "Starting up the application";
Logger.Write(logEntry);
Application.Run(new MainForm());
Logger.Write("Shutting down the application");
This code shows two techniques for writing Log Entries with the Default Category. The first technique explicitly creates a If you build and run the LoggingBlockInvestigator.exe application, then close it down, you will find two new entries in your Windows Event Log, in the Application section. If you look at the details, you will see a list of each of the Log Entries' properties. Specifying a CategoryBy default, all Log Entries are marked with the Default Category. For instance, the Windows Event Log details for the two Log Entries created above indicate their Category is “General.” The code in the sample application for the “Log From My Category” button handler uses an explicit Category instead: private void LogFromMyCategory_Click(object sender, System.EventArgs e)
{
Logger.Write("Written using My Category", "My Category");
}
Run the sample application and press the “Log From My Category” button, then look in the Windows Event Log. Under the System Log, you will find an entry with a source of "Logging Investigator". Looking at the details will show that the Category is set to "My Category". This Category has a second Destination configured which specifies that Log Entries are also written to a flat file C:\Trace.Log. If you open that file, you will find it contains the same Log Entry except formatted differently, as the second Destination is set to use a different Formatter. The code above uses a private void LogWithTracer_Click(object sender, System.EventArgs e)
{
using (new Tracer("My Trace Category", "My Outer Trace"))
{
Logger.Write("My first entry");
using (new Tracer("My Trace Category", "My Nested Trace"))
{
Logger.Write("My second entry [Root = " + Tracer.RootActivityId + "]");
}
}
}
If you press the “Log With Tracer” button, the following Log Entries are saved into the Application area of the Windows Event Log:
Specifying a PriorityWhen a If you press the Log At Priority 10 button, the following code is executed: private void LogAtPriority10_Click(object sender, System.EventArgs e)
{
Logger.Write("Written at priority 2", "General", 2);
Logger.Write("Written at priority 10", "General", 10);
}
This code actually tries to write two Log Entries. However, if you look in the Windows Event Log, you will find the first one has been filtered out. This is because the configuration files for the LoggingBlockInvestigator.exe application set a Minimum Priority of 5. Creating a Custom Log SinkAs well as using the provided Log Sinks, you can create your own. For instance, you may wish to send Log Entries by SMS or some proprietary protocol. CustomLogSink.cs in the sample application shows how simple this is. The class is derived from Note: The help supplied with the Enterprise library contains a “Walkthrough: Creating a Custom Sink” section. As of 9 February 2005, this is incorrect. Adding Context Specific InformationYou can add additional information to a private void LogWithContextInformation_Click(object sender, System.EventArgs e)
{
IDictionary contextInfo = new Hashtable();
contextInfo.Add("Additional Info", "Some information I wanted logged");
DebugInformationProvider provider = new DebugInformationProvider();
provider.PopulateDictionary(contextInfo);
LogEntry logEntry = new LogEntry();
logEntry.Message = "Logged with context specific information";
logEntry.ExtendedProperties = contextInfo;
Logger.Write(logEntry);
}
If you press the “Log With Context Information” button, a new entry is added to the Windows Event Log. If you look in its details, you will see the Extended Properties contain both the “Additional Info” property and a “Stack Trace” property. ConfigurationThe last few sections have introduced the code that you can add to your application to start logging through the Logging and Instrumentation Application Block. There is one more very important task... configuration. Without configuration, your Log Entries will never reach a Log Sink! One of the major enhancements that comes with the Enterprise Library is the Enterprise Library Configuration Console. This can be found on your Start menu under Program Files > Microsoft patterns & practices > Enterprise Library. With the console, you can use a fairly user friendly GUI to edit the various configuration files. To open the configuration files for the LoggingBlockInvestigator.exe application:
This should populate the console as below:
In the tree control on the left hand side, you will see all the configuration settings required to get the LoggingBlockInvestigator.exe application working correctly. Here is a quick run down of the highlights (click on each node to see its properties):
Note 1: The console allows you to search for a Custom Log Sink type by loading an assembly. However, it appears that it doesn't use a separate AppDomain to do this, therefore, once your assembly is loaded, it is never unloaded until the console is shut down. This prevents you searching for a type in an assembly, adding a new type to that assembly, and then looking for this new type. Obscure I know, but it caught me out! Note 2: Once an Adding Logging To Your ApplicationIn order to start using the Logging and Instrumentation Application Block in your own application, there are a few simple steps to follow: Create the configuration filesIn the Enterprise Library Configuration Console, do the following:
Your project directory will now contain two new files: loggingConfiguration.config and loggingDistributorConfiguration.config. These should be put under source control. Note: Tracing is disabled by default. To enable tracing, highlight Client Settings and change Set your project to copy the new configuration filesAdd the loggingConfiguration.config and loggingDistributorConfiguration.config files to your project. For a Windows application, you can ensure these files are always copied to your project's output directory, by adding the following to its “Post-build Event Command Line” (to do this, edit your project's settings and navigate to Common Properties > Build Events): copy "$(ProjectDir)loggingConfiguration.config" "$(TargetDir)"
copy "$(ProjectDir)loggingDistributorConfiguration.config" "$(TargetDir)"
Add a reference to the Logging and Instrumentation Application BlockIn Visual Studio, highlight your project and select Project > Add Reference. On the .NET tab, use “Browse...” to locate the Microsoft.Practices.EnterpriseLibrary.Logging.dll. Where to go from HereBy no means have I covered all the features of the Logging and Instrumentation Application Block. So there is plenty more for you to find for yourself. A good place to start is from GotDotNet. By participating in this workspace, you could influence the future direction of the block. You may also find patches, news about future updates, and contributions from other developers... you might even contribute yourself! ConclusionHopefully, this article provides a good introduction to the benefits and features of the Logging and Instrumentation Application Block. If implemented consistently throughout a system, it should provide a robust and powerful tool for both debugging and monitoring. The information given in this article should allow you to start incorporating the block into your code. At the very least, I hope the article has highlighted the benefits of thinking about logging early in a project, and choosing a consistent approach (whether that is with Log4Net, NSpring, the EIF, the Logging and Instrumentation Application Block, Revision History25 Feb 2005:
28 Sep 2005:
| ||||||||||||||||||||