这里是an X/Y problem:
Microsoft.Extensions.Logging
来编写事件(例如身份验证失败事件)。ILogger<T>.BeginScope
创建了一个“作用域记录器”中间件,该中间件在ASP.NET Core HTTP请求的整个生命周期内一直有效。此using( logger.BeginScope( ... ) )
调用将存在于中间件中(该中间件通过影响瞬时服务的DI ILogger
起作用)。我的中间件将不本身捕获异常,仅添加到日志记录范围,如下所示:
class LoggingScopeMiddleware {
private readonly ILoggerFactory loggerFactory; // DI
private readonly RequestDelegate next;
public async Task Invoke( HttpContext context ) {
Dictionary<String,Object> values = CreateDict( context.Request... );
using( this.loggerFactory.CreateLogger().BeginScope( values ) ) {
this.next( context );
}
}
}
但是,如果在next
内抛出异常,则在记录该异常时(通过链中上层或下层的另一个中间件层),它将丢失添加的额外记录值在BeginScope
中。我以为这不是本来打算发生的,但确实如此。
LoggingScopeMiddleware.Invoke
方法中捕获并记录了该异常,则开发人员异常页面将不会捕获该异常,而我只会在浏览器中显示空白页面。如果我在LoggingScopeMiddleware
内捕获到异常,则可以使用其他属性记录该异常:
class ExceptionCatchingLoggingScopeMiddleware {
private readonly ILoggerFactory loggerFactory; // DI
private readonly RequestDelegate next;
private readonly Boolean rethrow = true;
public async Task Invoke( HttpContext context ) {
Dictionary<String,Object> values = CreateDict( context.Request... );
using( this.loggerFactory.CreateLogger().BeginScope( values ) ) {
try {
this.next( context );
} catch( Exception ex ) {
LogException( ex );
if( this.rethrow ) throw;
}
}
}
}
when( LogException( ex ) /* == false */ )
技巧,也会发生这种情况。总结:
场景1:
--> DeveloperExceptionPage --> LoggingScopeMiddleware -->
场景2:
--> LoggingScopeMiddleware --> DeveloperExceptionPage -->
场景3:
--> ExceptionCatchingLoggingScopeMiddleware --> DeveloperExceptionPage -->
方案4:
--> DeveloperExceptionPage --> ExceptionCatchingLoggingScopeMiddleware( rethrow: true ) -->
场景5:
--> DeveloperExceptionPage --> ExceptionCatchingLoggingScopeMiddleware( rethrow: false ) -->