Monday, September 23, 2013

Semantic Logging Application Block In-Proc Usage

Semantic Logging Application Block provides various types of sinks. They include Console, File based, SQL Server and Windows Azure Table based sinks. We have been discussing how we can use these sinks out-proc. In this post we will be trying to focus how we can use these sinks in-proc i.e. in the same process where the ETW events are generated from. This is specially useful for scenarios where it is not feasible for running Semantic Logging Service as a separate process. I think the most common use would be desktop applications.

Let's create a sample console application SLABInProcApp targeting .net framework 4.5.



Since we would be using the sinks in process. We need to use the necessary nuget packages. As we know FlatFile, RollingFlatFile and Console sinks are directly available in EnterpriseLibrary.SemanticLogging package. The SQL Server and Windows Azure Table sinks are available in EnterpriseLibrary.SemanticLogging.Database and EnterpriseLibrary.SemanticLogging.WindowsAzure packages respectively. Since these packages have a dependency on EnterpriseLibrary.SemanticLogging package, installing these two packages should take care of all the necessary dependencies. These are the packages and their dependencies as shows in Package Visualizer.



And this is how the packages.config should look like for the project.

Now let us introduce our custom EventSource we have been using in these posts. As we have been seeing, it must inherit EventSource type available in System.Diagnostic.Tracing namespace. We can also introduce the necessary types for keywords, tasks. Here we have two logging methods with Event Ids set as 1 and 2.


IObservable<EventEntry> Implementation
SLAB provides ObservableEventListener. This is a specialized EventListener available (.net framework 4.5). As its name suggests, this is an observable type implementing IObservable<EventEntry>. Now SLAB provides various extension method to hook this observable type to the available sinks. In order to keep the world simple, for a given sink type X, the available extension is named as LogToX().



Here we seem to be interested in pushing the logs to Console, SQL Server and Windows Azure table. So we would be needing ConsoleSink, SqlDatabaseSink and WindowsAzureTableSink. These are provided through ConsoleLog, SqlDatabaseLog and WindowsAzureTableLog types respectively through their corresponding LogToX() methods. The extension methods for logging to SQL Server and Windows Azure Table are made available through installing their respective nuget packages.


There is some pre-requisites before we can push data to SqlServer and Windows Azure table here for this example. We need to create database (including the required objects). We also need to make sure that Storage Emulator is running on the machine running this application. This is only required for development. For the production application we can provide the necessary connection details. We have discussed the pre-requisites for SQL Server and Windows Azure table here.

And That's it! Ain't that simple!!!

Now we can just run the application. Since we have subscribed to the ConsoleSink through ConsoleLog.LogToConsole() extension method for IObservable<EventEntry> type, we should be seeing the following on the console.



Subscribing to WindowsAzureTableSink should push the following in the development table storage.



And finally we should be able to see the following data in Traces table in the SQL Server database used here:



Simplifying it Further
We can simplify the code even further. We don't need to instantiate ObservableEventListener ourselves. XLog types also provide the necessary CreateListener() methods. In addition to returning a new instance of ObservableEventListener, they also hook up the EventListener instance returned to the respective source sink.


Event Listeners and Application Life Cycles
Please note that this is a very simple example where you see these subscriptions and logging in the same methods. This would not be the same in the real-life application. You can consider this like Trace Listeners, they are added in the beginning of application life cycle. In the same way, EventListener subscriptions can also be done at the similar stage. They would be more suitable for application seams (Mark Seemann).

There are still some limitations about implementing interface type by the EventSource.

Subscribing Custom IObserver<EventEntry>
Since ObservableEventListener implements IObservable<EventEntry>, we can subscribe any IObserver<EventEntry> with this. Let's implement a sample IObserver<EventEntry> implementation.

We can use the CustomObserver to subscribe to the ObservableEventListener now. This should be using OnNext() method for any new event from the listener.


Download Code

11 comments:

Oz BobWa said...

SLAB now needs all attributes to be set of flush doesn't occur and messages don't make it.

eventListener.LogToWindowsAzureTable(
"Development",
"UseDevelopmentStorage=true;",
"SLAB",
new TimeSpan(0,0,10),
false,
new TimeSpan(0,5,0),
Buffering.DefaultMaxBufferSize);

https://slab.codeplex.com/wikipage?title=SLAB1.1ReleaseNotes

Oz BobWa said...

Thx Shujaat. Great example.
When extending this I found some general issues:
1. When adding new custom EventKeywords, there is no warning. BUT EVERY NEW ENTRY MUST BE ^2. I.E. 1,2,4,8,16,32 ...
2. If you put settings in a config file, like LogLevel, and you wish to change it at run time, you have to implement a custom file watcher. (e.g. in the sample code here by Mike Kelly http://msdn.microsoft.com/en-au/magazine/0295e2a6-ce49-4483-9522-052d8354b02c)
3. new nuget sources exist so it's important to add oDatav4, then WindowsAzure Config, then SemanticLogging.
Keep up the good work.

ashuthinks said...

Getting this error while using Azure table storage what to do?:

An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in msshrtmi.dll

Additional information: External component has thrown an exception.

Muhammad Shujaat Siddiqi said...

Hi ashuthinks, can you share your code?

ashuthinks said...

I have used this code for AZURE account which gives me that error .


// Subscription with Windows Azure Table Service
listener.LogToWindowsAzureTable("MyEvent",
RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));

ashuthinks said...

Hi Now It is able to create Table on Dev :)

Restarted machine nothing else but uable to work with A=ConnectionString.

unable to create table on Azure .
using code
listener.LogToWindowsAzureTable("CustomerSvc",
RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));

getting error :
Getting error while create a table on azure
An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in msshrtmi.dll

Additional information: External component has thrown an exception.

Muhammad Shujaat Siddiqi said...

Hi, This might help.
http://blogs.msdn.com/b/siddjain/archive/2010/07/23/writing-a-console-app-that-access-azure-storage.aspx

ashuthinks said...

thanks a lot all working fine now :)
one question can I use semantic logging with Azure WEBSITES ?
if not why not ? it is only a web application which we hosted on cloud , i'm confused please reply.

Muhammad Shujaat Siddiqi said...

I don't think out-proc should be allowed for azure websites. Have you tried in-proc first? I think this should work with asp.net mvc. But certainly you can use it with web role. This might help:
http://www.iconstructions.be/blog/instrument-webrole-with-etw-eventsource-using-windows-azure-diagnostics

ashuthinks said...

I took one solution inside that took one mvc web application and one console application.
In console application I did all SematicLogging code you shown. and add reference of this console project inside mvc application. and hosted that application on cloud.

Muhammad Shujaat Siddiqi said...

So now you can write those logs. You can add a custom in-proc listener and write those logs at the destination of your choice. Azure Website wouldn't provide that. If you had a webrole, this might be a different story.