【问题标题】:Application Insights - Add properties from .net core middlewareApplication Insights - 从 .net 核心中间件添加属性
【发布时间】:2018-10-20 09:25:17
【问题描述】:

我正在尝试从我们的 .net 核心 MVC 应用程序中获取有关应用程序洞察力的一些额外信息。我找到了以下帖子: Adding custom properties for each request in Application Insights metrics

在答案中,他们使用自定义遥测初始化程序,如果您需要一些请求数据或其他内容,它就可以工作。

现在我们的应用程序中有一组中间件。他们将一些标题翻译成可读的内容。

当然,我们可以记录标题并搜索它们可能具有的所有不同值。但我们希望将结果从中间件转化为应用洞察的属性。

有人知道如何将中间件的某些结果用于 Application Insights 请求遥测的属性吗?

【问题讨论】:

  • 你能澄清一下中间件的结果是什么,你把结果存储在哪里?因为无法理解为什么记录结果数据是比记录头更可取的解决方案。您是否将中间件工作的结果存储在 HttpContext.Items 中?
  • 是的,所有值都存储在 HttpContext.Items 中。例如,它是一个多租户应用程序。所有租户都有多个 ApiKey。标头中是 ApiKey,但如果租户 ID 在中间件中检索并存储在 HttpContext 项中,那就太好了。
  • @svoychik 帮我解决了这个问题。通过在自定义遥测初始化程序的构造函数中添加 HttpContextAccessor,您可以访问 http 上下文和上下文的项目。 Initialize 函数被多次调用。最后,http 上下文有项目。通过这种方式,您可以将这些值添加到 Application Insights 的属性中。

标签: .net .net-core asp.net-core-mvc azure-application-insights


【解决方案1】:

从@svoychik 那里得到了正确的想法。中间件将输出值添加到 HttpContext.Items。看例子:

using Microsoft.AspNetCore.Http;
using System.Text;
using System.Threading.Tasks;

namespace Test.API.Middleware
{
    public class ValueMiddleware
    {
        private readonly RequestDelegate next;

        public ApiKeyMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            if (!context.Items.ContainsKey("ApplicationData"))
            {
                httpContext.Items["ApplicationData"] = "Important Data";
            }
        }
    }
}

然后,当您需要将所有这些项目纳入应用程序洞察力时,您只需使用以下 Initializer:

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;

namespace Test.API.TelemetryInitializers : ITelemetryInitializer
{
    public class HttpContextItemsTelemetryInitializer
    {
        private readonly IHttpContextAccessor httpContextAccessor;
        public HttpContextItemsTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            var context = httpContextAccessor.HttpContext;
            if (context == null)
            {
                return;
            }

            foreach (var item in context.Items)
            {
                var itemKey = item.Key.ToString();

                // Remove some pollution that Microsoft and the systems adds to the HttpContext Items.
                if (itemKey.Contains("Microsoft") || itemKey.Contains("System"))
                {
                    continue;
                }

                if (!telemetry.Context.GlobalProperties.ContainsKey(itemKey))
                {
                    telemetry.Context.GlobalProperties.Add(itemKey, item.Value.ToString());
                }
            }
        }
    }
}

在您的 Startup.cs 中设置初始化程序和应用程序洞察,如下例所示:

using Test.API.TelemetryInitializers;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;

namespace Test.API
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSingleton<ITelemetryInitializer, HttpContextItemsTelemetryInitializer>();
            services.AddApplicationInsightsTelemetry();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMiddleware<ValueMiddleware>();
            app.UseMvc();
        }
    }
}

然后它只是将 HttpContext.Items 的所有值添加到您的应用程序洞察力中。

【讨论】:

    【解决方案2】:

    您可以直接将所需数据添加到中间件内的遥测对象中,而不是将中间件中的数据放入 HttpContext 并运行 TelemetryInitializer

    public class TelemetryMiddleware
    {
        private const string _BodyKey = "Body";
        private readonly RequestDelegate _next;
    
        public TelemetryMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
            httpContext.Request.EnableBuffering();
    
            if (httpContext.Request.Body.CanRead
                && (httpContext.Request.Method == HttpMethods.Put
                    || httpContext.Request.Method == HttpMethods.Post
                    || httpContext.Request.Method == HttpMethods.Patch))
            {
                // The needed method to access telemetry object within middleware
                var telemetry = httpContext.Features.Get<RequestTelemetry>();
    
                if (telemetry != null
                    && !telemetry.Properties.ContainsKey(_BodyKey))
                {
                    var oldPosition = httpContext.Request.Body.Position;
                    httpContext.Request.Body.Position = 0;
    
                    using (var reader = new StreamReader(httpContext.Request.Body, Encoding.UTF8, false, 4096, true))
                    {
                        var body = await reader.ReadToEndAsync();
    
                        if (!string.IsNullOrEmpty(body))
                            telemetry.Properties.Add(_BodyKey, body);
                    }
    
                    httpContext.Request.Body.Position = oldPosition;
                }
            }
    
            await _next(httpContext);
        }
    }
    

    构建到管道中与每个中间件相同:

    app.UseMiddleware<TelemetryMiddleware>();
    

    【讨论】:

      猜你喜欢
      • 2019-04-08
      • 2017-06-16
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多