How can I best make the Application Inisghts' Instrumentation Key configurable in a way that allows an Azure Administrator to manage the settings for an App Services deployment of an MVC5 web application? Is there a certain event in an MVC application initialization where this should be done or is it okay to do it at pretty much any point? I am using the Trace Listener integration as well.
By default, the Instrumentation Key (iKey) is set in the ApplicationInsights.config
file. Additionally, if you include the JavaScript portions, the iKey is again set in the _Layout.cshtml
file. This is two different places with an iKey that you need to manage.
I want to be able to manage this key via the App Services -> Application settings tab of the Azure Portal. The reasons are:
- I want to deploy multiple instances of this applications, each with its own unique iKey
- I want to change this iKey periodically (because reasons)
- I don't want this iKey stored in our code repository (it's okay for a "dev" iKey to be in code repo) nor do I want it to be managed by our build automation (again, because reasons)
All of the methods you specified are great. Our recommendation is to use a web.config app setting and using this in the global.asax.cs for standard initialization. No telemetry will be sent before the initlization as we hook into OnBeginRequest().
https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-custom-events-metrics#a-namedynamic-ikeya-dynamic-instrumentation-key
Another method that might work well is to set the APPINSIGHTS_INSTRUMENTATIONKEY
environment variable as it's picked up by the SDK. Of course that depends on if you have multiple apps on the same machine.
https://github.com/Microsoft/ApplicationInsights-dotnet/blob/v2.2.0/src/Core/Managed/Net40/Extensibility/Implementation/TelemetryConfigurationFactory.cs#L22
Here is the implementation that I am currently using, and it seems to work. However, I had other implementations that seemed to set the iKey either too early or too late as it seemed it would use the iKey in the physical web.config
file deployed to Azure instead of pulling from the Application settings tab from the Portal. Are there better options to do this in a best practice sort of way?
ApplicationInsights.config
<!-- Find the following node and *remove* it. It will have a GUID in it.
If you leave this, you may receive some errors even with all of the
other changes. -->
<InstrumentationKey>{GUID HERE}</InstrumentationKey>
Global.asax.cs
protected void Application_Start()
{
// Add this first line below
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey =
ConfigurationManager.AppSettings["ai:InstrumentationKey"];
// Showing the rest of this so you can see the order of operations
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
AutomapperConfig.Init();
}
web.config
<!-- Add the following to <appSettings> and put your iKey value in here. -->
<add key="ai:InstrumentationKey" value="*****" />
_Layout.cshtml (in the <head>
section of the HTML. NOTE TO FUTURE READERS: I recommend you don't use this entire snippet but instead just use the line that begins instrumentationKey:
and integrate that line into whatever the modern version is for the rest of this JS snippet!):
<script type = 'text/javascript' >
var appInsights=window.appInsights||function(config)
{
function r(config){ t[config] = function(){ var i = arguments; t.queue.push(function(){ t[config].apply(t, i)})} }
var t = { config:config},u=document,e=window,o='script',s=u.createElement(o),i,f;for(s.src=config.url||'//az416426.vo.msecnd.net/scripts/a/ai.0.js',u.getElementsByTagName(o)[0].parentNode.appendChild(s),t.cookie=u.cookie,t.queue=[],i=['Event','Exception','Metric','PageView','Trace','Ajax'];i.length;)r('track'+i.pop());return r('setAuthenticatedUserContext'),r('clearAuthenticatedUserContext'),config.disableExceptionTracking||(i='onerror',r('_'+i),f=e[i],e[i]=function(config, r, u, e, o) { var s = f && f(config, r, u, e, o); return s !== !0 && t['_' + i](config, r, u, e, o),s}),t
}({
instrumentationKey:'@(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey)'
});
window.appInsights=appInsights;
appInsights.trackPageView();
</script>