Unity, Part 11: Integrating With Azure Application Insights

Another one for the Unity series.

Lately I’ve been playing with Azure Application Insights. Nice thing, even if – at least, for the moment – not as powerful as some of its contesters. A thing that came to my mind almost immediately was how to integrate it with IoC containers like Unity.

I already talked about how to use AOP techniques in Unity. This time I will leverage on that and explain how we can use this knowledge to add insights into our application transparently.

We need the Application Insights SDK, which is available at GitHub in source code and conveniently as a NuGet package (all you need is Microsoft.ApplicationInsights):

image

I implemented an HandlerAttribute that is also an implementation of ICallHandler. Inside of it, I call the intercepted method and then log it to Application Insights through the TelemetryClient, a part of the Application Insights APIs. I added an option to set the instrumentation key, which uniquely identifies our Application Insights account and shouldn’t be shared. If not supplied, it will default to whatever is in

TelemetryConfiguration.Active.InstrumentationKey. Finally, we can decide to have the call asynchronous (so as to not cause delays to our application) or synchronous.

Here is the code for the interception attribute:

[Serializable]

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]

public sealed class TelemetryCallHandlerAttribute : HandlerAttribute, ICallHandler

{

    #region Public constructors

    public TelemetryCallHandlerAttribute()

    {

    }

 

    public TelemetryCallHandlerAttribute(string instrumentationKey)

    {

        this.InstrumentationKey = instrumentationKey;

    }

 

    public string InstrumentationKey { get; set; }

 

    public bool Async { get; set; }

 

    #endregion

 

    #region Public override methods

    public override ICallHandler CreateHandler(IUnityContainer ignored)

    {

        return (this);

    }

    #endregion

 

    #region ICallHandler Members

 

    IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

    {

        TelemetryConfiguration config = null;

 

        if (string.IsNullOrWhiteSpace(this.InstrumentationKey) == true)

        {

            config = TelemetryConfiguration.Active;

        }

        else

        {

            config = TelemetryConfiguration.CreateDefault();

            config.InstrumentationKey = this.InstrumentationKey;

        }

 

        var telemetryClient = new TelemetryClient(config);

        var watch = Stopwatch.StartNew();

        var result = getNext()(input, getNext);

 

        var elapsedMilliseconds = watch.ElapsedMilliseconds;

        var exception = result.Exception;

        var returnValue = result.ReturnValue;

 

        var properties = new Dictionary<string, string>();

 

        for (var i = 0; i < input.Arguments.Count; ++i)

        {

            var key = input.Arguments.ParameterName(i);

            properties[key] = (input.Arguments[i] ?? string.Empty).ToString();

        }

 

        if (exception != null)

        {

            properties["$Exception"] = exception.Message;

        }

 

        if (returnValue != null)

        {

            properties["$ReturnValue"] = returnValue.ToString();

        }

 

        var metrics = new Dictionary<string, double>();

        metrics["ElapsedMilliseconds"] = elapsedMilliseconds;

 

        if (this.Async == false)

        {

            this.TrackEvent(telemetryClient, input.MethodBase.Name, properties, metrics);

        }

        else

        {

            this.TrackEventAsync(telemetryClient, input.MethodBase.Name, properties, metrics);

        }

 

        return (result);

    }

 

    private void TrackEvent(TelemetryClient telemetryClient, string name, IDictionary<string, string> properties, IDictionary<string, double> metrics)

    {

        telemetryClient.TrackEvent(name, properties, metrics);

    }

 

    private async void TrackEventAsync(TelemetryClient telemetryClient, string name, IDictionary<string, string> properties, IDictionary<string, double> metrics)

    {[Serializable]

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]

    public sealed class TelemetryCallHandlerAttribute : HandlerAttribute, ICallHandler

    {

        #region Public constructors

        public TelemetryCallHandlerAttribute()

        {

        }

 

        public TelemetryCallHandlerAttribute(string instrumentationKey)

        {

            this.InstrumentationKey = instrumentationKey;

        }

 

        public string InstrumentationKey { get; set; }

 

        public bool Async { get; set; }

 

        #endregion

 

        #region Public override methods

        public override ICallHandler CreateHandler(IUnityContainer ignored)

        {

            return (this);

        }

        #endregion

 

        #region ICallHandler Members

 

        IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

        {

            TelemetryConfiguration config = null;

 

            if (string.IsNullOrWhiteSpace(this.InstrumentationKey) == true)

            {

                config = TelemetryConfiguration.Active;

            }

            else

            {

                config = TelemetryConfiguration.CreateDefault();

                config.InstrumentationKey = this.InstrumentationKey;

            }

 

            var telemetryClient = new TelemetryClient(config);

            var watch = Stopwatch.StartNew();

            var result = getNext()(input, getNext);

 

            var elapsedMilliseconds = watch.ElapsedMilliseconds;

            var exception = result.Exception;

            var returnValue = result.ReturnValue;

 

            var properties = new Dictionary<string, string>();

 

            for (var i = 0; i < input.Arguments.Count; ++i)

            {

                var key = input.Arguments.ParameterName(i);

                properties[key] = (input.Arguments[i] ?? string.Empty).ToString();

            }

 

            if (returnValue != null)

            {

                properties["$ReturnValue"] = returnValue.ToString();

            }

 

            var metrics = new Dictionary<string, double>();

            metrics["ElapsedMilliseconds"] = elapsedMilliseconds;

 

            if (this.Async == false)

            {

                if (exception != null)

                {

                    properties["Name"] = input.MethodBase.Name;

                    this.TrackException(telemetryClient, exception, properties, metrics);

                }

                else

                {

                    this.TrackEvent(telemetryClient, input.MethodBase.Name, properties, metrics);

                }

            }

            else

            {

                if (exception != null)

                {

                    properties["Name"] = input.MethodBase.Name;

                    this.TrackExceptionAsync(telemetryClient, exception, properties, metrics);

                }

                else

                {

                    this.TrackEventAsync(telemetryClient, input.MethodBase.Name, properties, metrics);

                }

            }

 

            return (result);

        }

 

        private void TrackException(TelemetryClient telemetryClient, Exception ex, IDictionary<string, string> properties, IDictionary<string, double> metrics)

        {

            telemetryClient.TrackException(ex, properties, metrics);

        }

 

        private async void TrackExceptionAsync(TelemetryClient telemetryClient, Exception ex, IDictionary<string, string> properties, IDictionary<string, double> metrics)

        {

            await Task.Run(() => this.TrackException(telemetryClient, ex, properties, metrics));

        }

 

        private void TrackEvent(TelemetryClient telemetryClient, string name, IDictionary<string, string> properties, IDictionary<string, double> metrics)

        {

            telemetryClient.TrackEvent(name, properties, metrics);

        }

 

        private async void TrackEventAsync(TelemetryClient telemetryClient, string name, IDictionary<string, string> properties, IDictionary<string, double> metrics)

        {

            await Task.Run(() => this.TrackEvent(telemetryClient, name, properties, metrics));

        }

 

        #endregion

    }        await Task.Run(() => this.TrackEvent(telemetryClient, name, properties, metrics));

    }

 

    #endregion

}

It will track the event under the called method name, and will send along a string representation of all its arguments, result value, exception thrown (if any) and elapsed time (TelemetryClient.TrackEvent or TelemetryClient.TrackException).

A simple usage, without providing the instrumentation key, would be:

[TelemetryCallHandler]

public virtual BusinessResponse PerformBusinessOperation(int businessId, string arg)

{

    //...

}

If the InstrumentationKey property is not supplied, it must be set through TelemetryConfiguration.Active.InstrumentationKey:

TelemetryConfiguration.Active.InstrumentationKey = "my key";

Having it as an IInterceptionBehavior should be straightforward. Feel free to modify it to your liking!

Data Platform Airlift 2015

Today I had the great pleasure to attend the Data Platform Airlift 2015 event, at Microsoft Portugal! Moreover, I presented a session together with Luís Calado on what’s new in the Azure world! My part was specifically about DocumentDB, one of Microsoft’s offers in the field of NoSQL.

Videos and materials for all presentations will be made available on Channel 9 in the next days, but, in the meantime, you can find my slide deck here.

As always, looking forward for your feedback!

Automating Microsoft Azure with PowerShell Review

Introduction

I was again asked by Packt Publishing to review one of their books, this time, it was Automating Microsoft Azure with PowerShell. It came in good time, because I am starting to use Azure more and more, and PowerShell is a timesaver – actually, it is the only way to do lots of things. I have reviewed other books on Azure, which you can find at my blog, here.

The book starts with an introductory chapter, where PowerShell and Azure are introduced, and then goes to the real thing. Not all APIs are covered, namely, Machine Learning, DocumentDB, BizTalk, Stream Analytics, etc, etc, which is not really surprising, since it seems that every month a new service pops out. The book is ~150 pages long, distributed between 10 chapters, which is perfectly acceptable for the amount of topics it covers. The target audience is clearly administrators with little knowledge of Azure.

The author is John Chapman, which can be followed at Twitter as @chapmanjw.

Chapter 1: Getting Started with Azure and PowerShell

This chapter offers an introduction to PowerShell and how to install the Azure integration, retrieve subscription files and connecting to Azure. At the end of it we see how to create a blank website using PowerShell.

Chapter 2: Managing Azure Storage with PowerShell

This one is about storage. It explains about the major storage options that Azure has to offer – Table storage, Blobs, Queues and Files. Basic operations are discussed and we are presented with an example of a backup system.

Chapter 3: Managing Azure Virtual Machines with PowerShell

Next we have a discussion of the APIs available for the management of virtual machines (VMs). We learn how to create the many kinds of VMs existing in the Azure gallery, and performing all the typical operations, including creating snapshots and managing its storage.

Chapter 4: Managing Azure SQL Databases with PowerShell

In this chapter we learn how to create SQL servers and databases, configuring access to them, executing queries and finally exporting and importing data to and from.

Chapter 5: Deploying and Managing Azure Websites

Chapter 5 is about Azure Websites, the old name for Azure Web Apps. We learn how to create websites and how to provision them. Here I got the feeling that a lot is missing.

Chapter 6: Managing Azure Virtual Networks with PowerShell

A short chapter on how to configure virtual networks. Again, a lot more could be said on this.

Chapter 7: Managing Azure Traffic Manager with PowerShell

Azure Traffic Manager is Azure’s load-balancing mechanism. It explains how to configure websites for using the different load balancing techniques and load balancing profiles.

Chapter 8: Managing Azure Cloud Services with PowerShell

Cloud Services is another way to host VMs. The chapter explains how to create and manage cloud services, roles and endpoints and how retrieve Remote Desktop connection files.

Chapter 9: Managing Azure Active Directory with PowerShell

This chapter explains the basics of the Azure Active Directory (AD), the main authoritative source of identities in an Azure virtual network. We learn how to create and configure the basic options of an AD, managing users, groups and password policies. The example at the end of the chapter is about bulk creating users in the AD.

Chapter 10: Automating Azure with PowerShell

The final chapter talks about one of the automation mechanisms in Azure. We learn how to create an automation account and how to add runbooks to it.

Conclusion

The book is very succinct, and some topics would require substantially more coverage. It does provide some information enough to cover the basic usage of the covered Azure services.

Learning Microsoft Azure Review

Introduction

I was recently asked by Packt Publishing to do a review of their title Learning Microsoft Azure, and so I did.

It wasn’t the first time I did a review on an Azure book, I also reviewed Microsoft Azure Development Cookbook, Second Edition, and you can see my review here.

This time, it is an introductory book, where the reader is introduced to Microsoft Azure, and guided as he/she develops a full solution for an imaginary industrial bakery, from end to end, including a mobile app. It covers technologies such as ASP.NET MVC 5, Windows Phone 8, Entity Framework Code First and Web API, always using C# and .NET as the backing framework. At the end of each chapter, there’s a questions and answers page where we can assess our level of understanding of the topics that were discussed in it.

The author is Geoff Webber-Cross (@webbercross), which also authored another book on Azure and Windows Phone.

Chapter 1: Getting Started with Microsoft Azure

The first chapter, as we might expect, does an introduction to cloud computing and the Microsoft Azure service, presents a decision framework for aiding in selecting a cloud service as opposed to on-premises, guides the reader in creating an Azure account including it’s many services and costs, and lists the most relevant terms that we will be encountering throughout the book.

Chapter 2: Designing a System for Microsoft Azure

Here we are presented with the sample scenario, its objectives and requirements and the architectural vision of it. Different views on the system and its subsystems are presented and for each the technical decisions are explained.

Chapter 3: Starting to Develop with Microsoft Azure

Next we setup the development environment, choose a Visual Studio edition, download the required SDK and create a project to be published in our Azure account. Visual Studio Online is also presented and it’s integration with Azure, namely, in order to ensure continuous integration and delivery.

Chapter 4: Creating and Managing a Windows Azure SQL Server Database

Here we get an overview of the SQL functionality of Azure, how to create and manage databases using the portal, Visual Studio and the SQL Server Management Studio, then we learn how to use Entity Framework Code First to access and manipulate its data, and to migrate to and from different versions using the Migrations API.

Chapter 5: Building Azure MVC Websites

This chapter explains how we can build an MVC application using OAuth authentication (social accounts such as Twitter, Facebook, Google and Microsoft Live). It goes on explaining how we can set up custom domains and SSL certificates for HTTPS and how to integrate the Azure Active Directory for single sign-on and custom permissions.

Chapter 6: Azure Website Diagnostics and Debugging

This one is about diagnosing problems and debugging our applications. It presents the basic built-in tracing and logging features of Azure and how we can obtain this information and goes on to show how we can use table storage and blobs for custom storing of structured logs and its querying. Kudu is briefly introduced and at the end we learn how to do remote debugging.

Chapter 7: Azure Service Bus Topic Integration

Next up is Service Bus, Azure’s enterprise service bus service. We learn how to configure it, create and manage topics using the portal and how to use the service from our MVC application and expose it as a service.

Chapter 8: Building Worker Roles

The next chapter is about Worker Roles, a feature of Azure Websites that performs disconnected (non web-related) tasks. The reader is guided in creating a Worker Role with Visual Studio, executing it in the Emulator and publishing it to Azure. The example presented builds on the Service Bus topics discussed in the previous chapter. We also learn about other scheduling mechanism of Azure, Scheduler jobs, and implement an example using Queues.

Chapter 9: Cloud Service Diagnostics, Debugging, and Configuration

Here we learn about configuring and using the diagnostics features of Cloud Services, again expanding the concepts introduced in chapter 6. We talk about IntelliTrace and Remote Debugging and on how to connect to our virtual machines with Remote Desktop. Finally we are given an example on how to use script tasks to automate common needs.

Chapter 10: Web API and Client Integration

This chapter introduces ASP.NET Web API, Microsoft’s latest technology for building REST web services and SignalR, for asynchronous, duplex, real-time communication between web clients and the server. The provided example shows how to integrate these two technologies to broadcast messages to connected clients, including a desktop Windows Presentation Framework (WPF) application. In the end we learn how to use the Active Directory to authorize accesses to our services.

Chapter 11: Integrating a Mobile Application Using Mobile Services

Coming closer to the end, this chapter walks the reader on the various aspects of building a mobile client that connects to the cloud using Azure Mobile Services. We see how to implement a mobile-enabled web application and Web API service, how to publish it and how to implement a matching Windows Phone application, fully featured with push notifications. It also guides us on configuring the mobile service with Active Directory for authentication. At the end we are shown how to build a Windows Store app to interact with our application.

Chapter 12: Preparing an Azure System for Production

The final chapter puts everything in place, explains how to setup different build configurations for different deployment environments and how to build and deliver deployment packages for Azure. At the very end we get a deployment checklist that may come in handy if ever we run into problems.

Conclusion

Overall, I enjoyed reading this book. It doesn’t cover all of Azure, but it does a very decent job in explaining how one can build a real-life application that works and handles most typical concerns, including support for mobile devices.