A journey with Application Insights

Recently I have been trying to enable Application Insights (AI) on my simple SPARQL query UI on ASP.NET Core 2.1, with reference to quick-start guide on Microsoft Docs. After completing the configuation and trying out the website locally, I believe everyting worked fine. Though the SLA guarantees the delay of telemetries should be under 2 hours, actually I can see the requests in my development environment on Azure dashboard in less than 10 minutes.

Then I decided to move the instrumentation key into a separate application configuration file named appsettings._private.json, which would be excluded when submitting my files onto GitHub. What I was intending to move is the following part of appsettings._private.json:

  "ApplicationInsights": {
    "InstrumentationKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"	// AI instrumentation key.
  },

Though exposing your instrumentation key is actually not rather dangerous, you may still take the risk of receiving spoofed telemetries from the public. Thus I added a secret appsettings file into my .gitignore list; this is how the whole ordeal begins.

I want a non-default appsettings.json path

At first, I even hadn’t noticed anything fishy; until I deployed the website on VM. After asking Gray Wing about which cats belong to ThunderClan, I waited for half an hour, only to see there are no more requests shown on AI dashboard. Then I noticed the local development instance emitting the following traces to the Output window:

Application Insights Telemetry (unconfigured): ...

Wow. So I removed the whole ApplicationInsights node from appsettings._private.json. Guess what?

Nothing changes. Then I put the node back into appsettings.json, just like what the installation wizard has done. Then I saw the output indicated AI works!

Application Insights Telemetry (unconfigured): ...

So that’s wierd. I used the following code to load my extra appsettings file:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args)
                .Build()
                .Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration(config => config.AddJsonFile("appsettings._private.json"))
                .UseApplicationInsights()
                .UseStartup<Startup>();
    }

Looking back at the situation, I have a bad feeling about this.

After digging in the source code of AI for a while, I found the following snippet is to blame


Apparently, AI loads configuration from nothing other than appsettings.json and appsettings.{Environment}.json.This class is used in the source code of ApplicationInsightsExtensions.AddApplicationInsightsTelemetry, and lead to the current situation.

Just as I’m about to submit a new issue about this situation, I was thinking “what about now?” The most important thing is, I need to figure out how to get this work, again. Then, just beside  the extension method that had brought me trouble, I found an extension method that brought me hope:

public static IServiceCollection AddApplicationInsightsTelemetry(this IServiceCollection services,
    IConfiguration configuration)

Thats it! I can use this method in my Startup.ConfigureServicesmethod.

services.AddApplicationInsightsTelemetry(Configuration);

The Configuration here is the configuration fed to the whole application, having loaded all the configuration files it is supposed to.

Voila! It works. I can deploy it to the VM now.

A Ubuntu problem

Then it just works. I can see my requests from the dashboard now. FYI, with the advent of GDPR, all the IP Address field of the requests are zeroed out by AI to conform the new rules, while the geographical information is kept. You may choose to record the IP in a custom field with telemetry initializer, at your own risk.

Aside from the requests, however, there is another trace

AI: Local storage access has resulted in an error (User: cpdn-user) (CustomFolder: ). If you want Application Insights SDK to store telemetry locally on disk in case of transient network issues please give the process access to %LOCALAPPDATA% or %TEMP% folder. If application is running in non-windows platform, create StorageFolder yourself, and set ServerTelemetryChannel.StorageFolder to the custom folder name. After you gave access to the folder you need to restart the process. Currently monitoring will continue but if telemetry cannot be sent it will be dropped. Error message: .

I don’t want to lose telemetry. So I followed the instruction, created a new folder, and used the following code to telling AI about it

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    var aiStorageFolder = Configuration.GetValue<string>("ApplicationInsightsStorageFolder", null);
    if (aiStorageFolder != null)
    {
        // For Linux OS
        services.AddSingleton<ITelemetryChannel>(new ServerTelemetryChannel {StorageFolder = aiStorageFolder});
    }
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    services.Configure<RdfQueryServiceOptions>(Configuration.GetSection("RdfQueryService"));
    services.AddSingleton<RdfQueryService>();
}

About why this happens, I found aspnetcore#551 may answer your question. Basically, it’s about the inability of .NET Core BCL to chmod on Linux, to ensure the security of the storage directory…

Well, it also reminds me of the inability of .NET Core BCL to follow symlinks. Agh.

As a kind reminder: there is already a NuGet package that can follow symlinks on Windows. But no luck from Linux up till now.

Don’t mention Mono.Posix.NETStandard. It’s waaaaay to heavy.

Leave a Reply

Your email address will not be published. Required fields are marked *

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Content is available under CC BY-SA 3.0 unless otherwise noted.