代码之家  ›  专栏  ›  技术社区  ›  OriginalUtter

将请求头添加到Application Insights telemetry for Nancy应用程序

  •  1
  • OriginalUtter  · 技术社区  · 7 年前

    我想在Application Insights中的请求事件中包含标题,并找到了以下帖子,其中包含了一个针对具有HttpContext的应用程序的解决方案。我正在使用一个Nancy应用程序,其中请求头存储在NancyContext中。问题是Nancy并没有提供像HttpContext这样的静态访问器。所以我想知道如何解决它。

    我两次尝试都没有成功。第一个是构建一个ITelemetryInitializer,如下面的链接所述,但我无法访问NancyContext。

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

    我的第二次尝试是将NancyModule传递给一个静态函数,该函数将请求头添加到ITelemetryContext中,但是我无法获得当前的ITelemetryContext。

    还有其他人面临并解决过这个问题吗?

    3 回复  |  直到 7 年前
        1
  •  7
  •   Liero    7 年前

    实际上,有一个例子。NET框架: https://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/including-headers-for-request-events-with-application-insights/

    在里面NET核心,您只需使用IHttpContextAccessor而不是HttpContext来访问HttpContext。当前:

    public class TelemetryHeadersInitializer : ITelemetryInitializer
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public List<string> RequestHeaders { get; set; }
        public List<string> ResponseHeaders { get; set; }
    
        public TelemetryHeadersInitializer(IHttpContextAccessor httpContextAccessor)
        {
            RequestHeaders = new List<string> { "Referer" }; //whatever you need
            ResponseHeaders = new List<string> { ... };
            _httpContextAccessor = httpContextAccessor;
        }
    
        public void Initialize(ITelemetry telemetry)
        {
            var requestTelemetry = telemetry as RequestTelemetry;
            // Is this a TrackRequest() ?
            if (requestTelemetry == null) return;
    
            var context = _httpContextAccessor.HttpContext;
            if (context == null) return;
    
            foreach (var headerName in RequestHeaders)
            {
                var headers = context.Request.Headers[headerName];
                if (headers.Any())
                {
                    telemetry.Context.Properties.Add($"Request-{headerName}", string.Join(Environment.NewLine, headers));
                }             
            }
            foreach (var headerName in ResponseHeaders)
            {
                var headers = context.Response.Headers[headerName];
                if (headers.Any())
                {
                    telemetry.Context.Properties.Add($"Response-{headerName}", string.Join(Environment.NewLine, headers));
                }
            }
        }
    }
    
    //Services.cs:
    services.AddSingleton<ITelemetryInitializer, TelemetryHeadersInitializer>();
    

    同时检查: https://github.com/Microsoft/ApplicationInsights-aspnetcore/wiki/Custom-Configuration

        2
  •  1
  •   John Gardner    7 年前

    您的第二种方法应该可以工作,并且您可以使用现有的扩展方法来获取当前的请求遥测(如果有)。

    方法为方法: HttpContextExtension.GetRequestTelemetry ( https://github.com/Microsoft/ApplicationInsights-dotnet-server/blob/2a681f5399a6aaee554fa2d93a1d6447a8402fe1/Src/Web/Web.Shared.Net/HttpContextExtension.cs#L16 )

    这将返回给定HttpContext的当前请求遥测,因此您应该能够执行以下操作:

     var requestTelemetry = HttpContext.Current?.GetRequestTelemetry();
     // add whatever you need to the request telemetry?
    

    从你的Nancy模块内部?

        3
  •  1
  •   OriginalUtter    7 年前

    我找到了一个解决方案,可能不是最漂亮的,但至少它似乎有效。

    我创建了一个静态可访问的 AsyncLocal 实例来保存每个线程的RequestTelemetry对象。

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

    我设置的值为 RequestVariables.RequestTelemetry ITelemetryInitializer

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

    然后,我在 Startup.Configure(...) 获取 RequestTelemetry 实例设置的 ITelemetryInitializer 并向其中添加请求头。

    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();
    });
    
    推荐文章