Use Application Insights in a desktop application

Application Insights allows to monitor applications. Monitoring your application is very important to know which features are used, to track unexpected exceptions and performance issues, …

With Visual Studio 2017, you can integrate Application Insights in a web application in about 30 seconds (or maybe less). However, there is nothing new for integration with desktop applications. This means you'll need to do the hard work by yourself.

First, you need to create a new Application Insights instance on the Azure portal, and get the instrumentation key:

Instrumentation key

Then, add the 2 following NuGet packages to your application:

The first package contains the TelemetryClient object. This is the object used to send data to Azure. The second package is not mandatory but strongly recommended. Indeed, the TelemetryClient store events in the memory and send them in batch at regular intervals. So, some events may get lost if the application crashes. Paradoxically, the exception is very important in this case, and it is lost… The ServerTelemetryChannel, provided by the second package, stores the events in a file and then, it sends them to Azure at regular intervals. So, if the application terminates without sending some events, they'll be sent the next time you start the application.

public static class Telemetry
{
    private const string TelemetryKey = "<INSERT YOUR TELEMETRY KEY HERE>";

    private static TelemetryClient _telemetry = GetAppInsightsClient();

    public static bool Enabled { get; set; } = true;

    private static TelemetryClient GetAppInsightsClient()
    {
        var config = new TelemetryConfiguration();
        config.InstrumentationKey = TelemetryKey;
        config.TelemetryChannel = new Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel();
        //config.TelemetryChannel = new Microsoft.ApplicationInsights.Channel.InMemoryChannel(); // Default channel
        config.TelemetryChannel.DeveloperMode = Debugger.IsAttached;
#if DEBUG
        config.TelemetryChannel.DeveloperMode = true;
#endif
        TelemetryClient client = new TelemetryClient(config);
        client.Context.Component.Version = Assembly.GetEntryAssembly().GetName().Version.ToString();
        client.Context.Session.Id = Guid.NewGuid().ToString();
        client.Context.User.Id = (Environment.UserName + Environment.MachineName).GetHashCode().ToString();
        client.Context.Device.OperatingSystem = Environment.OSVersion.ToString();
        return client;
    }

    public static void SetUser(string user)
    {
        _telemetry.Context.User.AuthenticatedUserId = user;
    }

    public static void TrackEvent(string key, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
    {
        if (Enabled)
        {
            _telemetry.TrackEvent(key, properties, metrics);
        }
    }

    public static void TrackException(Exception ex)
    {
        if (ex != null && Enabled)
        {
            var telex = new Microsoft.ApplicationInsights.DataContracts.ExceptionTelemetry(ex);
            _telemetry.TrackException(telex);
            Flush();
        }
    }

    internal static void Flush()
    {
        _telemetry.Flush();
    }
}

Then, you can use it everywhere in your application:

Telemetry.TrackEvent("Application started");

A good practice is to track all unhandled exceptions in your application:

// Somewhere in the Main method or Startup event in a WPF app
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Application.Current.DispatcherUnhandledException += DispatcherUnhandledException; // WPF app


private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    var ex = e.ExceptionObject as Exception;
    Telemetry.TrackException(ex);
}

private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
    Telemetry.TrackException(e.Exception);
}

private static void DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    Telemetry.TrackException(e.Exception);
}

Then, you can analyse your data on the portal:

Query result

Leave a reply