.NET Core - 将带有 Request-Id 的传入请求与出站 HTTP 请求挂钩

我们正在寻找一种跨多个 API 请求 HOOK a Request-Id(或 a Correlation-Id)的方法,如下图所示:

http://img2.mukewang.com/61e28ba800017ba712100395.jpg

这个想法是通过我们的日志中的多个 API 使用一个 id 来跟踪特定请求。我们使用ILogger的是 .NET Core 2.1 开箱即用的标准。

到目前为止我们所做的尝试

  • 我们已尝试Request-Id在请求标头中使用,该标头已成功记录,但我们无法检索该值以将其添加到随后对其他 API 的 HTTP 请求中。

  • 我们注意到还有一个CorrelationId被记录的。但是,我们无法弄清楚如何更新它。

  • 此外,我们注意到有TraceIdentity可能HttpContextAccessor解决我们的目的。但是,我们不知道如何利用它来解决我们的问题。

我们不能使用 Application Insights,而是希望依赖我们自己的日志记录基础架构框架。我们在文档中找不到任何东西。

是否有任何开箱即用的解决方案可供我们使用,而无需提出我们自己的定制解决方案?


蝴蝶不菲
浏览 475回答 3
3回答

月关宝盒

我在 Twitter 上向@davidfowl 提出了同样的问题。他已回复:不,没有什么开箱即用的。有一个端到端的应用程序洞察力,但它不是很充实。您可能会考虑跨团队使用相同的中间件。如果在 3.0 中有一个工作项来解决这个问题https://github.com/aspnet/Hosting/issues/1350因此,目前看来,定制中间件是唯一的出路。这可能会随着未来的版本而改变。更新我们最终按照@DavidMcEleney 的建议创建了一个自定义中间件。然而,在它之上我们添加了CorrelationId一个AsyncLocal属性。这有助于我们在CorrelationId需要时访问代码中的任何位置。这是代码获取/设置CorrelationId:using System;using System.Threading;public static class CorrelationContext{&nbsp; &nbsp; private static readonly AsyncLocal<string> CorrelationId = new AsyncLocal<string>();&nbsp; &nbsp; public static void SetCorrelationId(string correlationId)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (string.IsNullOrWhiteSpace(correlationId))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ArgumentException(nameof(correlationId), "Correlation id cannot be null or empty");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (!string.IsNullOrWhiteSpace(CorrelationId.Value))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new InvalidOperationException("Correlation id is already set");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; CorrelationId.Value = correlationId;&nbsp; &nbsp; }&nbsp; &nbsp; public static string GetCorrelationId()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return CorrelationId.Value;&nbsp; &nbsp; }}用于 CorrelationMiddleware.cspublic class CorrelationMiddleware{&nbsp; &nbsp; private readonly RequestDelegate _next;&nbsp; &nbsp; public CorrelationMiddleware(RequestDelegate next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _next = next;&nbsp; &nbsp; }&nbsp; &nbsp; public async Task Invoke(HttpContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; context.Request.Headers.TryGetValue("Correlation-Id-Header", out var correlationIds);&nbsp; &nbsp; &nbsp; &nbsp; var correlationId = correlationIds.FirstOrDefault() ?? Guid.NewGuid().ToString();&nbsp; &nbsp; &nbsp; &nbsp; CorrelationContext.SetCorrelationId(correlationId);&nbsp; &nbsp; &nbsp; &nbsp; using (LogContext.PushProperty("Correlation-Id", correlationId))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _next.Invoke(context);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}如果我们CorrelationId稍后需要在代码中的任何地方访问 in,那么我们只需调用:CorrelationContext.GetCorrelationId();

有只小跳蛙

我一直在使用 Serilog 登录 dotnet core 并一直在使用中间件推送 LogContext 属性-相关中间件.cs&nbsp; &nbsp; public class CorrelationMiddleware&nbsp; &nbsp; {&nbsp; &nbsp; readonly RequestDelegate _next;&nbsp; &nbsp; public CorrelationMiddleware(RequestDelegate next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _next = next;&nbsp; &nbsp; }&nbsp; &nbsp; public async Task Invoke(HttpContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; context.Request.Headers.TryGetValue(Headers.Correlation, out StringValues correlationId);&nbsp; &nbsp; &nbsp; &nbsp; using (LogContext.PushProperty("Correlation-Id", correlationId.FirstOrDefault()))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _next.Invoke(context);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}在您的 Startup.cs 配置方法中注册它:app.UseMiddleware<CorrelationLogger>();然后,在进行出站 http 调用时 - 您可以通过添加向 HttpRequestMessage 添加标头request.Headers.Add(Headers.Correlation, GetHeader("Correlation-Id"));在搜索日志时,我们可以通过相关 ID 进行搜索并查看所有 API 之间的完整端到端...

Cats萌萌

不确定,如果这直接相关,但我们在 Service Fabric 项目中跨 api 和服务关联请求时面临同样的问题。我们最终从 CallContext(在 System.Runtime.Remoting.Messaging 内部)设置和获取了相关性 ID。巧合的是刚刚在这里写了一些关于它的东西。请看看这是否有帮助。
打开App,查看更多内容
随时随地看视频慕课网APP