Another useful application block that is part of the Enterprise Library is the Logging and Instrumentation Application Block. It allows you to log events in your applications to various locations, such as a database, the event log, email, a flat file, etc.
As you can see from the snapshot of the configuration tool below, I created a single location to store all my events – a flat file. It is the MessageLogSink, which stores messages in a file I decided to call message.log.
For testing purposes, I decide to group all my events into 5 categories:
You have to assign one of the categories as default, so I assigned General as default. Each category can be assigned to one of more sinks. Thus you could have events of type Exception not only stored to a text file, but also sent to you via email, placed in the event log, etc. In my case, I just assigned them all to MessageLogSink that saves messages to message.log.
How you organize your categories is fairly important because you not only have the ability to channel categories to one or more different locations, but you also have the ability to filter on categories. For example, when you first start building the application you will probably want to see all events of type Debug. However, when the application gets closer to production or into production, you will probably want to turn off a lot of the Debug messages. You can also filter on Priority as well, so one needs to think out the strategy on how you organize the events and the priority of the events within each category so that you can minimize the logging as the application becomes more mature.
The Logging and Instrumentation Application Block is called within your application using a simple Logger.Write(…) call that has several overloads where you can pass parameters:
The parameters are as such:
These values are all neatly placed in a type of LogEntry that gets distributed (after filtering) to each Sink on a category-by-category basis via the Interface ILogSink.
The formatter you see mentioned above is also configurable per sink and category and just specifies what you want the message to look like and what information you want it to contain.
After I finished creating the configuration files, I created a quick test application in Snippet Compiler as shown below. To stay somewhat consistent on how I use the categories and set priorties, etc., I derived more specific category-based LogEntry classes from LogEntry. This is totally unnecessary as I was just playing:
Here is the output using my template for Text Formatter:
You could also pull off a cleaner and more consistent model by using your own facade on top of Logger to maintain the additional consistency in your applications such as:
You could obviously refactor the code above as necessary, but you get the idea. I am basically trying to create a more intuitive method and consistent manner in which I use the Logging and Instrumentation Application Block so that as I grow from an immature application to a mature application I can filter the amount of information that is written into the log as necessary by Category and Priority.
I have purposely not posted the config files with this example as they are your typical Enterprise Library log files.
Here are other Enterprise Library Application Blocks that I have posted about:
- Configuration Application Block
- Cache and Configuration Application Block
- Data Access Application Block (DAAB)
- Data Access Application Block Revealed – Factory Methods and Reflection
You can download Enterprise Library here.
Don’t forget about the Enterprise Library webcasts.