【问题标题】:Adding request headers to Application Insights telemetry for Nancy application将请求标头添加到 Nancy 应用程序的 Application Insights 遥测
【发布时间】:2018-08-14 14:09:09
【问题描述】:

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

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

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

我的第二次尝试是将 NancyModule 传递给将请求标头添加到 ITelemetryContext 的静态函数,但随后我无法获取当前的 ITelemetryContext。

有其他人遇到并解决过这个问题吗?

【问题讨论】:

    标签: c# asp.net-core nancy azure-application-insights telemetry


    【解决方案1】:

    其实.NET Framework有一个例子:https://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/including-headers-for-request-events-with-application-insights/

    在 .NET Core 中,您只需使用 IHttpContextAccessor 而不是 HttpContext.Current 访问 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】:

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

      方法是方法: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 模块内部?

      【讨论】:

      • 没有设法以这种方式获取 RequestTelemetry。可能是因为我的项目是 AspNetCore,它使用 Microsoft.AspNetCore.Http.HttpContext 而不是 System.Web.HttpContext?
      • 对我来说最好的答案 asp net (net 452)
      【解决方案3】:

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

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

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

      我在ITelemetryInitializer 中设置了RequestVariables.RequestTelemetry 的值

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

      然后我在Startup.Configure(...) 方法中注册了一个小型中间件,它获取ITelemetryInitializer 设置的RequestTelemetry 实例并将请求标头添加到其中。

      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();
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 2020-08-02
        • 1970-01-01
        • 2020-01-08
        • 1970-01-01
        • 1970-01-01
        • 2017-03-01
        相关资源
        最近更新 更多