Leverage Application Insights without Azure

Brief overview of Application Insights

Application Insights is Microsoft's application performance management solution for monitoring and analysing application data such as page load times, server performance counters, dependency wait times and more.

The end use case being that development teams will set up application insights on any environment and then use the Azure portal to monitor, optimise applications or anticipate problems.

Once setup, configured and deployed telemetry data is sent to an Azure endpoint to be stored and analysed. The application could be hosted in Azure or on any container or server that is running a .NET application.

The benefit to monitoring this way is that the hosting environment in theory uses minimal resource to collect and send telemetry data and in turn there is no need to provision storage and computing resources to analyse the incoming data since it is offloaded to Azure (at a cost of course).

This solution may not be feasible in all cases however, some barriers might be: 

  • Security concerns with sending data outside of the system boundary (in cases where the application is not hosted on Azure).
  • Budget requirements, unable to justify ongoing Azure resource cost.
  • Performance implications of data gathering in a production environment.

The less advertised fact is that it is still possible to leverage the Application Insights telemetry data without using Azure.

Adding Application Insights to a web project

For some project templates this may have already been done by default, if there is an ApplicationInsights.config file present then it has already been setup.

If not go to the main Project menu then Add Application Insights Telemetry. Click on Get Started, it will ask you register the app with Azure credentials but just ignore that and click on Or just add the SDK to try local only mode.

This will import the necessary packages and add in the ApplicationInsights.config file.

This needs to be done on the web project and it is also possibly to do by right clicking on the project then going to Add -> Application Insights Telemetry but this one seems to be slightly broken and it only works going via the main Project menu.

Viewing telemetry data in Visual Studio

Now when debugging the application it should be possible to view the telemetry data in Visual Studio. Go to View -> Other Windows -> Application Insights Search.

This will open up a new tab where you can inspect all the data that is being gathered. At this point the data is just being captured in memory and not stored anywhere. If you want to do some quick debugging to see what is going on locally this may be sufficient for your needs. But in some cases it may be necessary to do longer term data collection, storage and detail analysis.

Intercept telemetry data with a custom channel

One solution is to implement a CustomTelemetryChannel this may be handy for debugging a local development or if you need fine grain control over the telemetry being sent, but beyond that it is a fairly limited solution.

Create a custom channel by implementing the ITelemetryChannel interface. Within the Send method you can intercept the telemetry data and do whatever you want with it.

public class CustomTelemteryChannel : ITelemetryChannel
{
    public bool? DeveloperMode { get; set; }
    public string EndpointAddress { get; set; }
    public void Dispose() { }
    public void Flush() { }
    
    public void Send(ITelemetry item)
    {
        // Store in db, log to file, selectively send to service etc
    }
}

You can set the custom channel in the ApplicationInsights.config file but on nuget package updates this can be overwritten so I found it easier to set it up in code in Application_Start.

TelemetryConfiguration.Active.TelemetryChannel = new CustomTelemetryChannel();

Note if you want to debug on IIS Express you may also need to enable the performance counters here specifically:

var module = new PerformanceCollectorModule
{
    EnableIISExpressPerformanceCounters = true
}

module.Initialize(TelemetryConfiguration.Active);
TelemetryModules.Instance.Module.Add(module);

The downside to this solution is that you may end up putting extra load on your application or collecting telemetry about the code that is collecting the telemetry. It also does not allow you to capture any front end telemetry since the data is being gathered and sent via script needs to send to a service endpoint.

Configuring a custom endpoint

If you want to go the whole hog and roll your own data telemetry endpoint then this is also possible. By default the SDK just posts the data to an azure endpoint but this can be configured. In Application_Start:

// Configure custom endpoint assuming you have implemented one
TelemetryConfiguration.Active.TelemetryChannel.EndpointAddress = "http://somedomain/track";
// Required or no data will be sent, could be used to identify source if more than  one application use the same endpoint
TelemetryConfiguration.Active.InstrumentationKey = "dummy";

You need to use something other than localhost here and you must provide a dummy Instrumentation Key otherwise the telemetry data will not be sent. Running the code should post the telemetry data as JSON to your endpoint.

Configuring page view insights

There is a script available that can also send page view data if you want to monitor front end load times, this script block is all that is needed:

<!-- To collect end-user usage analytics about your application, 
insert the following script into each page you want to track.
Place this code immediately before the closing </head> tag,
and before any other scripts. Your first data will appear 
automatically in just a few seconds.-->

<script type="text/javascript">
var appInsights=window.appInsights||function(a){
function b(a){c[a]=function(){var b=arguments;c.queue.push(function(){c[a].apply(c,b)})}}var c={config:a},d=document,e=window;setTimeout(function(){var b=d.createElement("script");b.src=a.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js",d.getElementsByTagName("script")[0].parentNode.appendChild(b)});try{c.cookie=d.cookie}catch(a){}c.queue=[];for(var f=["Event","Exception","Metric","PageView","Trace","Dependency"];f.length;)b("track"+f.pop());if(b("setAuthenticatedUserContext"),b("clearAuthenticatedUserContext"),b("startTrackEvent"),b("stopTrackEvent"),b("startTrackPage"),b("stopTrackPage"),b("flush"),!a.disableExceptionTracking){f="onerror",b("_"+f);var g=e[f];e[f]=function(a,b,d,e,h){var i=g&&g(a,b,d,e,h);return!0!==i&&c["_"+f](a,b,d,e,h),i}}return c
} ({
        instrumentationKey:"dummy",
        endpointUrl:"http://somedomain/track" 
});

window.appInsights=appInsights,appInsights.queue&&0===appInsights.queue.length&&appInsights.trackPageView();
</script>

As before if you omit the Instrumentation Key or use a localhost endpoint then the data may not be sent. You may also need to ensure that your security content policy allows the loading of the application insights tracking script located at

https://az416426.vo.msecnd.net/scripts/a/ai.0.js