我正在尝试从我们的.net核心MVC应用程序中获取一些有关应用程序见解的附加信息。我发现了以下帖子: Adding custom properties for each request in Application Insights metrics
答案中,他们使用了自定义遥测初始化程序,并且在您需要一些请求数据或其他内容时可以使用。
现在,我们的应用程序中有一组中间件。他们将某些标头转换为可读的内容。
当然,我们可以记录标题并搜索那些标题可以具有的所有不同值。但是我们希望将中间件的结果用于应用程序见解的属性。
任何人都想将中间件的某些结果用于Application Insights请求遥测的属性中?
答案 0 :(得分:2)
从@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";
}
}
}
}
然后,当您需要将所有这些项目纳入应用程序见解时,只需使用以下初始化程序即可:
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的所有值添加到您的应用程序见解中。
答案 1 :(得分:0)
无需将中间件中的数据放入 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>();