System.Diagnostics.Activity 在 aspnet 核心 2.1 中为空

Mas*_*ton 7 c# .net-core asp.net-core

我们刚刚将一个 aspnet 核心 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();
        }
Run Code Online (Sandbox Code Playgroud)

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

    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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Mas*_*ton 3

经过几天的研究,回答我自己的问题,但简单地说是:在 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日志属性,这会干扰此操作中间件代码。