Search code examples
c#azurewcfazure-application-insights

How to configure Application Insights with instrumentation keys from multiple environments in WCF?


If I set up my WCF project with an ApplicationInsights.config file as outlined in this Microsoft documentation, and data is logged to Application Insights (using the hardcoded instrumentation key) as expected.

Is there any way to specify instrumentation keys on a per-environment basis when using the ApplicationInsights.config file?

The config file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
 <TelemetryInitializers>
   <Add Type="Microsoft.ApplicationInsights.DependencyCollector.HttpDependenciesParsingTelemetryInitializer, Microsoft.AI.DependencyCollector" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.BuildInfoConfigComponentVersionTelemetryInitializer, Microsoft.AI.WindowsServer" />
   <Add Type="Microsoft.ApplicationInsights.Web.WebTestTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.SyntheticUserAgentTelemetryInitializer, Microsoft.AI.Web">
     <!-- Extended list of bots:
           search|spider|crawl|Bot|Monitor|BrowserMob|BingPreview|PagePeeker|WebThumb|URL2PNG|ZooShot|GomezA|Google SketchUp|Read Later|KTXN|KHTE|Keynote|Pingdom|AlwaysOn|zao|borg|oegp|silk|Xenu|zeal|NING|htdig|lycos|slurp|teoma|voila|yahoo|Sogou|CiBra|Nutch|Java|JNLP|Daumoa|Genieo|ichiro|larbin|pompos|Scrapy|snappy|speedy|vortex|favicon|indexer|Riddler|scooter|scraper|scrubby|WhatWeb|WinHTTP|voyager|archiver|Icarus6j|mogimogi|Netvibes|altavista|charlotte|findlinks|Retreiver|TLSProber|WordPress|wsr-agent|http client|Python-urllib|AppEngine-Google|semanticdiscovery|facebookexternalhit|web/snippet|Google-HTTP-Java-Client-->
     <Filters>search|spider|crawl|Bot|Monitor|AlwaysOn</Filters>
   </Add>
   <Add Type="Microsoft.ApplicationInsights.Web.ClientIpHeaderTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.AzureAppServiceRoleNameFromHostNameHeaderInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.OperationNameTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.OperationCorrelationTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.UserTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.AuthenticatedUserIdTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.AccountIdTelemetryInitializer, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.SessionTelemetryInitializer, Microsoft.AI.Web" />
 </TelemetryInitializers>
 <TelemetryModules>
   <Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
     <ExcludeComponentCorrelationHttpHeadersOnDomains>
       <!-- 
       Requests to the following hostnames will not be modified by adding correlation headers.         
       Add entries here to exclude additional hostnames.
       NOTE: this configuration will be lost upon NuGet upgrade.
       -->
       <Add>core.windows.net</Add>
       <Add>core.chinacloudapi.cn</Add>
       <Add>core.cloudapi.de</Add>
       <Add>core.usgovcloudapi.net</Add>
     </ExcludeComponentCorrelationHttpHeadersOnDomains>
     <IncludeDiagnosticSourceActivities>
       <Add>Microsoft.Azure.EventHubs</Add>
       <Add>Microsoft.Azure.ServiceBus</Add>
     </IncludeDiagnosticSourceActivities>
   </Add>
   <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
     <!--
     Use the following syntax here to collect additional performance counters:

     <Counters>
       <Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
       ...
     </Counters>

     PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName

     NOTE: performance counters configuration will be lost upon NuGet upgrade.

     The following placeholders are supported as InstanceName:
       ??APP_WIN32_PROC?? - instance name of the application process  for Win32 counters.
       ??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
       ??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
     -->
   </Add>
   <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryModule, Microsoft.AI.PerfCounterCollector" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.AppServicesHeartbeatTelemetryModule, Microsoft.AI.WindowsServer" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureInstanceMetadataTelemetryModule, Microsoft.AI.WindowsServer">
     <!--
     Remove individual fields collected here by adding them to the ApplicationInsighs.HeartbeatProvider 
     with the following syntax:

     <Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights">
       <ExcludedHeartbeatProperties>
         <Add>osType</Add>
         <Add>location</Add>
         <Add>name</Add>
         <Add>offer</Add>
         <Add>platformFaultDomain</Add>
         <Add>platformUpdateDomain</Add>
         <Add>publisher</Add>
         <Add>sku</Add>
         <Add>version</Add>
         <Add>vmId</Add>
         <Add>vmSize</Add>
         <Add>subscriptionId</Add>
         <Add>resourceGroupName</Add>
         <Add>placementGroupId</Add>
         <Add>tags</Add>
         <Add>vmScaleSetName</Add>
       </ExcludedHeartbeatProperties>
     </Add>

     NOTE: exclusions will be lost upon upgrade.
     -->
   </Add>
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.DeveloperModeWithDebuggerAttachedTelemetryModule, Microsoft.AI.WindowsServer" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.UnhandledExceptionTelemetryModule, Microsoft.AI.WindowsServer" />
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.UnobservedExceptionTelemetryModule, Microsoft.AI.WindowsServer">
     <!--</Add>
   <Add Type="Microsoft.ApplicationInsights.WindowsServer.FirstChanceExceptionStatisticsTelemetryModule, Microsoft.AI.WindowsServer">-->
   </Add>
   <Add Type="Microsoft.ApplicationInsights.Web.RequestTrackingTelemetryModule, Microsoft.AI.Web">
     <Handlers>
       <!-- 
       Add entries here to filter out additional handlers: 

       NOTE: handler configuration will be lost upon NuGet upgrade.
       -->
       <Add>Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler</Add>
       <Add>System.Web.StaticFileHandler</Add>
       <Add>System.Web.Handlers.AssemblyResourceLoader</Add>
       <Add>System.Web.Optimization.BundleHandler</Add>
       <Add>System.Web.Script.Services.ScriptHandlerFactory</Add>
       <Add>System.Web.Handlers.TraceHandler</Add>
       <Add>System.Web.Services.Discovery.DiscoveryRequestHandler</Add>
       <Add>System.Web.HttpDebugHandler</Add>
     </Handlers>
   </Add>
   <Add Type="Microsoft.ApplicationInsights.Web.ExceptionTrackingTelemetryModule, Microsoft.AI.Web" />
   <Add Type="Microsoft.ApplicationInsights.Web.AspNetDiagnosticTelemetryModule, Microsoft.AI.Web" />
 </TelemetryModules>
 <ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights" />
 <TelemetrySinks>
   <Add Name="default">
     <TelemetryProcessors>
       <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryProcessor, Microsoft.AI.PerfCounterCollector" />
       <Add Type="Microsoft.ApplicationInsights.Extensibility.AutocollectedMetricsExtractor, Microsoft.ApplicationInsights" />
       <Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
         <MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
         <ExcludedTypes>Event</ExcludedTypes>
       </Add>
       <Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
         <MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
         <IncludedTypes>Event</IncludedTypes>
       </Add>
     </TelemetryProcessors>
     <TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel" />
   </Add>
 </TelemetrySinks>
 <!-- 
   Learn more about Application Insights configuration with ApplicationInsights.config here: 
   http://go.microsoft.com/fwlink/?LinkID=513840
 -->
 <InstrumentationKey>your-instrumentation-key-here</InstrumentationKey>
</ApplicationInsights>

My web.config contains the following:

<system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
    <httpModules>
      <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
    </httpModules>
  </system.web>

This documentation suggests that I can set the instrumentation key in code (such as in an AppInitialize method as suggested by this answer), but it doesn't seem to work.

TelemetryConfiguration configuration = TelemetryConfiguration.CreateDefault();
configuration.InstrumentationKey = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

Solution

  • While there appear to be some caveats to this solution (depending on your hosting strategy), it is sometimes possible to add a Global.asax, and use the Application_Start hook to inject your configuration (This answer assumes you're using config transforms).

    For example:

    using System;
    
    namespace SomeWcfThing
    {
        public class Global : System.Web.HttpApplication
        {
    
            protected void Application_Start(object sender, EventArgs e)
            {
                Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey =
                    System.Configuration.ConfigurationManager.AppSettings["InstrumentationKey"];
            }
        }
    }