我正在为我的端点提供一个关联ID:
然后我从HttpContext.Request.Headers中读取该ID,并将其用作我的遥测.Context.Operation.Id。
这有效,但是当我查看日志时,会有一个额外的条目,该条目由框架自动生成。该条目具有其自己的ID。如何确保框架使用相同的ID?
这是我配置服务的方式
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Users.Api.Services;
using Users.Api.Utility;
using Users.Services.Implementations;
using Users.Services.Interfaces;
using Users.Sql;
using Users.Utility;
using Packages.Api.Filters;
using Packages.Audit;
using Swashbuckle.AspNetCore.Swagger;
namespace Users.Api
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Dependency injection
services.AddAutoMapper();
services.AddDbContext<UsersContext>(
builder => builder.UseSqlServer(Environment.GetEnvironmentVariable("Connectionstring")));
services.AddScoped<IUserService, UserService>();
services.AddScoped<IIdentityService, IdentityService>();
services.AddScoped<IServiceBusCommunicator, ServiceBusCommunicator>();
services.AddScoped<IGraphClient, GraphClient>();
services.AddScoped<IClaimsHarvester, ClaimsHarvester>();
services.AddScoped<IUserRepository, UserRepository>();
services.AddSingleton<HttpClient>();
services.AddSingleton<EndpointConfiguration>();
services.AddSingleton<GraphConfiguration>();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IAuditLogClient, AuditLogClient>();
var clientId = Environment.GetEnvironmentVariable("Authentication:AzureAd:ClientId");
var tenant = Environment.GetEnvironmentVariable("Authentication:AzureAd:Tenant");
var signInPolicyId = Environment.GetEnvironmentVariable("Authentication:AzureAd:SignInPolicyId");
var authority = $"https://login.microsoftonline.com/tfp/{tenant}/{signInPolicyId}/v2.0/";
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(bearerOptions =>
{
bearerOptions.Authority = authority;
bearerOptions.Audience = clientId;
bearerOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed
};
});
services.AddMvc();
services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new Info { Title = "Users API", Version = "v1" });
});
services.ConfigureSwaggerGen(options =>
{
options.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
options.OperationFilter<CorrelationHeaderParameterOperationFilter>();
options.OperationFilter<XTotalCountHeaderParameterOperationFilter>();
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
ContextInitializer contextInitializer)
{
if (env.IsDevelopment())
{
// loggerFactory.AddConsole(Configuration.GetSection("Logging"));
// loggerFactory.AddDebug();
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(
c =>
{
c.SwaggerEndpoint($"{Environment.GetEnvironmentVariable("ServiceFabric:UniqueUrlPath")}/swagger/v1/swagger.json", "Contacts API V1");
});
// Seed default values
contextInitializer.Seed();
}
private Task AuthenticationFailed(AuthenticationFailedContext arg)
{
// For debugging purposes only!
var s = $"AuthenticationFailed: {arg.Exception.Message}";
arg.Response.ContentLength = s.Length;
arg.Response.Body.Write(Encoding.UTF8.GetBytes(s), 0, s.Length);
return Task.FromResult(0);
}
}
}
答案 0 :(得分:1)
ApplicationInsights通常不支持此功能。
您仍然可以实现它,但是必须编写一个自定义请求集合。
您需要从DI容器中删除RequestTelemetryTrackingModule,然后添加用于跟踪请求的自定义中间件。
这种方法行不通(下面的代码):
方案。您可以查看如何在AppInsights SDK(设置requestTelemetry.Source和response header)中对其进行处理
与AspNetCore发出的信息跟踪的相关性。
通常,请求遥测名称包含路径而不是路径,您可能需要弄清楚
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry("ikey");
var requestModule =
services.FirstOrDefault(sd => sd.ImplementationType == typeof(RequestTrackingTelemetryModule));
if (requestModule != null)
{
services.Remove(requestModule);
}
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, TelemetryClient client)
{
app.UseMiddleware<RequestMiddleware>(client);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
public class RequestMiddleware
{
private readonly RequestDelegate next;
private readonly TelemetryClient telemetryClient;
public RequestMiddleware(
RequestDelegate next,
TelemetryClient telemetryClient)
{
this.telemetryClient = telemetryClient;
this.next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var activity = new Activity("request");
if (context.Request.Headers.TryGetValue("x-my-correlation-id", out var val))
{
activity.SetParentId(val);
}
using (var request = telemetryClient.StartOperation<RequestTelemetry>(activity))
{
request.Telemetry.Url = context.Request.GetUri();
request.Telemetry.Context.Operation.Name = $"{context.Request.Method} {context.Request.Path.Value}";
request.Telemetry.Name = $"{context.Request.Method} {context.Request.Path.Value}";
try
{
await next.Invoke(context).ConfigureAwait(false);
}
catch (Exception e)
{
telemetryClient.TrackException(e);
request.Telemetry.Success = false;
throw;
}
finally
{
if (context.Response != null)
{
request.Telemetry.ResponseCode = context.Response.StatusCode.ToString();
request.Telemetry.Success = context.Response.StatusCode < 400;
}
else
{
request.Telemetry.Success = false;
}
}
}
}
}