AzureTrace … managing all your Azure Logging Needs

One of the best practices when creating an application on top of the Azure Service Platform is to constantly log your applications activity. This is so that when a worker role inevitably goes down (and it will) you will be view output in your log files to view if there was an error with the code in your application (surely not :p ) or if it was a problem that occurred with the fabric itself.

To write out to the Azure logs you need to use the RoleManager and write to the log as the below code shows:

 RoleManager.WriteToLog("Information", "Logging the activity of my web / worker role");

Now, not only can this start to make your code extremely ugly (yes, we all love pretty code) by you take more time deciding what to log, how much information to provide, and creating a string to pass to the WriteToLog method.

There are a number of areas where I can think that logging would be needed these are:

  • Tracing In / Out of a method, making us aware of where the error occurred along with some simple performance monitors from your logs timestamps).
  • Exceptions, this is vital, every time an error occurs we want to log as much information as possible.
  • General Messages, you may just want to log that your application has reached a certain point in its process or the outcome of a given task.
  • Variable values, if you change on of your variables throughout a process you may want to keep a log of what its value has been throughout the whole process. This would make it a lot easier to pin point where anything has gone wrong in a process. 

With these four key tracing areas in mine, I sat down with a nice cup of tea and pack of digestive biscuits and set to creating my own AzureTrace library that would allow you to handle the above situations with ease. Allowing you to concentrate on getting your app up and running than the finer points of logging.

The library that I have created has the following methods:

TraceIn / TraceOut

trace3

Accepts a number of parameters of type object that will be written out to the log.

Will also identify what is the calling method so that you can see the method we are in when the tracing occurs.

TraceException

trace4

Given an exception object, the method will write out information to the log identifying the exception, the exception message and the method the exception occurred in.

TreacMessage

trace5

This is much like a standard tracing method that allows you to pass in a TraceType argument that gives the an enum of the standard Azure log types (Information, Critical, Error, Warning …)  along with a format and a number of string parameters and will be written to the log as is.

Trace (Extension Method)

trace6

With the ‘Trace’ extension method you can trace any variable out to the logs. Allowing, you to record the state of a given object as it passes through the system.

All of the above methods have the option of supplying a GUID to identify the process, this makes following the process flow of a given operation over multiple roles and servers much easier. If you generate a new GUID each time a user requests an action you can have a paper trail that you can follow from start to finish. An example of this would be if a user clicks a button on the web role (generate GUID), the web role does some processing (using AzureTrace with the given GUID), passes a message to a worker role via queues (adding the GUID as a property of the message) and then continue to log with the same GUID on the worker role.

HiddenInformation Attribute

trace8

When creating these methods I realised that when logging out to these methods may end up supplying the reader of the logs with private information such as a persons national insurance number or other personal identifiable data that you don’t want just anyone looking at, so with this in mind (and another cup of tea) I created an attribute that would allow you to hide properties within an abject and therefore this data would not get written out to the log.

AzureTrace In Action

I have created a quick sample application that uses all of the methods within the library along with the Hidden Information attribute on a property.

    1: namespace Azure_WebRole
    2: {
    3:     using System;
    4:     using AzureTrace;
    5:  
    6:     public class TestClass
    7:     {
    8:         [HiddenInformation]
    9:         public string Hidden
   10:         {
   11:             get;
   12:             set;
   13:         }
   14:  
   15:         public string NotHidden
   16:         {
   17:             get;
   18:             set;
   19:         }   
   20:     }
   21:  
   22:     public partial class _Default : System.Web.UI.Page
   23:     {
   24:         /// <summary>
   25:         /// Handles the Load event of the Page control.
   26:         /// </summary>
   27:         /// <param name="sender">The source of the event.</param>
   28:         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
   29:         protected void Page_Load(object sender, EventArgs e)
   30:         {
   31:             TestClass testClass = new TestClass()
   32:             {
   33:                 Hidden = "Do Not Show Me!",
   34:                 NotHidden = "Show Me!"
   35:             };
   36:  
   37:             this.TraceTestMethod(testClass);
   38:         }
   39:  
   40:         /// <summary>
   41:         /// Traces the test method.
   42:         /// </summary>
   43:         /// <param name="input">The input.</param>
   44:         protected void TraceTestMethod(TestClass input)
   45:         {
   46:             AzureTraceManager.TraceIn(input);
   47:  
   48:             AzureTraceManager.TraceMessage(TraceType.Information, "Formatted text - args(0) {0} args(1) {1}", "first", "second");  
   49:             
   50:             input.Trace();
   51:  
   52:             try
   53:             {
   54:                 throw new Exception("Something went wrong. :s");
   55:             }
   56:             catch (Exception ex)
   57:             {
   58:                 AzureTraceManager.TraceException(ex);
   59:             }
   60:  
   61:             AzureTraceManager.TraceOut(input);
   62:  
   63:         }
   64:  
   65:     }
   66: }

From the above code sample we get the following output displayed in the logs on the dev fabric running on our local machine.

trace2 

Notice that the only property that is written out to the log for the TestClass is that of the NotHidden property, with the Hidden property being safely hidden with the HiddenInformation attribute.

IsTracingEnabled?

When each of the methods are called I first check to see if the user is wanting to trace all this information out to the logs, this is done by looking at the cloud configuration files. The library looks into the config for a setting called “IsTracingEnabled” and if set to true will start logging. However, by default if tracing is set to false.

The below config shows a web role that has tracing enabled and worker which by default has not enabled tracing.

    1: <?xml version="1.0"?>
    2: <ServiceConfiguration serviceName="Azure" xmlns="https://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
    3:   <Role name="WebRole">
    4:     <Instances count="1"/>
    5:     <ConfigurationSettings>
    6:       <Setting name="AccountName" value="devstoreaccount1"/>
    7:       <Setting name="AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>
    8:       <Setting name="BlobStorageEndpoint" value="https://127.0.0.1:10000"/>
    9:       <Setting name="QueueStorageEndpoint" value="https://127.0.0.1:10001"/>
   10:       <Setting name="TableStorageEndpoint" value="https://127.0.0.1:10002/" />
   11:       <Setting name="IsTracingEnabled" value="true"/>
   12:     </ConfigurationSettings>
   13:   </Role>
   14:   <Role name="WorkerRole">
   15:     <Instances count="1"/>
   16:     <ConfigurationSettings>
   17:       <Setting name="AccountName" value="devstoreaccount1"/>
   18:       <Setting name="AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>
   19:       <Setting name="BlobStorageEndpoint" value="https://127.0.0.1:10000"/>
   20:       <Setting name="QueueStorageEndpoint" value="https://127.0.0.1:10001"/>
   21:       <Setting name="TableStorageEndpoint" value="https://127.0.0.1:10002/" />
   22:     </ConfigurationSettings>
   23:   </Role>
   24: </ServiceConfiguration>

 

 

 

 

 

 

I have uploaded the AzureTrace Library to my Sky Drive in case you want to give it a quick whirl / suggest any improvements that could be made.

Technorati Tags: Azure,Azure Services Platform,Cloud,Code,AzureTrace