2016-10-19 4 views
1

Я пишу обогатитель для Serilog, и я хочу, чтобы добавить свойство, которое может вызвать новое событие журнала, на практике:StackOverflowException в Serilog Обогатитель

public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) 
{ 
    ISession session = /* HttpContext.Session */; 
    logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ValueFromSession", session.GetString("ValueFromSession"))); 
    /* other properties ... */ 
} 

Я хочу, чтобы иметь возможность добавить значение из моя сессия http к моим журналам, поэтому я использую LogContext.PushProperties с пользовательским расширителем. ASP.NET Core регистрирует предупреждение всякий раз, когда считывается истекший сеанс, который запускает мой обогатитель, но всякий раз, когда я пытаюсь прочитать сеанс в расширителе, он предупреждает меня об истекшем сеансе, который запускает новый экземпляр моего enricher (ad infitum). Это вызывает StackOverflowException, который, похоже, не улавливается блоком try.

Есть ли способ отключить ведение журнала при использовании метода Enrich? Или я могу каким-то образом обнаружить такую ​​рекурсию (кроме разбора stacktrace)?

+0

проверьте, существует ли какая-либо циклическая ссылка – Mostafiz

+0

Существует косвенная ссылка между моим кодом и ASP.NET, как описано в вопросе, но я не могу удалить ссылку, потому что мне нужно иметь возможность читать с сеанса и Я хочу, чтобы ASP.NET предупреждал меня об истекших сеансах. –

+0

Исключения, вызванные из 'Enrich()', должны быть захвачены Serilog и не приводить к срабатыванию другого обработчика исключений верхнего уровня. Похоже, что-то еще может происходить здесь; вы можете добавить трассировку стека к вопросу? Ура! –

ответ

0

Я столкнулся с этой проблемой с моей собственной реализацией ILogger (не используя Serilog). Это происходит в любое время при доступе к объекту Session. Мне удалось это исправить, добавив DataProtection с сохраненными ключами в мое приложение при запуске.

services.AddDataProtection() 
    .PersistKeysToFileSystem(new DirectoryInfo("keys")); 

Я не зашел слишком глубоко в детали реализации, но от того, что я вижу в DistributedSession код, сообщение «Доступ к просроченного сеанса» регистрируется, когда старый ключ сеанса обнаружено. Проблема заключается в том, что ведение журнала происходит до того, как флаг isAvailable установлен в true, что вызывает рекурсию. Я не знаю, почему добавление DataProtection позволяет избежать этой проблемы, но может быть, что DataProtection приводит к тому, что _isNewSessionKey всегда будет true.

Другим обходным решением, предложенным в GitHub, было бы добавление промежуточного программного обеспечения для сохранения элементов сеанса, которые вы хотите зарегистрировать в HttpContext.Items. Затем извлеките эти элементы в своем журнале.