为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
蝴蝶不菲 2022-01-15 16:53:38
我们正在寻找一种跨多个 API 请求 HOOK a Request-Id(或 a Correlation-Id)的方法,如下图所示:这个想法是通过我们的日志中的多个 API 使用一个 id 来跟踪特定请求。我们使用ILogger的是 .NET Core 2.1 开箱即用的标准。到目前为止我们所做的尝试我们已尝试Request-Id在请求标头中使用,该标头已成功记录,但我们无法检索该值以将其添加到随后对其他 API 的 HTTP 请求中。我们注意到还有一个CorrelationId被记录的。但是,我们无法弄清楚如何更新它。此外,我们注意到有TraceIdentity可能HttpContextAccessor解决我们的目的。但是,我们不知道如何利用它来解决我们的问题。我们不能使用 Application Insights,而是希望依赖我们自己的日志记录基础架构框架。我们在文档中找不到任何东西。是否有任何开箱即用的解决方案可供我们使用,而无需提出我们自己的定制解决方案?
查看完整描述

3 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

我在 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

{

    private static readonly AsyncLocal<string> CorrelationId = new AsyncLocal<string>();


    public static void SetCorrelationId(string correlationId)

    {

        if (string.IsNullOrWhiteSpace(correlationId))

        {

            throw new ArgumentException(nameof(correlationId), "Correlation id cannot be null or empty");

        }


        if (!string.IsNullOrWhiteSpace(CorrelationId.Value))

        {

            throw new InvalidOperationException("Correlation id is already set");

        }


        CorrelationId.Value = correlationId;

    }


    public static string GetCorrelationId()

    {

        return CorrelationId.Value;

    }

}

用于 CorrelationMiddleware.cs


public class CorrelationMiddleware

{

    private readonly RequestDelegate _next;


    public CorrelationMiddleware(RequestDelegate next)

    {

        _next = next;

    }


    public async Task Invoke(HttpContext context)

    {

        context.Request.Headers.TryGetValue("Correlation-Id-Header", out var correlationIds);


        var correlationId = correlationIds.FirstOrDefault() ?? Guid.NewGuid().ToString();


        CorrelationContext.SetCorrelationId(correlationId);


        using (LogContext.PushProperty("Correlation-Id", correlationId))

        {

            await _next.Invoke(context);

        }

    }

}

如果我们CorrelationId稍后需要在代码中的任何地方访问 in,那么我们只需调用:CorrelationContext.GetCorrelationId();


查看完整回答
反对 回复 2022-01-15
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

我一直在使用 Serilog 登录 dotnet core 并一直在使用中间件推送 LogContext 属性-


相关中间件.cs


    public class CorrelationMiddleware

    {

    readonly RequestDelegate _next;


    public CorrelationMiddleware(RequestDelegate next)

    {

        _next = next;

    }


    public async Task Invoke(HttpContext context)

    {

        context.Request.Headers.TryGetValue(Headers.Correlation, out StringValues correlationId);


        using (LogContext.PushProperty("Correlation-Id", correlationId.FirstOrDefault()))

        {

            await _next.Invoke(context);

        }

    }

}

在您的 Startup.cs 配置方法中注册它:


app.UseMiddleware<CorrelationLogger>();

然后,在进行出站 http 调用时 - 您可以通过添加向 HttpRequestMessage 添加标头


request.Headers.Add(Headers.Correlation, GetHeader("Correlation-Id"));

在搜索日志时,我们可以通过相关 ID 进行搜索并查看所有 API 之间的完整端到端...


查看完整回答
反对 回复 2022-01-15
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

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


查看完整回答
反对 回复 2022-01-15
  • 3 回答
  • 0 关注
  • 474 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号