Monday, August 3, 2015

Azure Application Insights: Know Your Users

(The layout of this blog post is terrible, I know. Blogger.com just seems not to be suitable for pictured step-by-step guides. Or at least not with the amount of effort that I was willing to spend.)

When I was looking for a way to collect voluntary usage statistics for a desktop App, I stumbled upon Application Insights, which is a Microsoft Azure service that is currently in preview. There is an introduction and further readings on MSDN. However, I will give a short summary of which steps to take to set AppInsights up and what the results will look like so you can get a quick glance at what you can expect.

Feature Summary


FeatureUse cases
Track pagesTrack which pages (web), windows (desktop) or screens (mobile) are visited how often by your users and what they load time was.
Track sessionsTrack all active server sessions (web) or running app instances (desktop and mobile).
Track eventsTrack some meaningful events for you, such as clicking of a certain button, choosing a certain option or executing a certain command.
Track metricsTrack how often something in your app happens, how many datasets your users manage with your app or some other averages.
Track web requestsWeb only: Track requests to other web services and how long they take.
Track crashes and tracesTrack detailed information about crashes, exceptions or some other unexpected situation, including full call stacks and many other properties, such as geographical area, operating system, and more.
Custom propertiesAttach custom properties of any kind either to the context that all metrics are collected in, or for each telemetry item itself.
Time rangeSpecify the time range that should be included in the graphs on the App Insights dashboard.
AlertsSpecify alerts that trigger when certain conditions are met (such as when more than 100 exceptions are logged within 15 minutes). This seems to be useful for web services only.
Data exportYou can download data for any kind of telemetry item as an Excel spreadsheet.
Continuous exportIf the one-time export is not enough, you can continuously export to an Azure storage space. This seems to be possible in JSON format only, so you need some hand-crafted code to process the data any further. See https://azure.microsoft.com/en-us/documentation/articles/app-insights-export-telemetry/ for more details.


Requirements


Application Insights runs on Microsoft Azure, so an Azure subscription is a prerequisite. You can use it either on mobile apps (iOS and Android), web sites and services (ASP.NET, WCF, J2EE) or desktop apps (either Classic or Windows Store Apps - in other words: anything written in .NET). AppInsights is free for a limited number of datasets and will cost about $25,- for standard and $100,- for premium accounts. See the pricing table.

Getting Started


For the impatient, there is a TL;DR version of it at the bottom.

To get started, you need to log into your Azure account at the new Azure Portal or register for a new account, and add Application Insights.
When you first log in, it looks something like this:

An empty Azure Portal start screen

The design of the home screen is kept in the tiled style, just like the Windows 8 start page or Windows Phone home screens. I personally find this pretty neat and clear.

You can add Application Insights by hitting the big fat + in the upper left corner and then browse to [Developer Services > Application Insights].

A shortcut on the "Home Screen" will be created automatically for you. But before, you will have to set up your new instance of Application Insights.
Add Application Insights to your Azure account
First you have to select the Application Type. I think this does not influence the capabilities of the instance at all - instead only a few default settings and pinned elements on the dashboard will differ. I find the names a bit misleading, personally, since there is no clear mapping from the name to the underlying technology. E.g. I use the type "Windows Store Application" for a classic desktop application written in C# and WPF.

I have no idea what a Resource Group is, but rumor has it you can find out more here.

If you have multiple Subscriptions you can select the one that should be billed for this AppInsights instance here.

Currently, there is only the "Central US" Location. I guess, if App Insights will find it's users, there will be more locations added.
Set up Application Insights - Step 1 of 2

There is now a new icon on your home screen: "tutorial APPLICATIONINSIGHTS" (I have no clue why the instance name is in lowercase and the service name is in ALL CAPS).

Click this new icon and you will finally find your Application Insights.

Set up Application Insights - Step 1 of 2

You are now on the usage statistics dashboard, which will be the starting point for all analysis. The dashboard is fully configurable and is populated with some default widgets. These, too, are aligned in tiles. The most prominent default tile is the Timeline. You can watch the trend in numbers of metric items of the past week and you will see new items coming in live. All views in Application Insights are viewing live data, which is especially useful for websites I'd imagine.

If you are interested in statistics of a longer time range, let's say half a year, you can easily configure that via the "Time Range" tool button.

I will describe more features after we got some data into our dashboard.

Set up Application Insights - Step 1 of 2

The last step in the Azure Portal before some coding is to copy the Instrumentation Key, which is our unique identifier that we need to provide to AppInsight's Telemetry API that is used to collect and send telemetry data into our Azure AppInsights dashboard.

Set up Application Insights - Step 1 of 2

Collecting data from a desktop app

For our testing purposes, we will create a simple WPF application with three buttons.
Our Test Application
We will track three different telemetry items:
  • Click of Button 1, including the total number of clicks on this button in the running session.
  • Click of Button 2, including the exact timestamp of the click.
  • A crash.
All items share some context information that is initialized in app startup. I chose to set the User ID to a fixed user called "tutorial1" and add a custom property named "app_start" that includes the time when the app was started.
To start collecting data, we need to utilize AppInsight's telemetry API. We can install the required assemblies via NuGet by right-clicking our project in the Solution Explorer, then selecting "Manage NuGet Packages" and install the package named Microsoft.ApplicationInsights (Application Insights Core API).

The class Microsoft.ApplicationInsights.TelemetryClient is the core class that we need to collect data. First, we initialize the Instrumentation Key and the context in MainWindow's ctor:

private TelemetryClient tc = new TelemetryClient();

public MainWindow()
{
    tc.InstrumentationKey = "aea76edd-a119-4ce3-bba0-2a31ec66880d";
    tc.Context.User.Id = "tutorial1";
    tc.Context.Properties["app_start"] = DateTime.Now.ToString(CultureInfo.InvariantCulture.DateTimeFormat);

    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

    InitializeComponent();
}

Then, we will add three event handlers for the aforementioned events that we would like to track:

private int button1Counter = 0;

private void button1_Click(object sender, RoutedEventArgs e)
{
    var ev = new EventTelemetry("button1");
    ev.Properties["click_counter"] = (++button1Counter).ToString();
    tc.TrackEvent(ev);
    tc.Flush();
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    var ev = new EventTelemetry("button2");
    ev.Properties["click_time"] = DateTime.Now.ToString(CultureInfo.InvariantCulture.DateTimeFormat);
    tc.TrackEvent(ev);
    tc.Flush();
}

private void buttonCrash_Click(object sender, RoutedEventArgs e)
{
    object foo = null;
    string crash = foo.ToString();
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is Exception) {
        tc.TrackException(new ExceptionTelemetry((Exception) e.ExceptionObject));
        tc.Flush();
    }
}

That's all!
Now we can start this nice little demo app and mash the buttons a few times. Remember that the app will actually crash when you click on Crash!.
When you are done playing with your app, we can head back to the Azure Portal and look at the AppInsights dashboard. As I said earlier, the data is updated live, so the newly created items should be visible immediately. If they are not, just hit "Refresh".


Watch Live Telemetry Data

Voila! There it is: One user, and four crashes - I apparently hit on "Crash!" four times. We can inspect the crashes to see more information.


Inspect crashes

You can see interesting things like how many times the crash occured, how many users where affected. If I initialized the context of the TelemetryClient properly, we could see the affected program versions, devices names and operating systems that the crash happened on. I'm sure that you can imagine that all these properties will be very interesting when trying to fix crashes in your app.

As with any telemetry items, you can even attach custom properties to the crash log, so you can include information that might be interesting in your specific app, such as the title of the active window when the crash happened or even the free disk space or things like that.

You could see these custom properties together with a few other properties that are gathered by default on the "Exception Properties" page.
Exception properties page

If you are not using an online crash logging facility already, this will really take your bug fixing to a new level!

There are similarly useful stats for your custom events that you logged when clicking the two buttons.

Custom event infos

TL;DR


See the feature list and the requirements at the top.
Then, execute these steps:
  • Create an Azure account, if you do not already have one
  • Add [Developer Services > Application Insights] in your Azure Portal
  • Copy the Instrumentation Key
  • Create a new WPF app
  • Add the package "Microsoft.ApplicationInsights" Core API via NuGet
  • Create a Microsoft.ApplicationInsights.TelemetryClient and call TrackEvent, TrackPageView, TrackException, TrackMetric, TrackRequest or TrackTrace.
  • Watch the data appear in the AppInsights dashboard

Code


You can find the full example code on GitHub.