33

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

Liero
  • 25,216
  • 29
  • 151
  • 297
  • IConfiguration is not respected by `UseApplicationInsightsTelemetry()`. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/1566 and https://github.com/microsoft/ApplicationInsights-dotnet/issues/1684 . Only environment variables and appsettings.json in the app root works as expected. – shannon Feb 24 '20 at 21:15

2 Answers2

20

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
});
Community
  • 1
  • 1
Tseng
  • 61,549
  • 15
  • 193
  • 205
  • I know how asp.net core configuration builder works, but that is not what I ask. – Liero Jun 06 '18 at 13:11
  • 3
    It's the same, essentially, see [source code](https://github.com/Microsoft/ApplicationInsights-aspnetcore/blob/v2.5.0/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs#L288-L292). The extension method to register it looks in either one, when setting the options class with config overriding the environment variable value – Tseng Jun 06 '18 at 13:20
  • What I don't understand is why Azure Portal has to use different key, when `.AddEnvironmentVariables` would overwrite the value in appsettings.json, if it was the same key. Now we can easily end up with two different values being used, if we don't use `services.AddApplicationInsightsTelemetry(Configuration);` – Liero Aug 01 '18 at 08:52
  • 1
    Well AppInsights and Azure exited before ASP.NET Core i suppose :P Same applies for SQL connection strings, which use ASP.NET Core agnostic variables too. APPINSIGHTS_INSTRUMENTATIONKEY is azure way of passing the key. ASP.NET Core syntax would only apply to ASP.NET Core apps, not to other kind of apps hosted on Azure – Tseng Aug 01 '18 at 09:47
  • IConfiguration is not respected by `UseApplicationInsightsTelemetry()`. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/1566 and https://github.com/microsoft/ApplicationInsights-dotnet/issues/1684 . Only environment variables and appsettings.json in the app root works as expected. – shannon Feb 24 '20 at 21:15
2

Short answer:

APPINSIGHTS_INSTRUMENTATIONKEY in Azure Portal takes precedence over ApplicationInsights InstrumentationKey in appsettings.json.

You can use APPINSIGHTS_INSTRUMENTATIONKEY to overwrite appsettings.json's setting.

You should not have both in Azure Portal.

Rosdi Kasim
  • 24,267
  • 23
  • 130
  • 154