Share via


Richer exception details in Application Insights (custom exceptions!)

Hello everyone,

[Update]: I thought a great place for this code to run would be a telemetry processor, so I created one. I shared it on GitHub: https://github.com/helgemahrt/EnhancedApplicationInsights/blob/master/helgemahrt.EnhancedAI/Shared/TelemetryProcessors/ExceptionTelemetryEnhancer.cs
Additionally, I packed it into a NuGet package, which you can find here: https://www.nuget.org/packages/helgemahrt.EnhancedAI

While working on a project recently I encountered a situation where we needed to report custom exceptions to Application Insights. To keep things simple, they looked something like this:

 
public class CustomException : Exception
{
    public String AdditionalInformation { get; set; }

    public CustomException()
    {
    }

    public CustomException(string message) : base(message)
    {
    }

    public CustomException(string message, string additionalInformation) : base(message)
    {
        AdditionalInformation = additionalInformation;
    }

When throwing them we would provide addition context information, which was important to understand the failure. Something along these lines:

 
throw new CustomException("Something went wrong.", 
    "A piece of information I need to see in Application Insights.");

Unfortunately, by default - apart from the stack trace - all you get in Application Insights is the type of the exception and the message:
Capture

Luckily, the ExceptionTelemetry object accepts additional parameters, and with a bit of .NET reflection magic we can easily get all properties of any exception, serialize them and ship them off to Application Insights. Here’s an example of how to do this:

 
// ignore cyclic references
private static JsonSerializerSettings jsonSettings = 
    new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };

void LogException(Exception exception)
{
    ExceptionTelemetry telemetry = new ExceptionTelemetry(exception);

    // serialize properties that an exception may have and send them to application insights
    Type exceptionType = exception.GetType();
    if (exceptionType != null)
    {
        foreach (PropertyInfo property in exceptionType.GetProperties())
        {
            if (string.Equals(property.Name, "StackTrace") ||
                string.Equals(property.Name, "Message") ||
                string.Equals(property.Name, "TargetSite"))
            {
                // skip duplicate data
            }
            else
            {
                telemetry.Properties[$"{exceptionType.Name}.{property.Name}"] 
                    = JsonConvert.SerializeObject(property.GetValue(exception), jsonSettings);
            }
        }
    }

    client.TrackException(telemetry);
}

If we now report our CustomException to Application Insights, we get a lot more context information. It’ll show up in the “Custom Data” section in the Application Insights dashboard:
Capture2

In our project, we used this custom logging function in a Web Job which was a plain console application. However, if you’re using Application Insights in a Web App, you can create a custom exception filter to easily add this information to all exceptions reported to AI.

I hope this helps you troubleshoot your issues!

Cheers,

Helge Mahrt