- Мое приложение ASP.NET Core MVC + Web API использует другие слои промежуточного программного обеспечения, такие как IdentityServer4, которые используют
Microsoft.Extensions.Logging
для записи событий (например, событий сбоя аутентификации).
- Эти события в настоящее время записываются с минимальными дополнительными данными, что затрудняет поиск и устранение неисправностей. Я хочу добавить информацию, такую как заголовки HTTP-запроса и путь, чтобы помочь определить причину плохих событий.
- Мои исследования привели меня к использованию
ILogger<T>.BeginScope
для создания промежуточного программного обеспечения «scoped logger», которое действует в течение всего срока действия HTTP-запроса ASP.NET Core. Этот 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.
- Если я проглотил исключение и не перебросил его, то страница исключения разработчика не будет вызвана, и я получу пустой вывод.