Как я могу иметь пользовательское промежуточное программное обеспечение для регистрации необработанных исключений со страницей исключений разработчика без дублирующих записей журнала? - PullRequest
0 голосов
/ 26 января 2019

Вот проблема X / Y :

  • Мое приложение 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.
    • Если я проглотил исключение и не перебросил его, то страница исключения разработчика не будет вызвана, и я получу пустой вывод.

В итоге:

  • Сценарий 1:

    • Промежуточное программное обеспечение: --> DeveloperExceptionPage --> LoggingScopeMiddleware -->
    • Страница разработчика: Показано. (Хорошо)
    • Необработанное исключение: зарегистрировано без свойств области. (Плохо)
  • Сценарий 2:

    • Промежуточное программное обеспечение: --> LoggingScopeMiddleware --> DeveloperExceptionPage -->
    • Страница разработчика: Показано. (Хорошо)
    • Необработанное исключение: зарегистрировано без свойств области. (Плохо)
  • Сценарий 3:

    • Промежуточное программное обеспечение: --> ExceptionCatchingLoggingScopeMiddleware --> DeveloperExceptionPage -->
    • Страница разработчика: Показано. (Хорошо)
    • Необработанное исключение: зарегистрировано без свойств области. (Плохо)
  • Сценарий 4:

    • Промежуточное программное обеспечение: --> DeveloperExceptionPage --> ExceptionCatchingLoggingScopeMiddleware( rethrow: true ) -->
    • Страница разработчика: Отображается. (Хорошо)
    • Необработанное исключение: регистрируется дважды, один раз со свойствами области (Хорошо) и снова без свойств области (плохо)
  • Сценарий 5:

    • Промежуточное программное обеспечение: --> DeveloperExceptionPage --> ExceptionCatchingLoggingScopeMiddleware( rethrow: false ) -->
    • Страница разработчика: не отображается. (Плохо)
    • Необработанное исключение: зарегистрировано один раз со свойствами области действия (Хорошо)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...