-
我的ASP.NET核心MVC+Web API应用程序使用其他中间件层,如使用
Microsoft.Extensions.Logging
写入事件(如身份验证失败事件)。
-
这些事件目前是用最少的额外数据编写的,这使得故障排除变得困难。我想添加HTTP请求头和路径等信息,以帮助识别错误事件的原因。
-
我的研究使我使用了
ILogger<T>.BeginScope
创建一个“作用域记录器”中间件,该中间件将持续到ASP.NET核心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 */ )
C#6.0中的技巧。
-
如果我吞下异常并且不重新抛出它,那么开发人员异常页面将不会被调用,我将得到空白输出。