What's the difference between APPINSIGHTS_INSTRUMENTATIONKEY configured by Azure and ApplicationInsights:InstrumentationKey?

Liero picture Liero · Jun 6, 2018 · Viewed 10k times · Source

There is some confusion in the Application Insight configuration. It can be configured in the application itself using Visual Studio and in the App Service using Azure Portal.

Visual Studio

When I use Visual Studio to add Application Insights Telemetry to my asp.net core 2.0 website, it adds following configuration to appsettings.json:

{
// Changes to file post adding Application Insights Telemetry:
  "ApplicationInsights": {
    "InstrumentationKey": "10101010-1010-1010-1010-101010101010"
  }
}

I then configure the AppInsights services in the startup.cs like this:

var instrumentationKey= Configuration.GetSection("ApplicationInsights:InstrumentationKey").Value;
services.AddApplicationInsightsTelemetry(opt => opt.InstrumentationKey = instrumentationKey);

Azure Portal

However, when I open Application Insights tab in the App Service in Azure Portal, it still suggest to connect Application Insight. The wizard then adds new Intrumentation Key to configuration:

enter image description here

  1. Why there are two different keys?

  2. Exactly what telemetry produces App Service and what the .NET Core application itself.

  3. How can I avoid having the InstrumentationKey configured twice?

  4. What are the side effects (e.g. inside Visual Studio tooling) of using APPINSIGHTS_INSTRUMENTATIONKEY only. I mean I would write in startup.cs:

    var instrumentationKey= Configuration.GetSection("APPINSIGHTS_INSTRUMENTATIONKEY ").Value;
    services.AddApplicationInsightsTelemetry(opt => opt.InstrumentationKey = instrumentationKey);
    

EDIT:

I've come to conclusion based on Tseng's answer that it is best practice to use APPINSIGHTS_INSTRUMENTATIONKEY in both, in Azure portal and in appsettings.json.

ASP.NET Core understands both APPINSIGHTS_INSTRUMENTATIONKEY and ApplicationInsights:InstrumentationKey, but Azure Portal only the first one and it has to be environment variable. If you used the second, and tried to read it from config somewhere in the code, you could easily end up with different values in Azure Portal and in your app running in Azure.

Also, if you are manually reading the instrumentation key from configuration, you should first look at APPINSIGHTS_INSTRUMENTATIONKEY and then to ApplicationInsights:InstrumentationKey:

var instrumentationKey= Configuration.GetSection("APPINSIGHTS_INSTRUMENTATIONKEY")?.Value
    ?? Configuration.GetSection("ApplicationInsights:InstrumentationKey")?.Value;

because that's how services.AddApplicationInsightsTelemetry(Configuration); works as well. Just in case there would be different setting key in Azure Portal than in appsettings.json

Answer

Tseng picture Tseng · Jun 6, 2018

Well, the first one is when you don't host on Azure App Service or when you don't want to set an environment variable. Which one is actually used, depends on the way your configuration builder is configured.

Usually you have something like that in Startup.cs or Programm.cs:

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    .AddUserSecrets<Startup>()
    .AddEnvironmentVariables(); // Environment Variables override all other

The order in which the .AddXxx calls are used matter. The last registration with a matching key, will be used. Here .AddEnvironmentVariables() is the last one. When a APPINSIGHTS_INSTRUMENTATIONKEY variable is set, it will override all values for Appinsights:InstrumentationKey set in user secrets, appsettings.Development.json or appsettings.json.

If APPINSIGHTS_INSTRUMENTATIONKEY is not set, the configuration library will look into user secrets and use it if found. If not found it will search for appsettings.Development.json and if it doesn't contains the value search appsettings.json.

TL;DR: The one form appsettings.json will only be used when no environment variable is set.

Update

New Answer

As seen in the code, the Application Insight extension method to register it will override the values from either the environment variable or from the appsettings.json when it finds the matching entries.

Note: When you remove the .AddEnvironmentVariables() it won't ever use the value set in Azure Portal, because the .AddEnvironmentVariables() loads the environment variable into the configuration with the key APPINSIGHTS_INSTRUMENTATIONKEY (see below).

private const string InstrumentationKeyFromConfig = "ApplicationInsights:InstrumentationKey";
private const string InstrumentationKeyForWebSites = "APPINSIGHTS_INSTRUMENTATIONKEY";

When its not found there, it tries the regular key from the appsettings.json ApplicationInsights:InstrumentationKey.

In your example

var instrumentationKey= Configuration.GetSection("APPINSIGHTS_INSTRUMENTATIONKEY ").Value;
services.AddApplicationInsightsTelemetry(opt => opt.InstrumentationKey = instrumentationKey);

The passed value won't be used unless you both, remove the environment variable (or .AddEnvironmentVariables()) AND remove the entry from appsettings.json.

So for most common configuration, its enough to call

services.AddApplicationInsightsTelemetry(Configuration);

where Configuration is the IConfigurationRoot. This overload will load it from either Environment Variable or from appsettings.json if found.

When you want more programmatic control over it, you use the

services.AddApplicationInsightsTelemetry(options => {
    // some logic here, where you can override the default behavior described above
});