Edit

Share via


Application Insights for ASP.NET and ASP.NET Core applications

Caution

We recommend the Azure Monitor OpenTelemetry Distro for new applications or customers to power Azure Monitor Application Insights. The Azure Monitor OpenTelemetry Distro delivers a similar functionality and experience as the Application Insights SDK. It's possible to migrate from the Application Insights SDK using the migration guides for .NET, Node.js, and Python, but we are still working to add a few more features for backwards compatibility.

This article explains how to enable and configure Application Insights for ASP.NET and ASP.NET Core applications to send telemetry. Application Insights can collect the following telemetry from your apps:

  • Requests
  • Dependencies
  • Exceptions
  • Performance counters
  • Traces (Logs)
  • Heartbeats
  • Custom events & metrics (requires manual instrumentation)
  • Page views (requires JavaScript SDK for webpages)
  • Availability tests (requires manually setting up availability tests)

Supported scenarios

Note

The Application Insights SDK for ASP.NET Core can monitor your applications no matter where or how they run. If your application is running and has network connectivity to Azure, telemetry can be collected. Application Insights monitoring is supported everywhere .NET Core is supported.

Supported ASP.NET ASP.NET Core
Operating system Windows Windows, Linux, or macOS
Hosting method In-process (IIS or IIS Express) In process or out of process
Deployment method Web Deploy, MSI, or manual file copy Framework dependent or self-contained
Web server Internet Information Services (IIS) Internet Information Server (IIS) or Kestrel
Hosting platform Azure App Service (Windows), Azure Virtual Machines, or on-premises servers The Web Apps feature of Azure App Service, Azure Virtual Machines, Docker, and Azure Kubernetes Service (AKS)
.NET version .NET Framework 4.6.1 and later All officially supported .NET versions that aren't in preview
IDE Visual Studio Visual Studio, Visual Studio Code, or command line

Add Application Insights

Prerequisites

Create a basic web app

If you don't have a functioning web application yet, you can use the following guidance to create one.

Note

We use an MVC application example. If you're using the Worker Service, use the instructions in Application Insights for Worker Service applications.

  1. Open Visual Studio.
  2. Select Create a new project.
  3. Choose ASP.NET Web Application (.NET Framework) with C# and select Next.
  4. Enter a Project name, then select Create.
  5. Choose MVC, then select Create.

Add Application Insights automatically (Visual Studio)

This section guides you through automatically adding Application Insights to a template-based web app.

From within your ASP.NET web app project in Visual Studio:

  1. Select Project > Add Application Insights Telemetry > Application Insights Sdk (local) > Next > Finish > Close.

  2. Open the ApplicationInsights.config file.

  3. Before the closing </ApplicationInsights> tag, add a line that contains the connection string for your Application Insights resource. Find your connection string on the overview pane of the newly created Application Insights resource.

    <ConnectionString>Copy connection string from Application Insights Resource Overview</ConnectionString>
    
  4. Select Project > Manage NuGet Packages > Updates. Then update each Microsoft.ApplicationInsights NuGet package to the latest stable release.

  5. Run your application by selecting IIS Express. A basic ASP.NET app opens. As you browse through the pages on the site, telemetry is sent to Application Insights.

Add Application Insights manually (no Visual Studio)

This section guides you through manually adding Application Insights to a template-based web app.

  1. Add the following NuGet packages and their dependencies to your project:

  2. In some cases, the ApplicationInsights.config file is created for you automatically. If the file is already present, skip to step 4.

    Create it yourself if it's missing. In the root directory of an ASP.NET application, create a new file called ApplicationInsights.config.

  3. Copy the following XML configuration into your newly created file:


    Expand to view the configuration
    <?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>Azure.Messaging.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>
            <!--
              Adjust the include and exclude examples to specify the desired semicolon-delimited types. (Dependency, Event, Exception, PageView, Request, Trace)
            -->
          </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
      -->
      <ConnectionString>Copy the connection string from your Application Insights resource</ConnectionString>
    </ApplicationInsights>
    
  4. Add the connection string, which can be done in two ways:

    • (Recommended) Set the connection string in configuration.

      Before the closing </ApplicationInsights> tag in ApplicationInsights.config, add the connection string for your Application Insights resource. You can find your connection string on the overview pane of the newly created Application Insights resource.

      <ConnectionString>Copy the connection string from your Application Insights resource</ConnectionString>
      
    • Set the connection string in code.

      Provide a connection string in your program.cs class.

      var configuration = new TelemetryConfiguration
      {
          ConnectionString = "Copy the connection string from your Application Insights resource"
      };
      
  5. At the same level of your project as the ApplicationInsights.config file, create a folder called ErrorHandler with a new C# file called AiHandleErrorAttribute.cs. The contents of the file look like this:

    using System;
    using System.Web.Mvc;
    using Microsoft.ApplicationInsights;
    
    namespace WebApplication10.ErrorHandler //namespace will vary based on your project name
    {
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
        public class AiHandleErrorAttribute : HandleErrorAttribute
        {
            public override void OnException(ExceptionContext filterContext)
            {
                if (filterContext != null && filterContext.HttpContext != null && filterContext.Exception != null)
                {
                    //If customError is Off, then AI HTTPModule will report the exception
                    if (filterContext.HttpContext.IsCustomErrorEnabled)
                    {   
                        var ai = new TelemetryClient();
                        ai.TrackException(filterContext.Exception);
                    } 
                }
                base.OnException(filterContext);
            }
        }
    }
    
  6. In the App_Start folder, open the FilterConfig.cs file and change it to match the sample:

    using System.Web;
    using System.Web.Mvc;
    
    namespace WebApplication10 //Namespace will vary based on project name
    {
        public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new ErrorHandler.AiHandleErrorAttribute());
            }
        }
    }
    
  7. If Web.config is already updated, skip this step. Otherwise, update the file as follows:


    Expand to view the configuration
    <?xml version="1.0" encoding="utf-8"?>
    <!--
      For more information on how to configure your ASP.NET application, please visit
      https://go.microsoft.com/fwlink/?LinkId=301880
      -->
    <configuration>
      <appSettings>
        <add key="webpages:Version" value="3.0.0.0" />
        <add key="webpages:Enabled" value="false" />
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.7.2" />
        <httpRuntime targetFramework="4.7.2" />
        <!-- Code added for Application Insights start -->
        <httpModules>
          <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
        </httpModules>
        <!-- Code added for Application Insights end -->
      </system.web>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" />
            <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
            <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
          </dependentAssembly>
          <!-- Code added for Application Insights start -->
          <dependentAssembly>
            <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
          </dependentAssembly>
          <!-- Code added for Application Insights end -->
        </assemblyBinding>
      </runtime>
      <system.codedom>
        <compilers>
          <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
          <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
        </compilers>
      </system.codedom>
      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <!-- Code added for Application Insights start -->
        <modules>
          <remove name="TelemetryCorrelationHttpModule" />
          <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="managedHandler" />
          <remove name="ApplicationInsightsWebTracking" />
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
        </modules>
        <!-- Code added for Application Insights end -->
      </system.webServer>
    </configuration>
    

At this point, you successfully configured server-side application monitoring. If you run your web app, you see telemetry begin to appear in Application Insights.

Verify Application Insights receives telemetry

Run your application and make requests to it. Telemetry should now flow to Application Insights. The Application Insights SDK automatically collects incoming web requests to your application, along with the following telemetry.

Explore your telemetry

In this section

Live metrics

Live metrics can be used to quickly verify if application monitoring with Application Insights is configured correctly. Telemetry can take a few minutes to appear in the Azure portal, but the live metrics pane shows CPU usage of the running process in near real time. It can also show other telemetry like requests, dependencies, and traces.

Note

Live metrics are enabled by default when you onboard it by using the recommended instructions for .NET applications.

Enable live metrics by using code for any .NET application

To manually configure live metrics:

  1. Install the NuGet package Microsoft.ApplicationInsights.PerfCounterCollector.

  2. The following sample console app code shows setting up live metrics:

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
using System;
using System.Threading.Tasks;

namespace LiveMetricsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a TelemetryConfiguration instance.
            TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();
            config.InstrumentationKey = "INSTRUMENTATION-KEY-HERE";
            QuickPulseTelemetryProcessor quickPulseProcessor = null;
            config.DefaultTelemetrySink.TelemetryProcessorChainBuilder
                .Use((next) =>
                {
                    quickPulseProcessor = new QuickPulseTelemetryProcessor(next);
                    return quickPulseProcessor;
                })
                .Build();

            var quickPulseModule = new QuickPulseTelemetryModule();

            // Secure the control channel.
            // This is optional, but recommended.
            quickPulseModule.AuthenticationApiKey = "YOUR-API-KEY-HERE";
            quickPulseModule.Initialize(config);
            quickPulseModule.RegisterTelemetryProcessor(quickPulseProcessor);

            // Create a TelemetryClient instance. It is important
            // to use the same TelemetryConfiguration here as the one
            // used to set up live metrics.
            TelemetryClient client = new TelemetryClient(config);

            // This sample runs indefinitely. Replace with actual application logic.
            while (true)
            {
                // Send dependency and request telemetry.
                // These will be shown in live metrics.
                // CPU/Memory Performance counter is also shown
                // automatically without any additional steps.
                client.TrackDependency("My dependency", "target", "http://sample",
                    DateTimeOffset.Now, TimeSpan.FromMilliseconds(300), true);
                client.TrackRequest("My Request", DateTimeOffset.Now,
                    TimeSpan.FromMilliseconds(230), "200", true);
                Task.Delay(1000).Wait();
            }
        }
    }
}

Traces (logs)

Application Insights captures logs from ASP.NET Core and other .NET apps through ILogger, and from classic ASP.NET (.NET Framework) through the classic SDK and adapters.

Tip

Note

To review frequently asked questions (FAQ), see Logging with .NET FAQ.

ILogger guidance doesn’t apply to ASP.NET. To send trace logs from classic ASP.NET apps to Application Insights, use supported adapters such as:

  • System.Diagnostics.Trace with Application Insights TraceListener
  • log4net or NLog with official Application Insights targets

For detailed steps and configuration examples, see Send trace logs to Application Insights.

Console application

To add Application Insights logging to console applications, first install the following NuGet packages:

The following example uses the Microsoft.Extensions.Logging.ApplicationInsights package and demonstrates the default behavior for a console application. The Microsoft.Extensions.Logging.ApplicationInsights package should be used in a console application or whenever you want a bare minimum implementation of Application Insights without the full feature set such as metrics, distributed tracing, sampling, and telemetry initializers.

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

using var channel = new InMemoryChannel();

try
{
    IServiceCollection services = new ServiceCollection();
    services.Configure<TelemetryConfiguration>(config => config.TelemetryChannel = channel);
    services.AddLogging(builder =>
    {
        // Only Application Insights is registered as a logger provider
        builder.AddApplicationInsights(
            configureTelemetryConfiguration: (config) => config.ConnectionString = "<YourConnectionString>",
            configureApplicationInsightsLoggerOptions: (options) => { }
        );
    });

    IServiceProvider serviceProvider = services.BuildServiceProvider();
    ILogger<Program> logger = serviceProvider.GetRequiredService<ILogger<Program>>();

    logger.LogInformation("Logger is working...");
}
finally
{
    // Explicitly call Flush() followed by Delay, as required in console apps.
    // This ensures that even if the application terminates, telemetry is sent to the back end.
    channel.Flush();

    await Task.Delay(TimeSpan.FromMilliseconds(1000));
}

For more information, see What Application Insights telemetry type is produced from ILogger logs? Where can I see ILogger logs in Application Insights?.

Logging scopes

Note

The following guidance applies to ILogger scenarios (ASP.NET Core and console only). It doesn’t apply to classic ASP.NET.

ApplicationInsightsLoggingProvider supports log scopes, which are enabled by default.

If the scope is of type IReadOnlyCollection<KeyValuePair<string,object>>, then each key/value pair in the collection is added to the Application Insights telemetry as custom properties. In the following example, logs are captured as TraceTelemetry and have ("MyKey", "MyValue") in properties.

using (_logger.BeginScope(new Dictionary<string, object> { ["MyKey"] = "MyValue" }))
{
    _logger.LogError("An example of an Error level message");
}

If any other type is used as a scope, it gets stored under the property Scope in Application Insights telemetry. In the following example, TraceTelemetry has a property called Scope that contains the scope.

using (_logger.BeginScope("hello scope"))
{
    _logger.LogError("An example of an Error level message");
}

Find your logs

ILogger logs appear as trace telemetry (table traces in Application Insights and AppTraces in Log Analytics).

Example

In the Azure portal, go to Application Insights and run:

traces
| where severityLevel >= 2 // 2=Warning, 1=Information, 0=Verbose
| take 50

Dependencies

Automatically tracked dependencies

Application Insights SDKs for .NET and .NET Core ship with DependencyTrackingTelemetryModule, which is a telemetry module that automatically collects dependencies. The module DependencyTrackingTelemetryModule is shipped as the Microsoft.ApplicationInsights.DependencyCollector NuGet package and brought automatically when you use either the Microsoft.ApplicationInsights.Web NuGet package or the Microsoft.ApplicationInsights.AspNetCore NuGet package.

Currently, DependencyTrackingTelemetryModule tracks the following dependencies automatically:

Dependencies Details
HTTP/HTTPS Local or remote HTTP/HTTPS calls.
WCF calls Only tracked automatically if HTTP-based bindings are used.
SQL Calls made with SqlClient. See the section Advanced SQL tracking to get full SQL query for capturing SQL queries.
Azure Blob Storage, Table Storage, or Queue Storage Calls made with the Azure Storage client.
Azure Event Hubs client SDK Use the latest package: https://nuget.org/packages/Azure.Messaging.EventHubs.
Azure Service Bus client SDK Use the latest package: https://nuget.org/packages/Azure.Messaging.ServiceBus.
Azure Cosmos DB Tracked automatically if HTTP/HTTPS is used. Tracing for operations in direct mode with TCP are captured automatically using preview package >= 3.33.0-preview. For more details, visit the documentation.

If the dependency isn't autocollected, you can track it manually with a track dependency call.

For more information about how dependency tracking works, see Dependency tracking in Application Insights.

Set up automatic dependency tracking in console apps

To automatically track dependencies from .NET console apps, install the NuGet package Microsoft.ApplicationInsights.DependencyCollector and initialize DependencyTrackingTelemetryModule:

    DependencyTrackingTelemetryModule depModule = new DependencyTrackingTelemetryModule();
    depModule.Initialize(TelemetryConfiguration.Active);

Manually tracking dependencies

The following examples of dependencies, which aren't automatically collected, require manual tracking:

  • Azure Cosmos DB is tracked automatically only if HTTP/HTTPS is used. TCP mode isn't automatically captured by Application Insights for SDK versions older than 2.22.0-Beta1.
  • Redis

For those dependencies not automatically collected by SDK, you can track them manually by using the TrackDependency API that's used by the standard autocollection modules.

Example

If you build your code with an assembly that you didn't write yourself, you could time all the calls to it. This scenario would allow you to find out what contribution it makes to your response times.

To have this data displayed in the dependency charts in Application Insights, send it by using TrackDependency:


    var startTime = DateTime.UtcNow;
    var timer = System.Diagnostics.Stopwatch.StartNew();
    try
    {
        // making dependency call
        success = dependency.Call();
    }
    finally
    {
        timer.Stop();
        telemetryClient.TrackDependency("myDependencyType", "myDependencyCall", "myDependencyData", startTime, timer.Elapsed, success);
    }

Alternatively, TelemetryClient provides the extension methods StartOperation and StopOperation, which can be used to manually track dependencies as shown in Outgoing dependencies tracking.

Disabling the standard dependency tracking module

For more information, see telemetry modules.


Advanced SQL tracking to get full SQL query

For SQL calls, the name of the server and database is always collected and stored as the name of the collected DependencyTelemetry. Another field, called data, can contain the full SQL query text.

Note

Azure Functions requires separate settings to enable SQL text collection. For more information, see Enable SQL query collection.

For ASP.NET applications, the full SQL query text is collected with the help of byte code instrumentation, which requires using the instrumentation engine or by using the Microsoft.Data.SqlClient NuGet package instead of the System.Data.SqlClient library. Platform-specific steps to enable full SQL Query collection are described in the following table.

Platform Steps needed to get full SQL query
Web Apps in Azure App Service In your web app control panel, open the Application Insights pane and enable SQL Commands under .NET.
IIS Server (Azure Virtual Machines, on-premises, and so on) Either use the Microsoft.Data.SqlClient NuGet package or use the Application Insights Agent PowerShell Module to install the instrumentation engine and restart IIS.
Azure Cloud Services Add a startup task to install StatusMonitor.
Your app should be onboarded to the ApplicationInsights SDK at build time by installing NuGet packages for ASP.NET or ASP.NET Core applications.
IIS Express Use the Microsoft.Data.SqlClient NuGet package.
WebJobs in Azure App Service Use the Microsoft.Data.SqlClient NuGet package.

In addition to the preceding platform-specific steps, you must also explicitly opt in to enable SQL command collection by modifying the applicationInsights.config file with the following code:

<TelemetryModules>
  <Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
    <EnableSqlCommandTextInstrumentation>true</EnableSqlCommandTextInstrumentation>
  </Add>

In the preceding cases, the proper way of validating that the instrumentation engine is correctly installed is by validating that the SDK version of collected DependencyTelemetry is rddp. Use of rdddsd or rddf indicates dependencies are collected via DiagnosticSource or EventSource callbacks, so the full SQL query isn't captured.

Exceptions

Exceptions in web applications can be reported with Application Insights. You can correlate failed requests with exceptions and other events on both the client and server so that you can quickly diagnose the causes. In this section, you learn how to set up exception reporting, report exceptions explicitly, diagnose failures, and more.

Set up exception reporting

You can set up Application Insights to report exceptions that occur in either the server or the client. Depending on the platform your application is dependent on, you need the appropriate extension or SDK.

To have exceptions reported from your server-side application, consider the following scenarios:

Important

This section is focused on .NET Framework apps from a code example perspective. Some of the methods that work for .NET Framework are obsolete in the .NET Core SDK.

Diagnose failures and exceptions

Application Insights comes with a curated Application Performance Management experience to help you diagnose failures in your monitored applications.

For detailed instructions, see Investigate failures, performance, and transactions with Application Insights.

Custom tracing and log data

To get diagnostic data specific to your app, you can insert code to send your own telemetry data. Your custom telemetry or log data is displayed in diagnostic search alongside the request, page view, and other automatically collected data.

Using the Microsoft.VisualStudio.ApplicationInsights.TelemetryClient, you have several APIs available:

To see these events, on the left menu, open Search. Select the dropdown menu Event types, and then choose Custom Event, Trace, or Exception.

Screenshot that shows the Search screen.

Note

If your app generates large amounts of telemetry, the adaptive sampling module automatically reduces the volume sent to the portal by sending only a representative fraction of events. Events that are part of the same operation are selected or deselected as a group so that you can navigate between related events. For more information, see Sampling in Application Insights.

See request POST data

Request details don't include the data sent to your app in a POST call. To have this data reported:

By default, not all exceptions that cause failures in your app appear in the portal. If you use the JavaScript SDK in your webpages, you see browser exceptions. However, most server-side exceptions are intercepted by IIS, so you need to add some code to capture and report them.

You can:

  • Log exceptions explicitly by inserting code in exception handlers to report the exceptions.
  • Capture exceptions automatically by configuring your ASP.NET framework. The necessary additions are different for different types of framework.
Report exceptions explicitly

The simplest way to report is to insert a call to trackException() in an exception handler.

var telemetry = new TelemetryClient();

try
{
    // ...
}
catch (Exception ex)
{
    var properties = new Dictionary<string, string>
    {
        ["Game"] = currentGame.Name
    };

    var measurements = new Dictionary<string, double>
    {
        ["Users"] = currentGame.Users.Count
    };

    // Send the exception telemetry:
    telemetry.TrackException(ex, properties, measurements);
}

The properties and measurements parameters are optional, but they're useful for filtering and adding extra information. For example, if you have an app that can run several games, you could find all the exception reports related to a particular game. You can add as many items as you want to each dictionary.

Browser exceptions

Most browser exceptions are reported.

If your webpage includes script files from content delivery networks or other domains, ensure your script tag has the attribute crossorigin="anonymous" and that the server sends CORS headers. This behavior allows you to get a stack trace and detail for unhandled JavaScript exceptions from these resources.

Reuse your telemetry client

Note

We recommend that you instantiate the TelemetryClient once and reuse it throughout the life of an application.

With Dependency Injection (DI) in .NET, the appropriate .NET SDK, and correctly configuring Application Insights for DI, you can require the TelemetryClient as a constructor parameter.

public class ExampleController : ApiController
{
    private readonly TelemetryClient _telemetryClient;

    public ExampleController(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient;
    }
}

In the preceding example, the TelemetryClient is injected into the ExampleController class.

Web forms

For web forms, the HTTP Module is able to collect the exceptions when there are no redirects configured with CustomErrors. However, when you have active redirects, add the following lines to the Application_Error function in Global.asax.cs.

void Application_Error(object sender, EventArgs e)
{
    if (HttpContext.Current.IsCustomErrorEnabled &&
        Server.GetLastError () != null)
    {
        _telemetryClient.TrackException(Server.GetLastError());
    }
}

In the preceding example, the _telemetryClient is a class-scoped variable of type TelemetryClient.

MVC

Starting with Application Insights Web SDK version 2.6 (beta 3 and later), Application Insights collects unhandled exceptions thrown in the MVC 5+ controllers methods automatically. If you previously added a custom handler to track such exceptions, you can remove it to prevent double tracking of exceptions.

There are several scenarios when an exception filter can't correctly handle errors when exceptions are thrown:

  • From controller constructors
  • From message handlers
  • During routing
  • During response content serialization
  • During application start-up
  • In background tasks

All exceptions handled by application still need to be tracked manually. Unhandled exceptions originating from controllers typically result in a 500 "Internal Server Error" response. If such response is manually constructed as a result of a handled exception, or no exception at all, it's tracked in corresponding request telemetry with ResultCode 500. However, the Application Insights SDK is unable to track a corresponding exception.

Prior versions support

If you use MVC 4 (and prior) of Application Insights Web SDK 2.5 (and prior), refer to the following examples to track exceptions.


Expand to view instructions for prior versions

If the CustomErrors configuration is Off, exceptions are available for the HTTP Module to collect. However, if it's set to RemoteOnly (default) or On, the exception is cleared and not available for Application Insights to automatically collect. You can fix that behavior by overriding the System.Web.Mvc.HandleErrorAttribute class and applying the overridden class as shown for the different MVC versions here (see the GitHub source):

using System;
using System.Web.Mvc;
using Microsoft.ApplicationInsights;

namespace MVC2App.Controllers
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AiHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (filterContext != null && filterContext.HttpContext != null && filterContext.Exception != null)
            {
                //The attribute should track exceptions only when CustomErrors setting is On
                //if CustomErrors is Off, exceptions will be caught by AI HTTP Module
                if (filterContext.HttpContext.IsCustomErrorEnabled)
                {   //Or reuse instance (recommended!). See note above.
                    var ai = new TelemetryClient();
                    ai.TrackException(filterContext.Exception);
                }
            }
            base.OnException(filterContext);
        }
    }
}

MVC 2

Replace the HandleError attribute with your new attribute in your controllers:

    namespace MVC2App.Controllers
    {
        [AiHandleError]
        public class HomeController : Controller
        {
            // Omitted for brevity
        }
    }

Sample

MVC 3

Register AiHandleErrorAttribute as a global filter in Global.asax.cs:

public class MyMvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AiHandleErrorAttribute());
    }
}

Sample

MVC 4, MVC 5

Register AiHandleErrorAttribute as a global filter in FilterConfig.cs:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // Default replaced with the override to track unhandled exceptions
        filters.Add(new AiHandleErrorAttribute());
    }
}

Sample

Web API

Starting with Application Insights Web SDK version 2.6 (beta 3 and later), Application Insights collects unhandled exceptions thrown in the controller methods automatically for Web API 2+. If you previously added a custom handler to track such exceptions, as described in the following examples, you can remove it to prevent double tracking of exceptions.

There are several cases that the exception filters can't handle. For example:

  • Exceptions thrown from controller constructors.
  • Exceptions thrown from message handlers.
  • Exceptions thrown during routing.
  • Exceptions thrown during response content serialization.
  • Exception thrown during application startup.
  • Exception thrown in background tasks.

All exceptions handled by application still need to be tracked manually. Unhandled exceptions originating from controllers typically result in a 500 "Internal Server Error" response. If such a response is manually constructed as a result of a handled exception, or no exception at all, it's tracked in a corresponding request telemetry with ResultCode 500. However, the Application Insights SDK can't track a corresponding exception.

Prior versions support

If you use Web API 1 (and earlier) of Application Insights Web SDK 2.5 (and earlier), refer to the following examples to track exceptions.


Expand to view instructions for prior versions

Web API 1.x

Override System.Web.Http.Filters.ExceptionFilterAttribute:

using System.Web.Http.Filters;
using Microsoft.ApplicationInsights;

namespace WebAPI.App_Start
{
    public class AiExceptionFilterAttribute : ExceptionFilterAttribute
    {
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext != null && actionExecutedContext.Exception != null)
        {  //Or reuse instance (recommended!). See note above.
            var ai = new TelemetryClient();
            ai.TrackException(actionExecutedContext.Exception);
        }
        base.OnException(actionExecutedContext);
    }
    }
}

You could add this overridden attribute to specific controllers, or add it to the global filter configuration in the WebApiConfig class:

using System.Web.Http;
using WebApi1.x.App_Start;

namespace WebApi1.x
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });
    
            // ...
            config.EnableSystemDiagnosticsTracing();
    
            // Capture exceptions for Application Insights:
            config.Filters.Add(new AiExceptionFilterAttribute());
        }
    }
}

Sample

Web API 2.x

Add an implementation of IExceptionLogger:

using System.Web.Http.ExceptionHandling;
using Microsoft.ApplicationInsights;

namespace ProductsAppPureWebAPI.App_Start
{
    public class AiExceptionLogger : ExceptionLogger
    {
        public override void Log(ExceptionLoggerContext context)
        {
            if (context != null && context.Exception != null)
            {
                //or reuse instance (recommended!). see note above
                var ai = new TelemetryClient();
                ai.TrackException(context.Exception);
            }
            base.Log(context);
        }
    }
}

Add this snippet to the services in WebApiConfig:

using System.Web.Http;
using System.Web.Http.ExceptionHandling;
using ProductsAppPureWebAPI.App_Start;

namespace WebApi2WithMVC
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

            config.Services.Add(typeof(IExceptionLogger), new AiExceptionLogger());
        }
    }
}

Sample

As alternatives, you could:

  • Replace the only ExceptionHandler instance with a custom implementation of IExceptionHandler. This exception handler is only called when the framework is still able to choose which response message to send, not when the connection is aborted, for instance.
  • Use exception filters, as described in the preceding section on Web API 1.x controllers, which aren't called in all cases.

WCF

Add a class that extends Attribute and implements IErrorHandler and IServiceBehavior.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    using System.Web;
    using Microsoft.ApplicationInsights;

    namespace WcfService4.ErrorHandling
    {
      public class AiLogExceptionAttribute : Attribute, IErrorHandler, IServiceBehavior
      {
        public void AddBindingParameters(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase,
            System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)
            {
                disp.ErrorHandlers.Add(this);
            }
        }

        public void Validate(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        bool IErrorHandler.HandleError(Exception error)
        {//or reuse instance (recommended!). see note above
            var ai = new TelemetryClient();

            ai.TrackException(error);
            return false;
        }

        void IErrorHandler.ProvideFault(Exception error,
            System.ServiceModel.Channels.MessageVersion version,
            ref System.ServiceModel.Channels.Message fault)
        {
        }
      }
    }

Add the attribute to the service implementations:

namespace WcfService4
{
    [AiLogException]
    public class Service1 : IService1
    {
        // Omitted for brevity
    }
}

Sample

Exception performance counters

If you installed the Azure Monitor Application Insights Agent on your server, you can get a chart of the exceptions rate measured by .NET. Both handled and unhandled .NET exceptions are included.

Open a metrics explorer tab and add a new chart. Under Performance Counters, select Exception rate.

The .NET Framework calculates the rate by counting the number of exceptions in an interval and dividing by the length of the interval.

This count is different from the Exceptions count calculated by the Application Insights portal counting TrackException reports. The sampling intervals are different, and the SDK doesn't send TrackException reports for all handled and unhandled exceptions.

Custom metric collection

The Azure Monitor Application Insights .NET and .NET Core SDKs have two different methods of collecting custom metrics:

  • The TrackMetric() method, which lacks preaggregation.
  • The GetMetric() method, which has preaggregation.

We recommend using aggregation, so TrackMetric() is no longer the preferred method of collecting custom metrics. This article walks you through using the GetMetric() method and some of the rationale behind how it works.


Expand to learn more about preaggregating vs. non-preaggregating API

The TrackMetric() method sends raw telemetry denoting a metric. It's inefficient to send a single telemetry item for each value. The TrackMetric() method is also inefficient in terms of performance because every TrackMetric(item) goes through the full SDK pipeline of telemetry initializers and processors.

Unlike TrackMetric(), GetMetric() handles local preaggregation for you and then only submits an aggregated summary metric at a fixed interval of one minute. If you need to closely monitor some custom metric at the second or even millisecond level, you can do so while only incurring the storage and network traffic cost of only monitoring every minute. This behavior also greatly reduces the risk of throttling occurring because the total number of telemetry items that need to be sent for an aggregated metric are greatly reduced.

In Application Insights, custom metrics collected via TrackMetric() and GetMetric() aren't subject to sampling. Sampling important metrics can lead to scenarios where alerts built around those metrics become unreliable. By never sampling your custom metrics, you can generally be confident that when your alert thresholds are breached, an alert fires. Because custom metrics aren't sampled, there are some potential concerns.

Trend tracking in a metric every second, or at an even more granular interval, can result in:

  • Increased data storage costs. There's a cost associated with how much data you send to Azure Monitor. The more data you send, the greater the overall cost of monitoring.
  • Increased network traffic or performance overhead. In some scenarios, this overhead could have both a monetary and application performance cost.
  • Risk of ingestion throttling. Azure Monitor drops ("throttles") data points when your app sends a high rate of telemetry in a short time interval.

Throttling is a concern because it can lead to missed alerts. The condition to trigger an alert could occur locally and then be dropped at the ingestion endpoint because of too much data being sent. We don't recommend using TrackMetric() for .NET and .NET Core unless you implemented your own local aggregation logic. If you're trying to track every instance an event occurs over a given time period, you might find that TrackEvent() is a better fit. Keep in mind that unlike custom metrics, custom events are subject to sampling. You can still use TrackMetric() even without writing your own local preaggregation. But if you do so, be aware of the pitfalls.

In summary, we recommend GetMetric() because it does preaggregation, it accumulates values from all the Track() calls, and sends a summary/aggregate once every minute. The GetMetric() method can significantly reduce the cost and performance overhead by sending fewer data points while still collecting all relevant information.

Get started with GetMetric

For our examples, we're going to use a basic .NET Core 3.1 worker service application. If you want to replicate the test environment used with these examples, follow steps 1-6 in the Monitoring worker service article. These steps add Application Insights to a basic worker service project template. The concepts apply to any general application where the SDK can be used, including web apps and console apps.

Send metrics

Replace the contents of your worker.cs file with the following code:

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights;

namespace WorkerService3
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private TelemetryClient _telemetryClient;

        public Worker(ILogger<Worker> logger, TelemetryClient tc)
        {
            _logger = logger;
            _telemetryClient = tc;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {   // The following line demonstrates usages of GetMetric API.
            // Here "computersSold", a custom metric name, is being tracked with a value of 42 every second.
            while (!stoppingToken.IsCancellationRequested)
            {
                _telemetryClient.GetMetric("ComputersSold").TrackValue(42);

                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

When you run the sample code, you see the while loop repeatedly executing with no telemetry being sent in the Visual Studio output window. A single telemetry item is sent around the 60-second mark, which in our test looks like:

Application Insights Telemetry: {"name":"Microsoft.ApplicationInsights.Dev.00000000-0000-0000-0000-000000000000.Metric", "time":"2019-12-28T00:54:19.0000000Z",
"ikey":"00000000-0000-0000-0000-000000000000",
"tags":{"ai.application.ver":"1.0.0.0",
"ai.cloud.roleInstance":"Test-Computer-Name",
"ai.internal.sdkVersion":"m-agg2c:2.12.0-21496",
"ai.internal.nodeName":"Test-Computer-Name"},
"data":{"baseType":"MetricData",
"baseData":{"ver":2,"metrics":[{"name":"ComputersSold",
"kind":"Aggregation",
"value":1722,
"count":41,
"min":42,
"max":42,
"stdDev":0}],
"properties":{"_MS.AggregationIntervalMs":"42000",
"DeveloperMode":"true"}}}}

This single telemetry item represents an aggregate of 41 distinct metric measurements. Because we were sending the same value over and over again, we have a standard deviation (stDev) of 0 with identical maximum (max) and minimum (min) values. The value property represents a sum of all the individual values that were aggregated.

Note

The GetMetric method doesn't support tracking the last value (for example, gauge) or tracking histograms or distributions.

If we examine our Application Insights resource in the Logs (Analytics) experience, the individual telemetry item would look like the following screenshot.

Screenshot that shows the Log Analytics query view.

Note

While the raw telemetry item didn't contain an explicit sum property/field once ingested, we create one for you. In this case, both the value and valueSum property represent the same thing.

You can also access your custom metric telemetry in the Metrics section of the portal as both a log-based and custom metric. The following screenshot is an example of a log-based metric.

Screenshot that shows the Metrics explorer view.

Cache metric reference for high-throughput usage

Metric values might be observed frequently in some cases. For example, a high-throughput service that processes 500 requests per second might want to emit 20 telemetry metrics for each request. The result means tracking 10,000 values per second. In such high-throughput scenarios, users might need to help the SDK by avoiding some lookups.

For example, the preceding example performed a lookup for a handle for the metric ComputersSold and then tracked an observed value of 42. Instead, the handle might be cached for multiple track invocations:

//...

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // This is where the cache is stored to handle faster lookup
            Metric computersSold = _telemetryClient.GetMetric("ComputersSold");
            while (!stoppingToken.IsCancellationRequested)
            {

                computersSold.TrackValue(42);

                computersSold.TrackValue(142);

                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(50, stoppingToken);
            }
        }

In addition to caching the metric handle, the preceding example also reduced Task.Delay to 50 milliseconds so that the loop would execute more frequently. The result is 772 TrackValue() invocations.

Multidimensional metrics

The examples in the previous section show zero-dimensional metrics. Metrics can also be multidimensional. We currently support up to 10 dimensions.

Here's an example of how to create a one-dimensional metric:

//...

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // This is an example of a metric with a single dimension.
            // FormFactor is the name of the dimension.
            Metric computersSold= _telemetryClient.GetMetric("ComputersSold", "FormFactor");

            while (!stoppingToken.IsCancellationRequested)
            {
                // The number of arguments (dimension values)
                // must match the number of dimensions specified while GetMetric.
                // Laptop, Tablet, etc are values for the dimension "FormFactor"
                computersSold.TrackValue(42, "Laptop");
                computersSold.TrackValue(20, "Tablet");
                computersSold.TrackValue(126, "Desktop");


                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(50, stoppingToken);
            }
        }

Running the sample code for at least 60-seconds results in three distinct telemetry items being sent to Azure. Each item represents the aggregation of one of the three form factors. As before, you can further examine in the Logs (Analytics) view.

Screenshot that shows the Log Analytics view of multidimensional metric.

In the metrics explorer:

Screenshot that shows Custom metrics.

Notice that you can't split the metric by your new custom dimension or view your custom dimension with the metrics view.

Screenshot that shows splitting support.

By default, multidimensional metrics within the metric explorer aren't turned on in Application Insights resources.

Enable multidimensional metrics

To enable multidimensional metrics for an Application Insights resource, select Usage and estimated costs > Custom Metrics > Enable alerting on custom metric dimensions > OK. For more information, see Custom metrics dimensions and preaggregation.

After you made that change and sent new multidimensional telemetry, you can select Apply splitting.

Note

Only newly sent metrics after the feature was turned on in the portal have dimensions stored.

Screenshot that shows applying splitting.

View your metric aggregations for each FormFactor dimension.

Screenshot that shows form factors.

Use MetricIdentifier when there are more than three dimensions

Currently, 10 dimensions are supported. More than three dimensions requires the use of MetricIdentifier:

// Add "using Microsoft.ApplicationInsights.Metrics;" to use MetricIdentifier
// MetricIdentifier id = new MetricIdentifier("[metricNamespace]","[metricId],"[dim1]","[dim2]","[dim3]","[dim4]","[dim5]");
MetricIdentifier id = new MetricIdentifier("CustomMetricNamespace","ComputerSold", "FormFactor", "GraphicsCard", "MemorySpeed", "BatteryCapacity", "StorageCapacity");
Metric computersSold  = _telemetryClient.GetMetric(id);
computersSold.TrackValue(110,"Laptop", "Nvidia", "DDR4", "39Wh", "1TB");

Custom metric configuration

If you want to alter the metric configuration, you must make alterations in the place where the metric is initialized.

Special dimension names

Metrics don't use the telemetry context of the TelemetryClient used to access them. Using special dimension names available as constants in the MetricDimensionNames class is the best workaround for this limitation.

Metric aggregates sent by the following Special Operation Request Size metric don't have Context.Operation.Name set to Special Operation. The TrackMetric() method or any other TrackXXX() method has OperationName set correctly to Special Operation.

        //...
        TelemetryClient specialClient;
        private static int GetCurrentRequestSize()
        {
            // Do stuff
            return 1100;
        }
        int requestSize = GetCurrentRequestSize()

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                //...
                specialClient.Context.Operation.Name = "Special Operation";
                specialClient.GetMetric("Special Operation Request Size").TrackValue(requestSize);
                //...
            }
                   
        }

In this circumstance, use the special dimension names listed in the MetricDimensionNames class to specify the TelemetryContext values.

For example, when the metric aggregate resulting from the next statement is sent to the Application Insights cloud endpoint, its Context.Operation.Name data field is set to Special Operation:

_telemetryClient.GetMetric("Request Size", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation");

The value of this special dimension is copied into TelemetryContext and isn't used as a normal dimension. If you want to also keep an operation dimension for normal metric exploration, you need to create a separate dimension for that purpose:

_telemetryClient.GetMetric("Request Size", "Operation Name", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation", "Special Operation");
Dimension and time-series capping

To prevent the telemetry subsystem from accidentally using up your resources, you can control the maximum number of data series per metric. The default limits are no more than 1,000 total data series per metric, and no more than 100 different values per dimension.

Important

Use low cardinal values for dimensions to avoid throttling.

In the context of dimension and time series capping, we use Metric.TrackValue(..) to make sure that the limits are observed. If the limits are already reached, Metric.TrackValue(..) returns False and the value isn't tracked. Otherwise, it returns True. This behavior is useful if the data for a metric originates from user input.

The MetricConfiguration constructor takes some options on how to manage different series within the respective metric and an object of a class implementing IMetricSeriesConfiguration that specifies aggregation behavior for each individual series of the metric:

var metConfig = new MetricConfiguration(seriesCountLimit: 100, valuesPerDimensionLimit:2,
                new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false));

Metric computersSold = _telemetryClient.GetMetric("ComputersSold", "Dimension1", "Dimension2", metConfig);

// Start tracking.
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value1");
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value2");

// The following call gives 3rd unique value for dimension2, which is above the limit of 2.
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value3");
// The above call does not track the metric, and returns false.
  • seriesCountLimit is the maximum number of data time series a metric can contain. When this limit is reached, calls to TrackValue() that would normally result in a new series return false.
  • valuesPerDimensionLimit limits the number of distinct values per dimension in a similar manner.
  • restrictToUInt32Values determines whether or not only non-negative integer values should be tracked.

Here's an example of how to send a message to know if cap limits are exceeded:

if (! computersSold.TrackValue(100, "Dim1Value1", "Dim2Value3"))
{
// Add "using Microsoft.ApplicationInsights.DataContract;" to use SeverityLevel.Error
_telemetryClient.TrackTrace("Metric value not tracked as value of one of the dimension exceeded the cap. Revisit the dimensions to ensure they are within the limits",
SeverityLevel.Error);
}

Counters in Application Insights

Application Insights supports performance counters and event counters. This guide provides an overview of both, including their purpose, configuration, and usage in .NET applications.

Overview

  • Performance counters are built into the Windows operating system and offer predefined metrics like CPU usage, memory consumption, and disk activity. These counters are ideal for monitoring standard performance metrics with minimal setup. They help track resource utilization or troubleshoot system-level bottlenecks in Windows-based applications but don't support custom application-specific metrics.

  • Event counters work across multiple platforms, including Windows, Linux, and macOS. They allow developers to define and monitor lightweight, customizable application-specific metrics, providing more flexibility than performance counters. Event counters are useful when system metrics are insufficient or when detailed telemetry is needed in cross-platform applications. They require explicit implementation and configuration, which makes setup more effort-intensive.

Performance counters

Windows provides various performance counters, such as those used to gather processor, memory, and disk usage statistics. You can also define your own performance counters.

Your application supports performance counter collection if it runs under Internet Information Server (IIS) on an on-premises host or a virtual machine with administrative access. Applications running as Azure Web Apps can't directly access performance counters, but Application Insights collects a subset of available counters.

Tip

Like other metrics, you can set an alert to warn if a counter goes outside a specified limit. To set an alert, open the Alerts pane and select Add Alert.

Prerequisites

Grant the app pool service account permission to monitor performance counters by adding it to the Performance Monitor Users group.

net localgroup "Performance Monitor Users" /add "IIS APPPOOL\NameOfYourPool"

View counters

The Metrics pane shows the default set of performance counters.

Default counters for ASP.NET web applications:

  • % Process\Processor Time
  • % Process\Processor Time Normalized
  • Memory\Available Bytes
  • ASP.NET Requests/Sec
  • .NET Common Language Runtime (CLR) Exceptions Thrown / sec
  • ASP.NET ApplicationsRequest Execution Time
  • Process\Private Bytes
  • Process\IO Data Bytes/sec
  • ASP.NET Applications\Requests In Application Queue
  • Processor(_Total)\% Processor Time

Add counters

If the performance counter you want isn't included in the list of metrics, you can add it.

Option 1: Configuration in ApplicationInsights.config

  1. Find out what counters are available in your server by using this PowerShell command on the local server:

    Get-Counter -ListSet *
    

    For more information, see Get-Counter.

  2. Open ApplicationInsights.config.

    If you added Application Insights to your app during development:

    1. Edit ApplicationInsights.config in your project.
    2. Redeploy it to your servers.
  3. Edit the performance collector directive:

    
        <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
          <Counters>
            <Add PerformanceCounter="\Objects\Processes"/>
            <Add PerformanceCounter="\Sales(photo)\# Items Sold" ReportAs="Photo sales"/>
          </Counters>
        </Add>
    

You capture both standard counters and counters you implement yourself. \Objects\Processes is an example of a standard counter that's available on all Windows systems. \Sales(photo)\# Items Sold is an example of a custom counter that might be implemented in a web service.

The format is \Category(instance)\Counter, or for categories that don't have instances, just \Category\Counter.

The ReportAs parameter is required for counter names that don't match [a-zA-Z()/-_ \.]+.

If you specify an instance, it becomes a dimension CounterInstanceName of the reported metric.

Option 2: Configuration in code

See the following section.

Collect performance counters in code for ASP.NET web applications or .NET/.NET Core console applications

To collect system performance counters and send them to Application Insights, you can adapt the following snippet:

    var perfCollectorModule = new PerformanceCollectorModule();
    perfCollectorModule.Counters.Add(new PerformanceCounterCollectionRequest(
      @"\Process([replace-with-application-process-name])\Page Faults/sec", "PageFaultsPerfSec"));
    perfCollectorModule.Initialize(TelemetryConfiguration.Active);

Or you can do the same thing with custom metrics that you created:

    var perfCollectorModule = new PerformanceCollectorModule();
    perfCollectorModule.Counters.Add(new PerformanceCounterCollectionRequest(
      @"\Sales(photo)\# Items Sold", "Photo sales"));
    perfCollectorModule.Initialize(TelemetryConfiguration.Active);

Performance counters for applications running in Azure Web Apps and Windows containers on Azure App Service

Both ASP.NET and ASP.NET Core applications deployed to Azure Web Apps run in a special sandbox environment. Applications deployed to Azure App Service can utilize a Windows container or be hosted in a sandbox environment. If the application is deployed in a Windows container, all standard performance counters are available in the container image.

The sandbox environment doesn't allow direct access to system performance counters. However, a limited subset of counters is exposed as environment variables as described in Perf Counters exposed as environment variables. Only a subset of counters is available in this environment. For the full list, see Perf Counters exposed as environment variables.

The Application Insights SDK for ASP.NET and ASP.NET Core detects if code is deployed to a web app or a non-Windows container. The detection determines whether it collects performance counters in a sandbox environment or utilizes the standard collection mechanism when hosted on a Windows container or virtual machine.

Log Analytics queries for performance counters

You can search and display performance counter reports in Log Analytics.

The performanceCounters schema exposes the category, counter name, and instance name of each performance counter. In the telemetry for each application, you see only the counters for that application. For example, to see what counters are available:

performanceCounters | summarize count(), avg(value) by category, instance, counter

Here, Instance refers to the performance counter instance, not the role, or server machine instance. The performance counter instance name typically segments counters, such as processor time, by the name of the process or application.

To get a chart of available memory over the recent period:

performanceCounters | where counter == "Available Bytes" | summarize avg(value), min(value) by bin(timestamp, 1h) | render timechart

Like other telemetry, performanceCounters also has a column cloud_RoleInstance that indicates the identity of the host server instance on which your app is running. For example, to compare the performance of your app on the different machines:

performanceCounters | where counter == "% Processor Time" and instance == "SendMetrics" | summarize avg(value) by cloud_RoleInstance, bin(timestamp, 1d)

Performance counters FAQ

To review frequently asked questions (FAQ), see Performance counters FAQ.

Event counters

EventCounter is .NET/.NET Core mechanism to publish and consume counters or statistics. EventCounters are supported in all OS platforms - Windows, Linux, and macOS. It can be thought of as a cross-platform equivalent for the PerformanceCounters that is only supported in Windows systems.

While users can publish any custom event counters to meet their needs, .NET publishes a set of these counters by default. This document walks through the steps required to collect and view event counters (system defined or user defined) in Azure Application Insights.

Tip

Like other metrics, you can set an alert to warn if a counter goes outside a specified limit. To set an alert, open the Alerts pane and select Add Alert.

Using Application Insights to collect EventCounters

Application Insights supports collecting EventCounters with its EventCounterCollectionModule, which is part of the newly released NuGet package Microsoft.ApplicationInsights.EventCounterCollector. EventCounterCollectionModule is automatically enabled when using either AspNetCore or WorkerService. EventCounterCollectionModule collects counters with a nonconfigurable collection frequency of 60 seconds. There are no special permissions required to collect EventCounters. For ASP.NET Core applications, you also want to add the Microsoft.ApplicationInsights.AspNetCore package.

dotnet add package Microsoft.ApplicationInsights.EventCounterCollector
dotnet add package Microsoft.ApplicationInsights.AspNetCore

Default counters collected

Starting with 2.15.0 version of either AspNetCore SDK or WorkerService SDK, no counters are collected by default. The module itself is enabled, so users can add the desired counters to collect them.

To get a list of well known counters published by the .NET Runtime, see Available Counters document.

Customizing counters to be collected

The following example shows how to add/remove counters. This customization would be done as part of your application service configuration after Application Insights telemetry collection is enabled using either AddApplicationInsightsTelemetry() or AddApplicationInsightsWorkerService(). Following is an example code from an ASP.NET Core application. For other type of applications, refer to this document.

using Microsoft.ApplicationInsights.Extensibility.EventCounterCollector;
using Microsoft.Extensions.DependencyInjection;

builder.Services.ConfigureTelemetryModule<EventCounterCollectionModule>(
        (module, o) =>
        {
            // Removes all default counters, if any.
            module.Counters.Clear();

            // Adds a user defined counter "MyCounter" from EventSource named "MyEventSource"
            module.Counters.Add(
                new EventCounterCollectionRequest("MyEventSource", "MyCounter"));

            // Adds the system counter "gen-0-size" from "System.Runtime"
            module.Counters.Add(
                new EventCounterCollectionRequest("System.Runtime", "gen-0-size"));
        }
    );

Disabling EventCounter collection module

EventCounterCollectionModule can be disabled by using ApplicationInsightsServiceOptions.

The following example uses the ASP.NET Core SDK.

using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.Extensions.DependencyInjection;

var applicationInsightsServiceOptions = new ApplicationInsightsServiceOptions();
applicationInsightsServiceOptions.EnableEventCounterCollectionModule = false;
builder.Services.AddApplicationInsightsTelemetry(applicationInsightsServiceOptions);

A similar approach can be used for the WorkerService SDK as well, but the namespace must be changed as shown in the following example.

using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.Extensions.DependencyInjection;

var applicationInsightsServiceOptions = new ApplicationInsightsServiceOptions();
applicationInsightsServiceOptions.EnableEventCounterCollectionModule = false;
builder.Services.AddApplicationInsightsTelemetry(applicationInsightsServiceOptions);

Log Analytics queries for event counters

You can search and display event counter reports in Log Analytics, in the customMetrics table.

For example, run the following query to see what counters are collected and available to query:

customMetrics | summarize avg(value) by name

To get a chart of a specific counter (for example: ThreadPool Completed Work Item Count) over the recent period, run the following query.

customMetrics 
| where name contains "System.Runtime|ThreadPool Completed Work Item Count"
| where timestamp >= ago(1h)
| summarize  avg(value) by cloud_RoleInstance, bin(timestamp, 1m)
| render timechart

Like other telemetry, customMetrics also has a column cloud_RoleInstance that indicates the identity of the host server instance on which your app is running. The prior query shows the counter value per instance, and can be used to compare performance of different server instances.

Event counters FAQ

To review frequently asked questions (FAQ), see Event counters FAQ.

Configure the Application Insights SDK

In this section

You can customize the Application Insights SDK for ASP.NET and ASP.NET Core to change the default configuration.

The Application Insights .NET SDK consists of many NuGet packages. The core package provides the API for sending telemetry to the Application Insights. More packages provide telemetry modules and initializers for automatically tracking telemetry from your application and its context. By adjusting the configuration file, you can enable or disable telemetry modules and initializers. You can also set parameters for some of them.

The configuration file is named ApplicationInsights.config or ApplicationInsights.xml. The name depends on the type of your application. It's automatically added to your project when you install most versions of the SDK.

By default, when you use the automated experience from the Visual Studio template projects that support Add > Application Insights Telemetry, the ApplicationInsights.config file is created in the project root folder. After compiling, it gets copied to the bin folder. It's also added to a web app by Application Insights Agent on an IIS server.

Important

The configuration file is ignored if the extension for Azure websites or the extension for Azure VMs and virtual machine scale sets is used.

There isn't an equivalent file to control the SDK in a webpage.

Telemetry channels

Telemetry channels are an integral part of the Application Insights SDKs. They manage buffering and transmission of telemetry to the Application Insights service. The .NET and .NET Core versions of the SDKs have two built-in telemetry channels: InMemoryChannel and ServerTelemetryChannel. This article describes each channel and shows how to customize channel behavior.

Note

To review frequently asked questions (FAQ), see Telemetry channels FAQ

What are telemetry channels?

Telemetry channels are responsible for buffering telemetry items and sending them to the Application Insights service, where they're stored for querying and analysis. A telemetry channel is any class that implements the Microsoft.ApplicationInsights.ITelemetryChannel interface.

The Send(ITelemetry item) method of a telemetry channel is called after all telemetry initializers and telemetry processors are called. So, any items dropped by a telemetry processor doesn't reach the channel. The Send() method doesn't ordinarily send the items to the back end instantly. Typically, it buffers them in memory and sends them in batches for efficient transmission.

Avoid calling Flush() unless it's critical to send buffered telemetry immediately. Use it only in scenarios like application shutdown, exception handling, or when using short-lived processes such as background jobs or command-line tools. In web applications or long-running services, the SDK handles telemetry sending automatically. Calling Flush() unnecessarily can cause performance problems.

Live Metrics Stream also has a custom channel that powers the live streaming of telemetry. This channel is independent of the regular telemetry channel, and this document doesn't apply to it.

Built-in telemetry channels

The Application Insights .NET and .NET Core SDKs ship with two built-in channels:

  • InMemoryChannel: A lightweight channel that buffers items in memory until they're sent. Items are buffered in memory and flushed once every 30 seconds, or whenever 500 items are buffered. This channel offers minimal reliability guarantees because it doesn't retry sending telemetry after a failure. This channel also doesn't keep items on disk. So any unsent items are lost permanently upon application shutdown, whether it's graceful or not. This channel implements a Flush() method that can be used to force-flush any in-memory telemetry items synchronously. This channel is well suited for short-running applications where a synchronous flush is ideal.

    This channel is part of the larger Microsoft.ApplicationInsights NuGet package and is the default channel that the SDK uses when nothing else is configured.

  • ServerTelemetryChannel: A more advanced channel that has retry policies and the capability to store data on a local disk. This channel retries sending telemetry if transient errors occur. This channel also uses local disk storage to keep items on disk during network outages or high telemetry volumes. Because of these retry mechanisms and local disk storage, this channel is considered more reliable. We recommend it for all production scenarios. This channel is the default for ASP.NET and ASP.NET Core applications that are configured according to the official documentation. This channel is optimized for server scenarios with long-running processes. The Flush() method that's implemented by this channel isn't synchronous.

    This channel is shipped as the Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel NuGet package and is acquired automatically when you use either the Microsoft.ApplicationInsights.Web or Microsoft.ApplicationInsights.AspNetCore NuGet package.

Configure a telemetry channel

You configure a telemetry channel by setting it to the active telemetry configuration. For ASP.NET applications, configuration involves setting the telemetry channel instance to TelemetryConfiguration.Active or by modifying ApplicationInsights.config. For ASP.NET Core applications, configuration involves adding the channel to the dependency injection container.

The following sections show examples of configuring the StorageFolder setting for the channel in various application types. StorageFolder is just one of the configurable settings. For the full list of configuration settings, see the Configurable settings in channels section later in this article.

Option 1: Configuration in code

The following code sets up a ServerTelemetryChannel instance with StorageFolder set to a custom location. Add this code at the beginning of the application, typically in the Application_Start() method in Global.aspx.cs.

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
protected void Application_Start()
{
    var serverTelemetryChannel = new ServerTelemetryChannel();
serverTelemetryChannel.StorageFolder = @"d:\temp\applicationinsights";
    serverTelemetryChannel.Initialize(TelemetryConfiguration.Active);
    TelemetryConfiguration.Active.TelemetryChannel = serverTelemetryChannel;
}

Option 2: Configuration in ApplicationInsights.config

The following section from ApplicationInsights.config shows the ServerTelemetryChannel channel configured with StorageFolder set to a custom location:

    <TelemetrySinks>
        <Add Name="default">
            <TelemetryProcessors>
                <!-- Telemetry processors omitted for brevity  -->
            </TelemetryProcessors>
            <TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel">
                <StorageFolder>d:\temp\applicationinsights</StorageFolder>
            </TelemetryChannel>
        </Add>
    </TelemetrySinks>

Configuration in code for console applications

For console apps, the code is the same for both .NET and .NET Core:

var serverTelemetryChannel = new ServerTelemetryChannel();
serverTelemetryChannel.StorageFolder = @"d:\temp\applicationinsights";
serverTelemetryChannel.Initialize(TelemetryConfiguration.Active);
TelemetryConfiguration.Active.TelemetryChannel = serverTelemetryChannel;

Operational details of ServerTelemetryChannel

ServerTelemetryChannel stores arriving items in an in-memory buffer. The items are serialized, compressed, and stored into a Transmission instance once every 30 seconds, or when 500 items are buffered. A single Transmission instance contains up to 500 items and represents a batch of telemetry that's sent over a single HTTPS call to the Application Insights service.

By default, a maximum of 10 Transmission instances can be sent in parallel. If telemetry is arriving at faster rates, or if the network or the Application Insights back end is slow, Transmission instances are stored in memory. The default capacity of this in-memory Transmission buffer is 5 MB. When the in-memory capacity is exceeded, Transmission instances are stored on local disk up to a limit of 50 MB.

Transmission instances are stored on local disk also when there are network problems. Only those items that are stored on a local disk survive an application crash. They're sent whenever the application starts again. If network issues persist, ServerTelemetryChannel uses an exponential backoff logic ranging from 10 seconds to 1 hour before retrying to send telemetry.

Configurable settings in channels

For the full list of configurable settings for each channel, see:

Here are the most commonly used settings for ServerTelemetryChannel:

  • MaxTransmissionBufferCapacity: The maximum amount of memory, in bytes, used by the channel to buffer transmissions in memory. When this capacity is reached, new items are stored directly to local disk. The default value is 5 MB. Setting a higher value leads to less disk usage, but remember that items in memory are lost if the application crashes.

  • MaxTransmissionSenderCapacity: The maximum number of Transmission instances that are sent to Application Insights at the same time. The default value is 10. This setting can be configured to a higher number, which we recommend when a huge volume of telemetry is generated. High volume typically occurs during load testing or when sampling is turned off.

  • StorageFolder: The folder that's used by the channel to store items to disk as needed. In Windows, either %LOCALAPPDATA% or %TEMP% is used if no other path is specified explicitly. In environments other than Windows, you must specify a valid location or telemetry isn't stored to local disk.

Which channel should I use?

We recommend ServerTelemetryChannel for most production scenarios that involve long-running applications. For more about flushing telemetry, read about using Flush().

When to use Flush()

The Flush() method sends any buffered telemetry immediately. However, it should only be used in specific scenarios.

Use Flush() when:

  • The application is about to shut down and you want to ensure telemetry is sent before exit.
  • You're in an exception handler and need to guarantee telemetry is delivered.
  • You're writing a short-lived process like a background job or CLI tool that exits quickly.

Avoid using Flush() in long-running applications such as web services. The SDK automatically manages buffering and transmission. Calling Flush() unnecessarily can cause performance problems and doesn't guarantee all data is sent, especially when using ServerTelemetryChannel, which doesn't flush synchronously.

Telemetry modules

Application Insights automatically collects telemetry about specific workloads without requiring manual tracking by user.

By default, the following automatic-collection modules are enabled. You can disable or configure them to alter their default behavior.

Each telemetry module collects a specific type of data and uses the core API to send the data. The modules are installed by different NuGet packages, which also add the required lines to the .config file.

Area Description
Request tracking Collects request telemetry (response time, result code) for incoming web requests.

Module: Microsoft.ApplicationInsights.Web.RequestTrackingTelemetryModule
NuGet: Microsoft.ApplicationInsights.Web
Dependency tracking Collects telemetry about outgoing dependencies (HTTP calls, SQL calls). To work in IIS, install Application Insights Agent. You can also write custom dependency tracking using TrackDependency API. Supports autoinstrumentation with App Service and VM/VMSS monitoring.

Module: Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule
NuGet: Microsoft.ApplicationInsights.DependencyCollector
Performance counters Collects Windows Performance Counters (CPU, memory, network load from IIS installs). Specify which counters (including custom ones). For more information, see Collects system performance counters.

Module: Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule
NuGet:Microsoft.ApplicationInsights.PerfCounterCollector
Event counters Collects .NET EventCounters. Recommended for ASP.NET Core and cross‑platform in place of Windows perf counters.

Module: EventCounterCollectionModule (SDK ≥ 2.8.0)
Live Metrics (QuickPulse) Collects telemetry for Live Metrics pane.

Module: QuickPulseTelemetryModule
Heartbeats (App Service) Sends heartbeats and custom metrics for App Service environment.

Module: AppServicesHeartbeatTelemetryModule
Heartbeats (VM/VMSS) Sends heartbeats and custom metrics for Azure VM environment.

Module: AzureInstanceMetadataTelemetryModule
Diagnostics telemetry Reports errors in Application Insights instrumentation code (for example, missing counters, ITelemetryInitializer exceptions). Trace telemetry appears in Diagnostic Search.

Module: Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule
NuGet: Microsoft.ApplicationInsights

Note: If you only install this package, the ApplicationInsights.config file isn't automatically created.
Developer mode (debugger attached) Forces TelemetryChannel to send items immediately when debugger is attached. Reduces latency but increases CPU/network overhead.

Module: Microsoft.ApplicationInsights.WindowsServer.DeveloperModeWithDebuggerAttachedTelemetryModule
NuGet: Application Insights Windows Server
Exception tracking (Web) Tracks unhandled exceptions in web apps. See Failures and exceptions.

Module: Microsoft.ApplicationInsights.Web.ExceptionTrackingTelemetryModule
NuGet: Microsoft.ApplicationInsights.Web
Exception tracking (Unobserved/Unhandled) Tracks unobserved task exceptions and unhandled exceptions for worker roles, Windows services, and console apps.

Modules:
 • Microsoft.ApplicationInsights.WindowsServer.UnobservedExceptionTelemetryModule
 • Microsoft.ApplicationInsights.WindowsServer.UnhandledExceptionTelemetryModule
NuGet: Microsoft.ApplicationInsights.WindowsServer
EventSource tracking Sends configured EventSource events to Application Insights as traces.

Module: Microsoft.ApplicationInsights.EventSourceListener.EventSourceTelemetryModule
NuGet: Microsoft.ApplicationInsights.EventSourceListener
ETW collector Sends configured ETW provider events to Application Insights as traces.

Module: Microsoft.ApplicationInsights.EtwCollector.EtwCollectorTelemetryModule
NuGet: Microsoft.ApplicationInsights.EtwCollector
Core API (not a module) Core API used by other telemetry components and for custom telemetry.

Module: Microsoft.ApplicationInsights package
NuGet: Microsoft.ApplicationInsights
Note: If you only install this package, the ApplicationInsights.config file isn't automatically created.

Configure telemetry modules

Use the TelemetryModules section in ApplicationInsights.config to configure, add, or remove modules. The following examples:

  • Configure DependencyTrackingTelemetryModule (enable W3C header injection).
  • Configure EventCounterCollectionModule (clear defaults and add a single counter).
  • Disable perf‑counter collection by removing PerformanceCollectorModule.
<ApplicationInsights>
  <TelemetryModules>

    <!-- Dependency tracking -->
    <Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
      <!-- Match Core example: enable W3C header injection -->
      <EnableW3CHeadersInjection>true</EnableW3CHeadersInjection>
    </Add>

    <!-- EventCounterCollectionModule: add a single counter (if you use event counters) -->
    <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.EventCounterCollectionModule, Microsoft.AI.PerfCounterCollector">
      <Counters>
        <!-- Mirrors Core example: only collect 'gen-0-size' from System.Runtime -->
        <Add ProviderName="System.Runtime" CounterName="gen-0-size" />
      </Counters>
    </Add>

    <!-- PerformanceCollectorModule (classic Windows performance counters).
         To DISABLE perf-counter collection, do NOT include this module.
         If it already exists in your file, remove or comment it out.
         Example of the line you would remove:
    <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector" />
    -->

  </TelemetryModules>
</ApplicationInsights>

Note

The exact set of modules present in your ApplicationInsights.config depends on which SDK packages you installed.

Disable telemetry

There's a node in the configuration file for each module. To disable a module, delete the node or comment it out.

Telemetry initializers

To enrich telemetry with additional information or to override telemetry properties set by the standard telemetry modules, use telemetry initializers.

Telemetry initializers set context properties that are sent along with every item of telemetry.

You can write your own initializers to set context properties.

The standard initializers are all set either by the web or WindowsServer NuGet packages:

Initializer Description
AccountIdTelemetryInitializer Sets the AccountId property.
AuthenticatedUserIdTelemetryInitializer Sets the AuthenticatedUserId property as set by the JavaScript SDK.
AzureRoleEnvironmentTelemetryInitializer Updates the RoleName and RoleInstance properties of the Device context for all telemetry items with information extracted from the Azure runtime environment.
BuildInfoConfigComponentVersionTelemetryInitializer Updates the Version property of the Component context for all telemetry items with the value extracted from the BuildInfo.config file produced by MS Build.
ClientIpHeaderTelemetryInitializer Updates the Ip property of the Location context of all telemetry items based on the X-Forwarded-For HTTP header of the request.
DeviceTelemetryInitializer Updates the following properties of the Device context for all telemetry items:

Type is set to PC.
Id is set to the domain name of the computer where the web application is running.
OemName is set to the value extracted from the Win32_ComputerSystem.Manufacturer field by using WMI.
Model is set to the value extracted from the Win32_ComputerSystem.Model field by using WMI.
NetworkType is set to the value extracted from the NetworkInterface property.
Language is set to the name of the CurrentCulture property.
DomainNameRoleInstanceTelemetryInitializer Updates the RoleInstance property of the Device context for all telemetry items with the domain name of the computer where the web application is running.
OperationNameTelemetryInitializer Updates the Name property of RequestTelemetry and the Name property of the Operation context of all telemetry items based on the HTTP method, and the names of the ASP.NET MVC controller and action invoked to process the request.
OperationIdTelemetryInitializer or OperationCorrelationTelemetryInitializer Updates the Operation.Id context property of all telemetry items tracked while handling a request with the automatically generated RequestTelemetry.Id.
SessionTelemetryInitializer Updates the Id property of the Session context for all telemetry items with value extracted from the ai_session cookie generated by the ApplicationInsights JavaScript instrumentation code running in the user's browser.
SyntheticTelemetryInitializer or SyntheticUserAgentTelemetryInitializer Updates the User, Session, and Operation context properties of all telemetry items tracked when handling a request from a synthetic source, such as an availability test or search engine bot. By default, metrics explorer doesn't display synthetic telemetry.

The <Filters> set identifying properties of the requests.
UserTelemetryInitializer Updates the Id and AcquisitionDate properties of the User context for all telemetry items with values extracted from the ai_user cookie generated by the Application Insights JavaScript instrumentation code running in the user's browser.
WebTestTelemetryInitializer Sets the user ID, session ID, and synthetic source properties for HTTP requests that come from availability tests.

The <Filters> set identifying properties of the requests.

Note

For .NET applications running in Azure Service Fabric, you can include the Microsoft.ApplicationInsights.ServiceFabric NuGet package. This package includes a FabricTelemetryInitializer property, which adds Service Fabric properties to telemetry items. For more information, see the GitHub page about the properties added by this NuGet package.

To learn how to use telemetry initializers with ASP.NET applications, see Filter and preprocess telemetry in the Application Insights SDK.

Telemetry processors

Telemetry processors can filter and modify each telemetry item before it's sent from the SDK to the portal.

To learn how to use telemetry processors with ASP.NET applications, see Filter and preprocess telemetry in the Application Insights SDK.

You can write your own telemetry processors.

Adaptive sampling telemetry processor (from 2.0.0-beta3)

This functionality is enabled by default. If your app sends considerable telemetry, this processor removes some of it.


    <TelemetryProcessors>
      <Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
        <MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
      </Add>
    </TelemetryProcessors>

The parameter provides the target that the algorithm tries to achieve. Each instance of the SDK works independently. So, if your server is a cluster of several machines, the actual volume of telemetry is multiplied accordingly.

Learn more about sampling.

Fixed-rate sampling telemetry processor (from 2.0.0-beta1)

There's also a standard sampling telemetry processor (from 2.0.1):


    <TelemetryProcessors>
     <Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.SamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">

     <!-- Set a percentage close to 100/N where N is an integer. -->
     <!-- E.g. 50 (=100/2), 33.33 (=100/3), 25 (=100/4), 20, 1 (=100/100), 0.1 (=100/1000) -->
     <SamplingPercentage>10</SamplingPercentage>
     </Add>
   </TelemetryProcessors>

Connection String

This setting determines the Application Insights resource in which your data appears. Typically, you create a separate resource, with a separate connection string, for each of your applications.

See Connection strings in Application Insights for code samples.

If you want to set the connection string dynamically, for example, to send results from your application to different resources, you can omit the connection string from the configuration file and set it in code instead.

To set the connection string for all instances of TelemetryClient, including standard telemetry modules, do this step in an initialization method, such as global.aspx.cs in an ASP.NET service:

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights;

    protected void Application_Start()
    {
        TelemetryConfiguration configuration = TelemetryConfiguration.CreateDefault();
        configuration.ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000";
        var telemetryClient = new TelemetryClient(configuration);

If you want to send a specific set of events to a different resource, you can set the key for a specific telemetry client:


    var tc = new TelemetryClient();
    tc.Context.ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000";
    tc.TrackEvent("myEvent");
    // ...

To get a new connection string, create a new resource in the Application Insights portal.

ApplicationId Provider

Note

For ASP.NET, this provider is available starting in SDK v2.6.0*.

The purpose of this provider is to look up an application ID based on a connection string. The application ID is included in RequestTelemetry and DependencyTelemetry and is used to determine correlation in the portal.

This functionality is available by setting TelemetryConfiguration.ApplicationIdProvider.

Interface: IApplicationIdProvider

public interface IApplicationIdProvider
{
    bool TryGetApplicationId(string instrumentationKey, out string applicationId);
}

We provide two implementations in the Microsoft.ApplicationInsights SDK: ApplicationInsightsApplicationIdProvider and DictionaryApplicationIdProvider.

ApplicationInsightsApplicationIdProvider

This wrapper is for our Profile API. It throttles requests and cache results. This provider is automatically included when you install either Microsoft.ApplicationInsights.DependencyCollector or Microsoft.ApplicationInsights.Web.

The class exposes an optional property called ProfileQueryEndpoint. By default, it's set to https://dc.services.visualstudio.com/api/profiles/{0}/appId.

If you need to configure a proxy, we recommend proxying the base address and ensuring the path includes /api/profiles/{0}/appId. At runtime, {0} is replaced with the instrumentation key for each request.

Example configuration via ApplicationInsights.config

<ApplicationInsights>
    ...
    <ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights">
        <ProfileQueryEndpoint>https://dc.services.visualstudio.com/api/profiles/{0}/appId</ProfileQueryEndpoint>
    </ApplicationIdProvider>
    ...
</ApplicationInsights>

Example configuration via code

TelemetryConfiguration.Active.ApplicationIdProvider = new ApplicationInsightsApplicationIdProvider();

DictionaryApplicationIdProvider

This static provider relies on your configured instrumentation key/application ID pairs.

This class has the Defined property, which is a Dictionary<string,string> of instrumentation key/application ID pairs.

This class has the optional property Next, which can be used to configure another provider to use when a connection string is requested that doesn't exist in your configuration.

Example configuration via ApplicationInsights.config

<ApplicationInsights>
    ...
    <ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.DictionaryApplicationIdProvider, Microsoft.ApplicationInsights">
        <Defined>
            <Type key="InstrumentationKey_1" value="ApplicationId_1"/>
            <Type key="InstrumentationKey_2" value="ApplicationId_2"/>
        </Defined>
        <Next Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights" />
    </ApplicationIdProvider>
    ...
</ApplicationInsights>

Example configuration via code

TelemetryConfiguration.Active.ApplicationIdProvider = new DictionaryApplicationIdProvider{
 Defined = new Dictionary<string, string>
    {
        {"InstrumentationKey_1", "ApplicationId_1"},
        {"InstrumentationKey_2", "ApplicationId_2"}
    }
};

Configure snapshot collection

To learn how to configure snapshot collection for ASP.NET and ASP.NET Core applications, see Enable Snapshot Debugger for .NET apps in Azure Service Fabric, Cloud Services, and Virtual Machines.

Sampling

To learn how to configure sampling for ASP.NET and ASP.NET Core applications, see Sampling in Application Insights.

Enrich data through HTTP

var requestTelemetry = HttpContext.Current?.Items["Microsoft.ApplicationInsights.RequestTelemetry"] as RequestTelemetry;

if (requestTelemetry != null)
{
    requestTelemetry.Properties["myProp"] = "someData";
}

Add client-side monitoring

The previous sections provided guidance on methods to automatically and manually configure server-side monitoring. To add client-side monitoring, use the client-side JavaScript SDK. You can monitor any web page's client-side transactions by adding a JavaScript (Web) SDK Loader Script before the closing </head> tag of the page's HTML.

Although it's possible to manually add the JavaScript (Web) SDK Loader Script to the header of each HTML page, we recommend that you instead add the JavaScript (Web) SDK Loader Script to a primary page. That action injects the JavaScript (Web) SDK Loader Script into all pages of a site.

For the template-based ASP.NET MVC app from this article, the file that you need to edit is _Layout.cshtml. You can find it under Views > Shared. To add client-side monitoring, open _Layout.cshtml and follow the JavaScript (Web) SDK Loader Script-based setup instructions from the article about client-side JavaScript SDK configuration.

Troubleshooting

See the dedicated troubleshooting article.

There's a known issue in Visual Studio 2019: storing the instrumentation key or connection string in a user secret is broken for .NET Framework-based apps. The key ultimately has to be hardcoded into the applicationinsights.config file to work around this bug. This article is designed to avoid this issue entirely, by not using user secrets.

Test connectivity between your application host and the ingestion service

Application Insights SDKs and agents send telemetry to get ingested as REST calls to our ingestion endpoints. You can test connectivity from your web server or application host machine to the ingestion service endpoints by using raw REST clients from PowerShell or curl commands. See Troubleshoot missing application telemetry in Azure Monitor Application Insights.

Open-source SDK

Read and contribute to the code.

For the latest updates and bug fixes, consult the release notes.

Release Notes

For version 2.12 and newer: .NET Software Development Kits (SDKs) including ASP.NET, ASP.NET Core, and Logging Adapters

Our Service Updates also summarize major Application Insights improvements.

Next steps