在ASP.NET Core 2.1中,System.Diagnostics.Activity为空

时间:2018-08-01 11:22:12

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

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

背景

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

我们采用的方法是:

  • 将诊断侦听器添加到Microsoft.AspNetCore.Hosting.HttpRequestIn.Start

  • 的中间件管道中
  • 调用此侦听器时,请检查context.request中是否有一个名为“ Request-Id”的标头,如果没有,则添加一个值为Activity.Current.Id 的标头。 p>

  • 另一种中间件负责将“ 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);
        }
    }

3 个答案:

答案 0 :(得分:2)

经过数天的研究,回答了我自己的问题,但简洁地是:在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标头和{{ 1}}以自己的方式记录属性,这会干扰此中间件代码。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

在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

我的建议:以微软的方式做到