StackOverflowException в Serilog Enricher

Я пишу дополнитель для 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, но всякий раз, когда я пытаюсь читать из сеанса в enricher, он предупреждает меня об истекшем сеансе, который запускает новый экземпляр моего enricher (ad infitum ). Это вызывает StackOverflowException, который не может быть уловлен с try блоком.

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


person Jussi Kosunen    schedule 19.10.2016    source источник
comment
внимательно проверьте, есть ли циркулярная ссылка   -  person Mostafiz    schedule 19.10.2016
comment
Между моим кодом и ASP.NET существует косвенная ссылка, как описано в вопросе, но я не могу удалить ссылку, потому что мне нужно иметь возможность читать из сеанса, и я хочу, чтобы ASP.NET предупреждал меня об истекших сеансах .   -  person Jussi Kosunen    schedule 19.10.2016
comment
Исключения, генерируемые из Enrich(), должны перехватываться Serilog и не приводить к срабатыванию другого обработчика исключений верхнего уровня. Похоже, здесь может происходить что-то еще; Можете ли вы добавить к вопросу трассировку стека? Ваше здоровье!   -  person Nicholas Blumhardt    schedule 20.10.2016
comment
Проблема не в том, что он регистрирует выброшенное исключение, ASP.NET просто регистрирует предупреждение всякий раз, когда я обращаюсь к HttpContext.Session в этом конкретном случае, что я хочу сделать в моем обогатителе. Конечным результатом этой взаимной рекурсии является переполнение стека.   -  person Jussi Kosunen    schedule 20.10.2016


Ответы (1)


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

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

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

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

person Donn Relacion    schedule 08.03.2018