Keep it simple, stupid … - “printf” style debugging in Windows Azure using the Azure Service Bus

 

We have the Azure Diagnostics Infrastructure ..., we have Intellitrace ..., we have the local emulator, and and  …

Yes, ... I’m aware of all these great features to debug Windows Azure applications!

But there are times when (at least I) wish to have something pretty simple, like the good old “printf” style debug output available to watch immediately on something like a console window on my developer desk!

(For people never saw a printf() statement, ... that was good old C/C++ .... it’s equivalent is today's Console.WriteLine() ;-)

Back to presence … using the Azure Service Bus ‘queue’ feature this is pretty easy to implement.

The general idea is to send your debugging output to a service bus queue from your Azure application and to catch and watch it from a simple console application on your developer desktop. Using the service bus we just make an outgoing connection from the developers desk, so firewalls should not be a problem.

 

 

We need to do 3 simple steps:

1, Create the Windows Azure Service Bus queue.

 

You can do this either from your Azure Portal resulting in something similiar to the following:

 

 

– or programmatically using something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;

namespace sbdebug
{
    class create
    {
        static void Main(string[] args)
        {
            var namespacemanager = new NamespaceManager(ServiceBusEnvironment.CreateServiceUri("sb","jwsolution1",string.Empty),
                                                         TokenProvider.CreateSharedSecretTokenProvider(
                                                                        "owner",
                                                                        "g+R1foueCH4pCJQXVE52xZ10dAvnrZi9/YJ+5MIIY="));

            var qd = namespacemanager.CreateQueue(new QueueDescription("debug")
                                                    {
                                                        DefaultMessageTimeToLive = TimeSpan.FromHours(48),
                                                        DuplicateDetectionHistoryTimeWindow = TimeSpan.FromMinutes(10),
                                                        LockDuration = TimeSpan.FromMinutes(2),
                                                        EnableBatchedOperations = true,
                                                        EnableDeadLetteringOnMessageExpiration = true,
                                                        RequiresDuplicateDetection = false
                                                    });

        }
    }
}

 

So, now in step 2 we create our "reader", in my case a simple console mode program, that f.e. could run on a the developers desk:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;

namespace sbdebug
{
    class read
    {
        static void Main(string[] args)
        {
            var messagingfactory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri(
                                                            "sb",
                                                            "jwsolution1",
                                                            string.Empty),
                                                            TokenProvider.CreateSharedSecretTokenProvider(
                                                            "owner",
                                                            "g+R1foueCH4pCJQXVE52xZ10dAvnrZi9/YJ+5MIIY=")
                                                            );

            var queueclient = messagingfactory.CreateQueueClient("debug");

            while (true)
            {
                var message = queueclient.Receive();
                if (message != null)
                {
                    var data = message.GetBody<string>();
                    Console.WriteLine(data);
                    message.Complete();
                }
            }
        }
    }
}

 

Step 3, The part where we do the logging: (usually code that finally run's in an Azure Web or WorkerRole):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;

namespace sbdebug
{
    class send
    {
        static void Main(string[] args)
        {

            var messagingfactory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri(
                                                            "sb",
                                                            "jwsolution1",
                                                            string.Empty),
                                                            TokenProvider.CreateSharedSecretTokenProvider(
                                                            "owner",
                                                            "g+R1foueCH4pCJQXVE52xZ10dAvnrZi9/YJ+5MIIY=")
                                                            );

            var queueclient = messagingfactory.CreateQueueClient("debug");

            for (int i = 0; i < 50; i++)
            {
                queueclient.Send(new BrokeredMessage(DateTime.Now+": Here I am:"+i));
            }

        }
    }
}

 

That's all!

Some notes:

  • To keep the code simple and understandable, I have left out *every* sort of error handling .. and avoided even hiding parameter values behind variables .., I have marked all the values where you probably want to use your own values in brown - and finally placed my ACS key direct into the src. (Do I need to mention that this is not the real one and that this is NoGo in a production src code ? ;-)
  • Using the various parameters for the service bus queue, you can easily specify f.e. how long the queue stores messages etc., this is very helpful if your apps produce debug output but no reader is available.
  • For testing purpose you can run both the sender and the logger part from your desktop.
  • As I noted, creation of the queue can be done either by code or using the portal (you just need to do this once ...,that parameters of CreateQueue() basically reflect what you can do in the portal. You can do even more with the API that in the portal)
  • The projects need a reference to the Microsoft.ServiceBus.dll that get's installed with the SDK .. at time of writing this this is usually located in "\Program Files\Windows Azure SDK\v1.6\ServiceBus\ref
  • To distinguish between several instances of your Azure Roles you can for example simply use System.Environment.MachineName() in your debug string.
  • Please also check that you are familiar with the fees for the Windows Azure Service bus!

 

Have fun!

JW