Writing trace data to your beloved .svclog files in Windows Azure (aka ‘XmlWriterTraceListener in the cloud’)

Tracing is probably one of the most discussed topics in the Windows Azure world. Not because it is freaking cool – but because it can be very tedious and partly massively counter-intuitive.

One way of doing tracing is to use System.Diagnostics features like traces sources and trace listeners. This has been in place since .NET 2.0. Since .NET 3.0 and the rise of WCF (Windows Communication Foundation) there was also extensive usage of the XmlWriterTraceListener. We can see numberless occurrences of the typical .svclog file extension in many .NET projects around the world. And we can view these files with the SvcTraceViewer.exe tool from the Windows SDK.

All nice and well. But what about Windows Azure?
In Windows Azure there is a default trace listener called Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener from the Microsoft.WindowsAzure.Diagnostics assembly.

If you use this guy and want to trace data via trace sources, your data will be stored in Windows Azure Storage tables. Take some time to play around with it and find out that the data in there is close to useless and surely not very consumer-friendly (i.e. try to search for some particular text or error message. Horror).

So, taking these two facts I thought it would be helpful to have a custom trace listener which I can configure just through my config file which uses Azure local storage to store .svclog files. From there on I am using scheduled transfers (which I demonstrated here) to move the .svclog files (which are now custom error logs for Windows Azure) to Azure blob storage. From there I can just open them up with the tool of my choice.

Here is the simplified code:

using System.Configuration;
using System.Diagnostics;
using System.IO;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace Thinktecture.Diagnostics.Azure
{
    public class LocalStorageXmlWriterTraceListener : XmlWriterTraceListener
    {        
        public LocalStorageXmlWriterTraceListener(string initializeData)
            : base(GetFileName(initializeData))
        {
        }

        public LocalStorageXmlWriterTraceListener(string initializeData, string name)
            : base(GetFileName(initializeData), name)
        {
        }

        private static string GetFileName(string initializationData)
        {
            try
            {
                var localResourceItems = initializationData.Split('\\');
                var localResourceFolder = localResourceItems[0];
                var localResourceFile = localResourceItems[1];

                var localResource = RoleEnvironment.GetLocalResource(localResourceFolder);

                var fileName = Path.Combine(localResource.RootPath, localResourceFile);

                return fileName;
            }
            catch
            {
                throw new ConfigurationErrorsException("No valid Windows Azure local 
resource name found in configuration."); } } } }


In my Azure role (a worker in this particular case, but it also works with a web role) I configure the trace listener like this:

<configuration>
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add type="Thinktecture.Diagnostics.Azure.LocalStorageXmlWriterTraceListener, 
               AzureXmlWriterTraceListener, Version=1.0.0.0,
               Culture=neutral, PublicKeyToken=null"
             name="AzureDiagnostics"
             initializeData="TraceFiles\worker_trace.svclog" />
      </listeners>
    </trace>
    </system.diagnostics>
</configuration>


After scheduling the transfer of my log files folder I can use a tool like Cerebrata’s Cloud Storage Studio to look at my configured blob container (named traces)– and I can see my .svclog file.

image


Double-clicking on the file in blob storage opens it up in Service Trace Viewer. From here on it is all the good ole’ tracing file inspection experience Winking smile

image


Note: as you can see the Service Trace Viewer tool is not just for WCF – but you knew that before!

 

UPDATE: this does not properly work with Azure SDK 1.3 and Full IIS due to permission issues – there is more information in the SDK release notes. Very unfortunate Sad smile


Hope this helps.