如何添加HttpContext来丰富未处理的异常日志?

时间:2018-02-16 00:26:43

标签: asp.net-core exception-handling asp.net-core-2.0 error-logging serilog

我已设置Serilog使用以下命令登录MSSql:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
    .MinimumLevel.Override("System", LogEventLevel.Information)
    .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
    .Enrich.FromLogContext()
    .WriteTo.Async(x => x.MSSqlServer(logConntectionString, tableName, LogEventLevel.Warning, autoCreateSqlTable: false, columnOptions: columnOptions))
    .CreateLogger();

此外,我添加了一个SerilogMiddleware,在管道中成功添加LogContext中的HttpContext

在测试控制器中,我有以下两种测试方法:

public class TestController : ControllerBase
{
    [HttpGet, Route("test")]
    public IActionResult Get() {
        try
        {
            string[] sar = new string[0];                
            var errorgenerator = sar[2]; // Trigger exception
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Caught Exception");
            return StatusCode(500, "Custom 500 Error");
        }
        return Ok();
    }

    [HttpGet, Route("test2")]
    public IActionResult Get2() {

        string[] sar = new string[0];
        var errorgenerator = sar[2];// Trigger exception

        return Ok();
    }
}

第一种方法不是DRY,所以我想处理全局/未捕获的异常,例如方法2。

我的from here是:

public class GloablExceptionFilter : ActionFilterAttribute, IExceptionFilter
{    
    public void OnException(ExceptionContext context)
    {
        var httpContext = context.HttpContext;  //  This does not appear to have the actual HttpContext

        Log.Error(context.Exception, "Unhandled Exception");
    }
}

问题是,我的中间件,否则不再工作..它不编辑响应体等...此外,当我访问ExceptionContext的context.HttpContext时,它不包含实际的HttpContext在上面的控制器方法中。

  1. 如何使用此过滤器注入或共享HttpContext和/或LogContext?
  2. 如果那不可能,我如何完成日志记录异常,同时在DRY,上有可用的上下文?
  3. 更新1:当前中间件

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddSerilog();            
    
        app.UseAuthentication();
    
        // Logging Middleware is just after Authentication, to have access to 
        // user IsAuthorized, claims, etc..
        app.UseMiddleware<SerilogMiddleware>();
    
        app.UseCors("CORSPolicy");
    
        app.UseMvc();
    }
    

    在中间件本身:

    public class SerilogMiddleware
    {
        readonly RequestDelegate _next;
    
        public SerilogMiddleware(RequestDelegate next)
        {
            if (next == null) throw new ArgumentNullException(nameof(next));
            _next = next;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
          // Do logging stuff with Request..
           await _next(httpContext);
          // Do logging stuff with Response but..
          // This point is never reached, when exception is unhandled.
        }
    }
    

1 个答案:

答案 0 :(得分:2)

基于代码片段,在向管道传递上下文时,您没有捕获异常。

如果您没有在中间件中捕获/处理异常,那么在调用流后它将无法访问您的代码。

public class SerilogMiddleware {
    readonly RequestDelegate _next;

    public SerilogMiddleware(RequestDelegate next) {
        if (next == null) throw new ArgumentNullException(nameof(next));
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext) {
        // Do logging stuff with Request..
        try {
            await _next(httpContext);
        } catch(Exception ex) {
            try {
                //Do exception specific logging

                // if you don't want to rethrow the original exception
                // then call return:
                // return;
            } catch (Exception loggingException) {
                //custom
            }

            // Otherwise re -throw the original exception
            throw;
        }
        // Do logging stuff with Response      
    }
}

以上内容将在记录之后重新抛出原始错误,以便管道中的其他处理程序捕获它并进行开箱即用处理。