Pages

Advertisement

Thursday, July 12, 2007

Enterprise Library 2.0: The Logging Application Block

The Enterprise Library 2.0 (EL2) is the second major release of the robust frameworks released by the Microsoft Patterns and Practices team. At the time this article was written, EL2 is a "Community Technology Preview (CTP)", so features are subject to change.

EL2 consists of six main application blocks: Logging and Instrumentation, Caching, Data Access, Cryptography, Security, and Exception Handling. Along with the application blocks, EL2 is built on a number of core components, which can be consumed by the general public, but are primarily used internally by the application blocks. These core components can be classified as: Configuration, Instrumentation, and the ObjectBuilder. In the previous version of the Enterprise Library, Configuration was the seventh application block. In EL2, the functionality has been replaced by the .NET 2.0 System.Configuration namespace and has been moved into the core architecture.

Although EL2 will ship with a series of excellent "QuickStart" applications, these quick starts don't always explore all the features and have been known to lack sufficient documentation. In addition, logging (for example, debug, trace, error, and so on) is far from standardized in most organizations, making it important to have as much content on the subject as possible. For example, a number of organizations have multiple ASP.NET applications that all log information differently.

The Logging Application Block and EL2 are not turnkey solutions; however, they provide people with a mechanism to create a unified logging strategy. The goal of this article is to investigate some basic logging scenarios, explain and define some of the required terminology, and help you take those first steps to more efficient logging.

Major Changes in the Logging Block

There are too many changes in the Logging Application Block between the Enterprise Library (EL1) and EL2 to cover in this short article, but I want to highlight some of the major changes in the Logging Application Block.

First, the previous version of the Logging Application Block (in fact, most of the original version of EL1) was based on Avanade's ACA.NET framework. The word "based" is used very loosely, because in many cases the only change between ACA.NET and EL1 is the namespace. Although ACA.NET and EL1 are both great pieces of code, EL2 has simplified the logging strategy and has aligned better with the .NET 2.0 framework.

For example, Trace Listeners (A.K.A. LogSinks in previous versions) were custom code. In the new version, they derive from the very established TraceListener class in the System.Diagnostics namespace. Additionally, the frequently used LogEntry class now supports multiple categories. This may not sound like a big deal; however, this feature allows you to create a more standardized logging policy across applications. Multiple categories provide you with the ability to log different event types (for example, debug, audit, and so forth) specified in different application tiers (as in UI, Business, and the like) to different locations (for example, database, text, and so on), a big improvement from previous versions.

Along with the code improvements, the new logging application block has also simplified the "strategy" aspect. This was done by eliminating the concept of "distribution strategies" that were tedious and complicated in EL1. Instead, EL2 utilizes a far superior architecture of linking TraceListener classes together, which further aligns its design with the .NET 2.0 frameworks.

Logging Block Definitions

Before jumping into some examples of working with the EL2 Logging Application Block, you should first understand some terminology. The following is a summary of some of the definitions that you will need to know before using the Logging Application Block:

Jumping into Logging...

The best way to understand EL2's logging features is to jump right into a few examples. Let me set the stage a bit. The first example is very simple and its purpose is to get the wheels spinning; it demonstrates a simple database logging scenario. The second example extends the logging application block. Both examples demonstrate the extensibility points in EL2.

I assume you have the EL2 already. If not, you can obtain it from here. If you are using the December CTP, it is highly recommended that you build the EL2 configuration console prior to working with the examples in this article. The configuration console allows you to manipulate the configuration files through a simple GUI.

Along with the configuration console, the following examples require that you have Visual Studio 2005 and a MS SQL Server database installed. I used SQL 2005 Express, but I believe that, with some minor tweaks, any version should work.

EL2 Database Logging

To start the first example showing a simple database logging, navigate to the install directory of the Enterprise Library 2.0 and locate the "..\Src\Logging\TraceListeners\Database\Scripts\" directory. In this directory, you should find a batch file, "CreateLoggingDb.cmd," which will need to be executed (first ensure that SQL Server is running). This batch file executes the SQL script, which is located in the same directory and called LoggingDatabase.sql, creating the logging database natively used by EL2. The native logging database used in this example, "Logging," is very full-featured, but you do also have the choice to design and create your own database for use with the logging block.

Continue by creating a new C# Windows application in Visual Studio 2005; for ease of use, for this and all of the examples, Windows forms applications will be used. Add a new application configuration file, and open the Enterprise Library console.

EL2 is heavily driven through meta-data stored in application configuration files. The console creates a visual interpretation of the XML stored in these configuration files and makes it easy to manipulate the data. Navigate to File, Open Application, and select the app.config file that you just created. Another way to do this is to create the app config file in the EL2 console, but both methods have the same result.

The next step is to add a new node to the configuration by right-clicking (or navigating to "Action") in the console on the top-level node, and selecting "Logging Application Block."

Figure 1: The EL2 console is a straightforward GUI that reduces the time it takes to generate the required configuration information.

By default, the Logging application block gets configured with the EventLog trace listener enabled for the "General" category, and the "Special Source" category of "Logging Errors & Warnings." The event log is a fine logging store if you have a single server, but in most cases you want something more centralized that you can query against, such as a database.

For this example, you will need to remove all of the event log references by highlighting their nodes and going to "Action, Remove" or by right-clicking on their nodes and selecting "Remove." Add a new "Database Trace Listener" by highlighting the "Trace Listeners" node by right-clicking or going to "Action" again. You should see a new database trace listener and a new reference to the data access application block. The granular details about the data access block will be saved for another time, but do know that a new connection reference (which defaults to "Connection String") has been created. The setting attributes will need to be modified appropriately to reflect your database setup.

The next step is to associate the "Database Trace Listener" with the new database connection reference, and provide it a formatter; in this case, the default text formatter is used.

The final configuration step is to add a new category called "Audit" under "Category Sources" and reference the new "Database Trace Listener."

Rest assured, even though these steps are slightly time consuming, they are far simpler than editing the configuration files by hand. Downloading the example will help make sense of the process.

With the application configuration out of the way, the next step is very simple. Just add a reference in VS 2005 to Microsoft.Practices.EnterpriseLibrary.Logging, add the using statement (Using Microsoft.Practices.EnterpriseLibrary.Logging), and add the following code to a button:

LogEntry le = new LogEntry();
le.Categories.Add("Audit");
le.Message = "Testing our DB Logging";
le.EventId = 1234;
le.Title = "Database Message";
le.Priority = 1;
Logger.Write(le);

Downloads

  • EL2LoggingProject.zip - Download source code - 19 Kb

  •  


    Extending the Logging Application Block

    EL2 and the Logging Application Block are highly extensible frameworks that have many predefined extension points. In this next example, you'll get a closer look at one of the extension points, the Custom Trace Listener, by creating a rolling flat file trace listener.

    Note: The purpose of this next example is to demonstrate the extensibility of the logging application block. The example has not been tested for production use and probably is not the most efficient method for creating a rolling log file.


     


    At this point, it is important that you download the source code so you can follow along with the text. I am not going to present all of the details on the System.Diagnostic.TraceListener class because there is already a ton of information out there on MSDN. I will outline the necessary steps required to create a custom trace listener in the context of the Logging Application Block.

    First, to wire up a custom trace listener and to enable it for use with the Console, you must do two things: inherit from Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.CustomTraceListener class and decorate your new class with the following attribute:

    [ConfigurationElementType(typeof(CustomTraceListenerData))]

    Now, understand that you can manually go through and hack your application configuration files, so technically speaking the attribute is not absolutely necessary, but it is a significant time saver.

    After you create a new class that meets those two requirements, it is as easy as opening the console and configuring your "Custom Trace Listener." This is accomplished the same way you configured the Database Trace Listener with two exceptions. First, you will have to specify the "type" attribute (right pane of the console), which is the location of the assembly with the Custom Trace Listener. Second, for this example you will need to configure the attribute collection, which is a group of name value parameters for use at runtime:


    Figure 2: Use the EL2 console to configure name-value pairs for use by the Custom Trace Listener.

    In this example, you are creating a new attribute called "fileName" and giving it a value of "CustomLog{Date}.txt". The "{Date}" string is used by the custom TraceListener as a token to enable the string as a replacement value. The attribute system is actually not new with EL2; rather, .Attribute is a StringDictionary property that hangs on the System.Diagnostic.TraceListener base class.

    What's new with EL2 is the plumbing code that automatically interprets the information stored in the app.config file. Take a look at the following excerpt from the app.config file. As you can see, the attribute "fileName" has been added to the listener configuration section automatically, and is interpreted natively by EL2.

    <listeners>
    <add fileName="CustomLog{Date}.log" listenerDataType="..."
    name="Custom TraceListener" initializeData="" />
    ...
    </listener>

    The last thing you need to do before writing some code to use this new trace listener is create a new category called "Fatal." Enable the new "Fatal" category with the new Custom Trace Listener. Once you have saved, add some code to test out the new Custom Trace Listener. Rather than logging to a single category (as in the previous example), use one of the new features in the Logging Block by utilizing the two categories created so far, "Audit" and "Fatal":

    LogEntry le = new LogEntry();
    le.Message = "Testing both our Custom Trace Listener and our
    Database Trace Listener";
    le.Categories.Add("Audit");
    le.Categories.Add("Fatal");
    le.EventId = 1234;
    le.Title = "Two Categories";
    le.Priority = 1;
    Logger.Write(le);

    Logger.Write() has 19 overloads, so nearly every way you would want to log a message (in other words, Generics, string parameters, and so forth) is available.

    The Easier, the Better

    This article has only scratched the surface of the new Logging Application block, but I hope that it has gotten some of you thinking about how EL2 can improve your code. The Enterprise Library is a free, reusable, battle-tested set of frameworks that can greatly reduce your time to market or improve your existing code base.

    Related Links

    No comments:

    Post a Comment