【问题标题】:System.Diagnostics.Activity is null in aspnet core 2.1System.Diagnostics.Activity 在 aspnet 核心 2.1 中为空
【发布时间】:2018-08-01 11:22:12
【问题描述】:

我们刚刚将一个 aspnet core 2.0 应用程序更新到 2.1,但在使用/依赖 System.Diagnostics.Activity 时遇到了问题。

背景

我们希望在我们的服务边界上传递一致的“相关 ID”,以便我们可以关联每个请求的日志条目。

我们采取的方法是:

  • Microsoft.AspNetCore.Hosting.HttpRequestIn.Start的中间件管道添加一个诊断侦听器

  • 调用此监听器时,检查 context.request 中是否有一个名为“Request-Id”的标头,如果没有则添加一个值为Activity.Current.Id的标头

  • 另一个中间件负责将“Request-Id”标头值推送到日志记录上下文中

这在 2.0 中运行良好,Activity.Current.Id 的分层特性意味着我们可以关联不同服务和层的日志条目。在 2.1 中,我们现在遇到了异常,因为 Activity.Current 在请求的入口点(即第一个被命中的服务,在本例中为 API)似乎总是为空。

我没有找到任何表明每当 HttpRequest 进入时不再自动启动活动的信息,但这似乎正在发生。有没有人能够阐明发生了什么变化和/或我们做错了什么?

一些代码

启动配置方法...

public void Configure(IApplicationBuilder app, IHostingEnvironment env, DiagnosticListener diagnosticListener)
        {
           diagnosticListener.SubscribeWithAdapter(new HttpRequestInDiagnosticListener());
           app.UseMiddleware<SetRequestIdHeaderForHttpRequestInMiddleware>();

            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();
            else
                app.UseStatusCodePages();

            app.UseSecurityHeaders(Headers.AddSecurityHeaders());

            app.UseMvc();
        }

...以及所涉及的自定义类

    public class HttpRequestInDiagnosticListener
    {
        [DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn.Start")]
        public virtual void OnMiddlewareStarting(HttpContext httpContext)
        {
            Console.WriteLine($"Middleware Starting, path: {httpContext.Request.Path}");
        }
    }

    public class SetRequestIdHeaderForHttpRequestInMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly DiagnosticSource _diagnostics;

        public SetRequestIdHeaderForHttpRequestInMiddleware(RequestDelegate next, DiagnosticSource diagnosticSource)
        {
            _next = next;
            _diagnostics = diagnosticSource;
        }

        public async Task Invoke(HttpContext context)
        {

            if (_diagnostics.IsEnabled("Microsoft.AspNetCore.Hosting.HttpRequestIn.Start"))
            {
                if (!context.Request.Headers.Keys.Contains("Request-Id"))
                {
                    context.Request.Headers.Add("Request-Id", Activity.Current.Id);
                }
            }

            await _next.Invoke(context);
        }
    }

【问题讨论】:

  • 如果您使用 Application Insights (SDK 2.1+),他们会设置 Activity.Current,您可以使用 Activity.Current?.Id 或 .RootId 来获取操作 ID/相关 ID

标签: c# asp.net-core .net-core


【解决方案1】:

经过几天的研究,回答我自己的问题,但简洁地说是:在 2.1 中,活动不再以与 2.0 中相同的方式开始。 https://github.com/aspnet/Hosting/blob/release/2.1/src/Microsoft.AspNetCore.Hosting/Internal/HostingApplicationDiagnostics.cs#L54-L79

要开始使用Activity,您需要专门观察Microsoft.AspNetCore.Hosting.HttpRequestIn,而问题中的代码是观察Microsoft.AspNetCore.Hosting.HttpRequestIn.Start

不幸的是,这不是 2.1 中影响问题中代码的唯一更改,并且仅更改正在观察的活动名称不会使此代码工作,因为 2.1 现在处理 Request-Id 标头和 CorrelationId 日志以自己的方式干扰此中间件代码的属性。

【讨论】:

  • 你是如何解决最后一部分的(Request-id processing in it's own way)?看起来在 .NET Core 3.0 中他们使用 Activity.Id 来生成 ProblemDetails.traceId:github.com/aspnet/AspNetCore/blob/… 并且无法覆盖它:/
  • 不幸的是我没有。我放弃了关注各种 aspnetcore 团队关于拥有可以跨越服务边界的跟踪/关联/请求 ID 的对话,因为它一直被推回到 2.2 和现在(可能)3.0。我在等他们解决这个问题。
  • 我也是 :) 如果您能找到解决方案,请在此处发布。现在,我保留自定义 Correlation 中间件并添加自定义 ProblemDetailsClientErrorFactory,它使用 TraceIdentifier 而不是 Activity.Id
  • 这个话题有什么进展吗?
【解决方案2】:

您可以使用HttpContext.TraceIdentifier 代替Activity.Current.Id。我有类似的用例并使用HttpContext.TraceIdentifier 来识别日志中的请求。有关更多信息,请查看此答案:https://stackoverflow.com/a/50694180/5632590

【讨论】:

    【解决方案3】:

    在 Visual Studio 2019 的当前默认 ASP.NET Core MVC 模板中,我发现了以下错误处理程序操作:

    public IActionResult Error()
    {
        var requestId = Activity.Current?.Id ?? this.HttpContext.TraceIdentifier;
        return this.View(new ErrorViewModel { RequestId = requestId });
    }
    

    所以我认为在 Web 应用程序中接收可跟踪标识符的预期方式是

    Activity.Current?.Id ?? this.HttpContext.TraceIdentifier
    

    我的建议:按照微软的方式做

    【讨论】:

    • 这是否带有跨服务边界的公共ID?即,如果我在 API 层中记录 ID,使用标准 HttpClient 调用另一个服务进行调用,那么接收服务是否具有相同的跟踪 ID?这就是我要解决的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    相关资源
    最近更新 更多