Using the block in applications for the in-process scenario
To use the Semantic Logging Application Block in the in-process scenario, after you have created your custom event source within your application and added the code required to raise the events, you must:
- Install the application block assemblies from NuGet. For more details, see Installing the application block assemblies.
- Instantiate an ObservableEventListener object to listen for your custom events, and enable it to receive event messages from your EventSource implementation. For more details, see Creating and enabling event listeners.
- Instantiate an ObservableEventListener object to listen for exception events raised by the application block itself, and enable it to receive event messages from the SemanticLoggingEventSource event source. For more details, see Creating a listener for application block exception events.
- Create any formatters you need to format the event messages. You can only use formatters with certain destinations, such as files. For more details, see Creating and configuring event formatters.
- Create and configure the event sinks that you need to save the event messages to the destinations you are using in your application, and attach them to the listeners. For more details, see Creating and configuring event sinks.
- If you are using the Console sink to write logged events to the console during development and testing, you can add a color mapper to the sink to enhance the output. For more details, see Using a color mapper to enhance Console output.
Installing the application block assemblies
Before you write any code that uses the Semantic Logging Application Block for the in-process scenario, you must install the required assemblies into your project. You can install the block by using the NuGet package manager in Visual Studio. If you intend to write to text log files, a SQL Server database, or Microsoft Azure table storage, you also need to install additional packages.
The following procedure describes how to include the necessary Enterprise Library assemblies and elements in your code.
To install the application block assemblies
In Microsoft Visual Studio, select the project node in Solution Explorer, open the shortcut menu, and choose Manage NuGet Packages.
Choose Online in the left-hand menu and then choose nugget.org. Enter semantic logging application block In the Search Online box.
Select the package Semantic Logging Application Block (the package with the ID EnterpriseLibrary.SemanticLogging) and choose Install.
After the installation is complete, decide if you need to install any additional packages for the specific event sinks that you want to use. You can use the following packages to install event sinks:
- Semantic Logging Application Block – Text file sinks
- Semantic Logging Application Block – SQL Server Sink
- Semantic Logging Application Block – Azure Sink
Note
Additional packages from third parties are available for use with other types of logging destinations. These are not covered in this guide.
After NuGet has finished installing the packages you require, click Close. NuGet has now updated your project with all the necessary assemblies and references that you need to use the Semantic Logging Application Block.
Creating and enabling event listeners
The ObservableEventListener class receives event messages from the EventSource implementation in your application. When you call the EnableEvents method of the ObservableEventListener class, you specify the event source to use and provide a filter for the events the event listener should receive. You can filter based on the severity of the event messages and on keywords. You can enable multiple event sources on the same listener.
Creating an instance of an observable event listener results in shared state. Typically, you create and enable event listeners when the application starts, and disable and dispose them just before the application ends. Depending on the type of application, and how it is deployed, you might create and dispose event listeners in Global.asax for an ASP.NET application, in the Main class of a Console application, or in the constructer and the Dispose method of a class.
The following code sample shows how to instantiate and enable an event listener.
// Create an event listener. Typically done when the application starts.
var listener1 = new ObservableEventListener();
listener1.EnableEvents(MyCompanyEventSource.Log, EventLevel.LogAlways,
MyCompanyEventSource.Keywords.Perf | MyCompanyEventSource.Keywords.Diagnostic);
The EventLevel enumeration is defined in the System.Diagnostics.Tracing namespace. The listener receives all messages that match or are more severe than the value passed to the EnableEvents method. The third (keywords) parameter specifies the event keywords, defined in the EventSource class, for which this event listener should receive events.
The example uses an overload of the EnableEvents method that specifies the custom event source, the level of events to log, and a keyword filter. The following table describes the parameters of the EnableEvents method.
Parameter |
Description |
---|---|
eventSource |
A reference to your custom event source. You typically reference this by using a static Log property. |
level |
A filter based on the severity level. All messages with the matching severity level or lower are logged. The EventLevel enumeration defines the severity levels and includes the special value LogAlways that means that all severity levels are logged. |
matchAnyKeyword |
A bitvector that specifies a filter for log messages based on their keyword values. You can use the special value Keywords.All to match all messages regardless of their keywords. Typically, you define your applications keywords in a nested class in your custom EventSource. |
There are also overloads of the EnableEvents method that take different sets of parameters:
- EnableEvents(eventSource, level**)**
- EnableEvents(eventSource, level**,** matchAnyKeyword**,** arguments**)**
- EnableEvents(eventSourceName, level**)**
- EnableEvents(eventSourceName, level**,** matchAnyKeyword**)**
- EnableEvents(eventSourceName, level**,** matchAnyKeyword**,** arguments**)**
These overloads allow you to enable events without requiring a keyword to be specified, to pass arguments to the event source, and to specify the event source by name as a string instead of using a reference to the object instance.
If you use an overload of the EnableEvents method that does not pass a matchAnyKeyword parameter, any methods defined in the custom event source class that have a keyword filter will fail to execute. Using an overload with the Keywords.All value for the matchAnyKeyword parameter ensures that all the events defined in the event source are sent to the listener. Keywords.All is a constant defined in the Microsoft.Practices.EnterpriseLibrary.SemanticLogging namespace as (EventKeywords)(-1).
The arguments parameter is used to specify an implementation of the IDictionary interface that contains arguments to be passed to the event source. Typically, these arguments are used to manage the behavior of the event source.
The capability to specify an event source by name as a string is used when you want to trace events exposed by an existing event source that you have not created yourself (and, therefore, cannot obtain a reference to). This approach, together with using the arguments parameter, is typically used when correlating and sampling events. For more details, see Correlating events and Sampling and filtering events.
Note
An alternative approach to creating a listener is to use the static methods of the event sinks that automatically create a listener for that sink. For more details, see Creating and configuring event sinks.
Disabling and disposing an event listener
You should dispose of event listeners when you have finished using them to enable them to release any resources and any subscribed sinks. Typically, you dispose of the listeners when the application shuts down, as shown in the following code.
// Dispose an event listener. Typically done when the application ends.
listener.DisableEvents(MyCompanyEventSource.Log);
listener.Dispose();
Sinks that buffer log messages, such as the SQL Database sink and the Azure Table Storage sink, will attempt to flush their buffer when you dispose of the listener and the sink. You can flush the sink by calling the FlushAsync method to ensure that all events received so far have been written to the destination log.
Keep in mind that the Dispose call will block the thread until the events are persisted, but you can specify a timeout when initializing the sink. However, if the configured timeout expires before the flushing completes, the sink will drop any unflushed entries.
For more information about the EnableEvents and DisableEvents methods, see EventListener Class on MSDN.
Creating a listener for application block exception events
The application block may raise events in response to specific operations or exceptions that occur within the block. You should create and enable an event listener for the SemanticLoggingEventSource class to collect these events, as shown in the following code.
// Create an event listener to collect exceptions raised by the block.
// Typically done when the application starts.
var blockEventListener = new ObservableEventListener();
blockEventListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.LogAlways, Keywords.All);
You should attach a suitable event sink to this listener in order to monitor the block itself. For a list of the events that the block may raise, see Error messages generated by the Semantic Logging Application Block.
Creating and configuring event formatters
The Console sink, Flat File sink, and Rolling Flat File sink can use an event formatter to control the format of the output. These formatters have configuration options that you set using parameters of the constructor or by setting properties after you create the formatter. For example, the following code shows how you can create and configure a JSON event formatter to generate indented output.
JsonEventTextFormatter formatter = new JsonEventTextFormatter(EventTextFormatting.Indented);
The following code shows how you can create an XML formatter and set its properties. You can specify the date/time format using an optional constructor parameter or (as shown here) by setting the DateTimeFormat property. The text formatting can be set only in the constructor; it is a read-only property.
XmlEventTextFormatter formatter = new XmlEventTextFormatter(EventTextFormatting.Indented);
formatter.DateTimeFormat = "yyyy-dd-MM";
For more details of the event formatters you can use, and the properties of each one, see Choosing and using text formatters.
Creating and configuring event sinks
Event sinks subscribe to event listeners. Each event sink receives a copy of the messages received by the event listener to which it is subscribes.
The built-in sinks have constructors that enable you to configure the sink as you create it. However, for convenience, an extension method is available for each sink that creates the sink together with a subscription to a listener. These methods accept parameters, which vary depending on the type of sink, and are used set the properties of the sink.
The following code shows an example of creating a Flat File sink, passing in a reference to a previously created formatter, and subscribing to a previously created listener.
listener.LogToFlatFile(@"C:\Logs\SemanticLogging.log", formatter);
The equivalent extension methods for other event sinks include LogToConsole, LogToRollingFlatFile, LogToSqlDatabase, and LogToWindowsAzureTable.
After the listener is created, you enable one or more event sources to listen to, as well as the highest level of event to capture, and any keywords to filter on for each source. The following code shows an example that creates, configures, and enables two sinks, one to write log messages to the console and one to write log messages to a SQL database.
// Initialize the listeners and sinks during application start-up.
var listener1 = new ObservableEventListener();
listener1.LogToConsole();
listener1.EnableEvents(MyCompanyEventSource.Log, EventLevel.LogAlways,
MyCompanyEventSource.Keywords.Perf | MyCompanyEventSource.Keywords.Diagnostic);
// In this example, the SinkSubscription is saved for use later to flush the
// buffer, although this is typically not required for basic scenarios.
var listener2 = new ObservableEventListener();
SinkSubscription<SqlDatabaseSink> subscription =
listener2.LogToSqlDatabase("Demo Semantic Logging Instance", connectionString);
listener2.EnableEvents(MyCompanyEventSource.Log, EventLevel.LogAlways, Keywords.All);
This example uses two listeners because it uses different keyword filters for each one. Notice that is saves a reference to the subscription for the second listener in order to be able to access the listener afterwards. This technique is typically used for tasks such as ensuring the buffer for the sink is flushed to the logging destination before the application closes down.
An alternative approach is to use the static entry points provided by the log classes, as shown in the following code. The advantage of this approach is you need to invoke only a single method rather than creating the listener and then attaching the sink.
// Create the event listener using the static method.
// Typically done when the application starts.
var listener = ConsoleLog.CreateListener();
listener.EnableEvents(MyCompanyEventSource.Log, EventLevel.LogAlways, Keywords.All);
However, the static methods do not give you access to the sink, and therefore you cannot explicitly flush any buffers associated with the sink when you are shutting down the application. Instead, you can use the onCompletedTimeout parameter to the CreateListener method to control how long a listener will wait for the sink to flush itself before disposing the sinks. For more information, see Choosing and using event sinks.
For more details of the event sinks you can use, and the properties of each one, see Choosing and using event sinks.
Using a color mapper to enhance Console output
A color mapper is a simple class that specifies the color to use for different event levels. When using the Console event sink, you can use the DefaultConsoleColorMapper class provided with the block to display the logged event output in different colors depending on the severity of the event.
The following code shows how you create a color mapper instance and specify its use with the Console sink.
var colorMapper = new MyCustomColorMapper();
listener1.LogToConsole(formatter, colorMapper);
listener1.EnableEvents(MyCompanyEventSource.Log, EventLevel.LogAlways, Keywords.All);
By default, the ConsoleSink class uses the colors listed in the following table to display log messages.
Event level |
Color |
---|---|
Critical |
Magenta |
Error |
Red |
Warning |
Yellow |
Verbose |
Cyan |
You can override these colors by implementing the IConsoleColorMapper interface and passing an instance of your class to the LogToConsole extension method or the static CreateListener method of the ConsoleLog class. The following code shows an example of a custom color mapper.
public class MyCustomColorMapper : IConsoleColorMapper
{
public ConsoleColor? Map(
System.Diagnostics.Tracing.EventLevel eventLevel)
{
switch (eventLevel)
{
case EventLevel.Critical:
return ConsoleColor.White;
case EventLevel.Error:
return ConsoleColor.DarkMagenta;
case EventLevel.Warning:
return ConsoleColor.DarkYellow;
case EventLevel.Verbose:
return ConsoleColor.Blue;
default:
return null;
}
}