【问题标题】:Serilog Logcontext properties are gone after exception handlerSerilog Logcontext 属性在异常处理程序之后消失了
【发布时间】:2019-08-08 23:05:02
【问题描述】:

在我的网站中,我正在集成 Serilog 以将我的错误记录到自定义接收器。日志通过 LogContext 丰富,其中需要传递一些自定义属性。如果我使用 Log.Information(),它会通过 LogEvent 中的属性到达我的接收器。所以这很好用。

主要目的是将日志系统与异常处理程序中间件结合起来。因此,在异常处理程序中,会捕获从控制器方法抛出的错误。我将 _logger.Log() 放在异常处理程序中的任何地方,Sink 中都没有可用的自定义属性。在调试时,它在进入 Sink 之前通过了 LogContextFilter,但没有找到过滤器的属性。

有人知道吗?

启动

Log.Logger = new LoggerConfiguration()
            .WriteTo.PasSink(new SerLogServiceClient.SerLogServiceClient(new SerLogServiceClientOptions()))
            .Enrich.FromLogContext()
            .CreateLogger();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddMvcOptions(mo =>
        {
            mo.Filters.Add(typeof(LogContextFilter));
        });

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMiddleware<LogContextMiddleware>();
        app.UseErrorHandler(o =>
        {
            o.ExceptionHandlingPath = "/Home/Error";
            o.Context = ExceptionHandler.Context.MVC;
        });

        //app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "Content")),
            RequestPath = "/Content"
        });

        app.UseAuthentication();

        app.UseSession();
        //app.UseCookiePolicy();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

LogContextFilter

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        using (LogContext.Push(
            new PropertyEnricher("UserCode", context.HttpContext.User.Claims.FirstOrDefault(s => s.ToString().StartsWith("UserCode"))?.Value),
            new PropertyEnricher("Test", "Will this go through?")))
        {
            await next.Invoke();
        }
    }

ExceptionHandlerMiddleware

public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (HttpRequestException hex)
        {
            //check response naar reynaersexception??
            //deserialize naar re
            throw new NotSupportedException();  //als test
        }
        catch  (Exception ex)
        {

            if (context.Response.HasStarted)
            {
                throw ex;
            }

            _logger.LogError(ex.Message);

            var originalPath = context.Request.Path;
            try
            {
                if (_options.Context == Context.MVC)
                {
                    context.Response.Clear();
                    context.Response.StatusCode = 500;
                    context.Response.OnStarting(Callback, context.Response);

                    //set features
                    var exceptionHandlerFeature = new ReynaersExceptionHandlerFeature()
                    {
                        Error = ex,
                        Path = context.Request.Path.Value,
                    };
                    context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
                    context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);

                    //continue lifecycle with updated context
                    if (_options.ExceptionHandlingPath.HasValue)
                    {
                        context.Request.Path = _options.ExceptionHandlingPath;
                    }

                    await _next.Invoke(context);
                }
            }
            catch (Exception ex2)
            {
                // Suppress secondary exceptions, re-throw the original.
                Log.Error(ex2.Message);
                context.Request.Path = originalPath;
                throw ex;
            }
        }
    }

【问题讨论】:

    标签: c# asp.net-mvc asp.net-core error-handling serilog


    【解决方案1】:

    发生这种情况是因为异常被记录在在using (LogContext.Push(..)) 之外运行的处理程序中,因此自定义属性已经从上下文中消失了。

    ...
    
    // in mvc's OnActionExecutionAsync()
            using (LogContext.Push(
                new PropertyEnricher("UserCode", ".."),
                new PropertyEnricher("Test", "Will this go through?")))
            {
                await next.Invoke(); // code that throws
            }
    
    ...
    
    // later in ExceptionHandlerMiddleware, no custom properties
    _logger.LogError(ex.Message);
    

    前段时间研究了这个问题,写了ThrowContextEnricher

    此库从引发异常的点捕获上下文。然后可以使用 ThrowContextEnricher 用原始上下文丰富异常日志。

    Log.Logger = new LoggerConfiguration()
        .Enrich.With<ThrowContextEnricher>()  // Adds enricher globally
        .Enrich.FromLogContext()
        .WriteTo
        ...
        .CreateLogger();
    ...
    
    
    // in mvc's OnActionExecutionAsync()
    // push your properties as normal
            using (LogContext.Push(
                new PropertyEnricher("UserCode", ".."),
                new PropertyEnricher("Test", "Will this go through?")))
            {
                await next.Invoke(); // code that throws
            }
    
    ...
    
    // in exception handler
    // properties get logged now
    // notice the exception is passed too, not just message
    _logger.LogError(ex, ex.Message);
    
    

    【讨论】:

      【解决方案2】:

      我也为此苦苦挣扎,几个月前找到了答案(虽然现在找不到。搜索它,这就是我偶然发现你的问题的方式。)。很确定您现在找到了解决方案,但这可能会对某人有所帮助。

      但试试这个变化:

      catch (Exception ex2) when (LogUnexpectedError(ex2))
      {
          // Suppress secondary exceptions, re-throw the original.        
          context.Request.Path = originalPath;
          throw ex;
      }
      
      private bool LogUnexpectedError(Exception ex)
      {
          Log.Error(ex.Message);
          return true;
      }
      

      如果我没记错的话,在 LogExceptionFilter 超出范围之前,when 部分是唯一可以处理异常的地方。希望对您有所帮助。

      更新:在我最初找到这个的地方找到: https://andrewlock.net/how-to-include-scopes-when-logging-exceptions-in-asp-net-core/#using-exception-filters-to-capture-scopes

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-05
        • 1970-01-01
        • 2011-09-22
        • 1970-01-01
        • 1970-01-01
        • 2011-05-20
        • 1970-01-01
        相关资源
        最近更新 更多