How to use AppInsights with ASP.NET Core 2.0

With all excitement and new release cadence of .NET Core, there are a lot of moving parts you need to be aware when adding AppInsights.
We will guide you through possible challenges when using AppInsights with ASP.NET Core MVC 2.0
more here

Let’s start with the official docs:

All in all, it is so easy to integrate AppInsights if you’re using VS 2017 – it does everything by default. It is much harder to do that in, say, VS Code.

So what is wrong with quick and dirty VS 2017 style integration?
It is transparent and invisible. And if you want to customize AppInsights, you would have to do everything manually.

What do we suggest?
We went through integration and production use of AppInsights in ASP.NET Core 2.0 app. We’re tracking server side information, dependencies, browser-side behavior, performance and errors. That happens on multiple environments, so configuring AppInsights to work with environments is important.

What are the steps?

  1. Install AppInsights latest package. 2.2.0-beta3 as of now. This will give you a realtime server monitor in Azure Portal (anything 2.2.0 and up)
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.0-beta3" />

Add initialization code in Startup constructor:

public Startup(IHostingEnvironment env)
{
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        builder.AddApplicationInsightsSettings();
        Configuration = builder.Build();
}

and in Startup.ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
...
services.AddApplicationInsightsTelemetry(Configuration);
}
  1. Start tracking any events in the server-side code
    Inject TelemetryClient where needed and track event(s).
public YourController(TelemetryClient insightsClient)
{
    _insightsClient = insightsClient;
}

public async Task<IAsyncResult> Home()
{
_insightsClient.TrackEvent("CustomEvent", 
      new Dictionary<string, string>() 
      { 
         { "CustomParameter1", "Value1" }, 
         { "CustomParameter2", "Value2" }
     });
}
  1. Add support for different environments (say, development and production)
    Easiest way to do that is to configure your Azure AppServices with different AppInsights Telemetry Keys in the Application Settings blade.
    Alternatively, you could do this if you have already multiple environment settings in the .json format:
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey = yourEnvironmentKey;

yourEnvironmentKey is the instrumentation key for the specific environment you want to setup. You could also use that to separate analytics from version 1 of your app to version 2.
There’s an additional information in the official docs Separating telemetry from development, test, and release in Azure Application Insights | Microsoft Docs
7. Configure keys and deploy
After deploying/running your app and loading several pages, you should see:
– custom events
– dependencies
– browser-related information, including javascript errors

Some pictures

What’s next?

Power of AppInsights is that it is tracking everything by default. And it is configurable. There are a lot of extensions and things you can do with it.

For example, we were getting a lot if dependency-events in the system and it was taking down useful space in AppInsights. So we added a filter to skip all quick and successful SQL queries.
Create an extension:

public class SkipQuickSQLDependencies : ITelemetryProcessor
{
    private const int SlowSqlMs = 500;
    private ITelemetryProcessor Next { get; }

    public SkipQuickSQLDependencies(ITelemetryProcessor next)
    {
        Next = next;
    }

    public void Process(ITelemetry item)
    {
        if (ShouldSkipDependency(item)) { return; }
        this.Next.Process(item);
    }

    private bool ShouldSkipDependency(ITelemetry item)
    {
        var dependency = item as DependencyTelemetry;
        if (dependency?.DependencyTypeName == "SQL")
        {
            if (dependency.Duration.TotalMilliseconds < SlowSqlMs && dependency.Success == true)
                return true;
        }
        return false;
    }
}

Plug it in in your Startup class:

var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
builder.Use((next) => new SkipQuickSQLDependencies(next));
builder.Build();

You can also do that on the client side in JavaScript, though this feature is not documented. To filter/preprocess data in Application Insights use AppInsights JS SDK TelemtryInitializer and return false when you don’t want to process the item. Source – ApplicationInsights JS Github

Enjoy clarity of your data. Just make sure you know what you’re filtering out (remember Survivorship bias?).

Update:

We were able to cut AppInsights Azure costs on one of our high load web services from ~$100/mo to ~$8/mo by filtering out some of the noisy data.