Trace and TraceSource in the Windows Azure DevFabric UI

Windows Azure

The Windows Azure Platform has a rich diagnostics infrastructure to enable logging and performance monitoring in the cloud.

When you run a cloud app locally in the DevFabric you can view diagnostics trace output in the console window that is part of the DevFabric UI. For example, say I have the line

System.Diagnostics.Trace.TraceInformation("Old Trace called at {0}.", DateTime.Now);

That line gives a result like this in the DevFabric UI:

Screenshot of DevFabric UI

If you can’t see the DevFabric UI, you can enable it here after starting your cloud app from Visual Studio:

image 

Using the DevFabric UI is the most basic form of viewing Trace output. Looking at each individual console window doesn’t really scale well if you have many instances and, furthermore, the console window of an instance is not available in the cloud. For this, there is a special TraceListener derived class: Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener. It sends the trace output to a Windows Azure diagnostics monitor process that is able to store the messages in Windows Azure Storage. Here is a look at a trace message using the Azure Storage Explorer:

Screenshot of Azure Storage Explorer

This trace listener is enabled through web.config:

  <system.diagnostics>
    <sources>
      <source name="Diag">
        <listeners>
          <add name="AzureDiagnostics" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          name="AzureDiagnostics" />
    </sharedListeners>
    <trace>
      <listeners>
        <add name="AzureDiagnostics" />
      </listeners>
    </trace>
  </system.diagnostics>

You can also see a message “TraceSource called at …”. This message was output using a TraceSource instance:

private static readonly TraceSource ts = new System.Diagnostics.TraceSource("Diag", SourceLevels.All);

protected void TraceMeButton_Click(object sender, EventArgs e)
{
    ts.TraceEvent(TraceEventType.Information, 2, "TraceSource called at {0}.", DateTime.Now);
    System.Diagnostics.Trace.TraceInformation("Old Trace called at {0}.", DateTime.Now);
}

However, note that a similar message “TraceSource called at …” didn’t show up in the DevFabric UI. You might wonder what is going on. And you might wonder why I want to use a TraceSource instead of Trace? Because this MSDN article states:

One of the new features in the .NET Framework version 2.0 is an enhanced tracing system. The basic premise is unchanged: tracing messages are sent through switches to listeners, which report the data to an associated output medium. A primary difference for version 2.0 is that traces can be initiated through instances of the TraceSource class. TraceSource is intended to function as an enhanced tracing system and can be used in place of the static methods of the older Trace and Debug tracing classes. The familiar Trace and Debug classes still exist, but the recommended practice is to use the TraceSource class for tracing.

Also check out this blog post.

The reason you don’t see the message for the TraceSource in the DevFabric UI is that the DevFabric magically adds a special TraceListener for the “old fashioned” Trace class, but not for your TraceSource instance. I put together a cloud app solution (Visual Studio 2010) that shows this through a simple web role. This web role has the configuration you see above in its web.config file. If you run this simple web role in the DevFabric you’ll see:

Screenshot of sample web role app

Note that Trace has a Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime.DevelopmentFabricTraceListener instance registered, while the TraceSource hasn’t. To remedy this, I’ve created a small class that adds a DevFabricTraceListener to a TraceSource if it is registered for Trace:

public static class TraceSourceFixer
{
    private const string DevFabricTraceListenerFullName = "Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime.DevelopmentFabricTraceListener";

    public static void AddDevFabricTraceListener(TraceSource traceSource)
    {
        var alreadyInTraceSource = GetDevFabricTraceListeners(traceSource.Listeners);

        if (alreadyInTraceSource.Count() > 0)
            return;

        var alreadyInTrace = GetDevFabricTraceListeners(Trace.Listeners);

        var devFabricTraceListener = alreadyInTrace.FirstOrDefault();
        if (devFabricTraceListener != null)
        {
            traceSource.Listeners.Add(devFabricTraceListener);
        }
    }

    private static IEnumerable<TraceListener> GetDevFabricTraceListeners(TraceListenerCollection listeners)
    {
        var result = from TraceListener listener in listeners.Cast<TraceListener>()
                where IsDevFabricTraceListener(listener)
                select listener;

        return result;
    }

    private static bool IsDevFabricTraceListener(TraceListener listener)
    {
        return (listener.GetType().FullName == DevFabricTraceListenerFullName);
    }
}

This helper class gets called when you press the Register DevFabric Listener button. If you click the Trace Me button after that, you’ll see two trace messages show up in the DevFabric UI:

Screenshot of DevFabric UI detail

You can download my solution DiagnosticsService.zip to try it yourself.

Leave a Reply

Your email address will not be published. Required fields are marked *