Search code examples
c#asp.net-corenancyazure-application-insightstelemetry

Adding request headers to Application Insights telemetry for Nancy application


I want to include headers in the request events in Application Insights and found the following post that has a solution for application with a HttpContext. I'm working with a Nancy application where the request headers are stored in the NancyContext. Problem is that Nancy doesn't provide a static accessor like HttpContext.Current so I wonder how I can solve it.

I've made two attempts without succeeding. The first was to build an ITelemetryInitializer like described in the link below but then I could not access the NancyContext.

https://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/including-headers-for-request-events-with-application-insights/

My second attempt was to pass the NancyModule to a static function that added the request headers to the ITelemetryContext but then I could not get a hold of the current ITelemetryContext instead.

Has anyone else faced and solved this issue?


Solution

  • I found a solution, might not be the prettiest but at least it seems to work.

    I created a statically accessible AsyncLocal instance to hold the RequestTelemetry object for each thread.

    public class RequestVariables
    {
        public static AsyncLocal<RequestTelemetry> RequestTelemetry = new AsyncLocal<RequestTelemetry>();
    }
    

    I set the value of RequestVariables.RequestTelemetry in an ITelemetryInitializer

    public class RequestTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {
            if (telemetry is RequestTelemetry requestTelemetry)
                RequestVariables.RequestTelemetry.Value = requestTelemetry;
        }
    }
    

    Then I registered a small middleware in the Startup.Configure(...) method which fetches the RequestTelemetry instance that was set by the ITelemetryInitializer and adds the request headers to it.

    app.Use((context, next) =>
    {
        var requestTelemetry = RequestVariables.RequestTelemetry.Value;
        if (requestTelemetry?.Context == null) return next();
    
        foreach (var header in context.Request.Headers)
        {
            if (!requestTelemetry.Context.Properties.ContainsKey(header.Key))
                requestTelemetry.Context.Properties.Add(header.Key, header.Value.First());
        }
    
        return next();
    });