Уничтожение исключений в Serilog
Serilog имеет удобный способ деструктурирования объектов, как показано в этом примере:
logger.Debug(exception, "This is an {Exception} text", exception);
logger.Debug(exception, "This is an {@Exception} structure", exception);
Первая строка приводит к тому, что регистратор регистрирует исключение как обычный текст (вызывая ToString()), а вторая строка заставляет журнал регистрировать свойства исключения как отдельные поля. Но как насчет этой перегрузки:
logger.Debug(exception, "This is an exception", exception);
Это принимает исключение в качестве первого аргумента и всегда записывается как строка. То, что я хотел бы сделать возможным, заключается в том, чтобы включить исключение регистрации в структурированном виде. Можно ли настроить Serilog для этого?
ОБНОВИТЬ. Я предполагаю, что этот вопрос приводит к еще одному аспекту исключений регистрации: как я могу обеспечить, чтобы сообщения были обогащены свойствами исключений (поэтому они регистрируются структурированным способом для богатых поглотителей, таких как Elasticsearch), не записывая все свойства исключения в отображаемое текстовое сообщение ( поэтому обычные текстовые журналы не заполнены огромными кучами деталей исключения).
Ответы
Ответ 1
Там обсуждается это обсуждение форума, в котором представлены несколько решений. Томас Болон создал расширение исключения, которое можно найти в Gist.
В этом случае вы используете только этот синтаксис:
logger.Debug(exception, "This is an exception");
Нет необходимости добавлять исключение в строку формата.
Чтобы исключение печаталось в текстовые раковины, просто убедитесь, что {Exception}
включено в выходной шаблон. Стандартные встроенные уже имеют это, например:
outputTemplate: "{Timestamp} [{Level}] {Message}{NewLine}{Exception}";
Ответ 2
Взгляните на Serilog.Exceptions регистрирует детали исключений и настраиваемые свойства, которые не выводятся в Exception.ToString().
Эта библиотека имеет собственный код для работы с дополнительными свойствами в большинстве распространенных типов исключений и только возвращается к использованию отражения, чтобы получить дополнительную информацию, если исключение не поддерживается Serilog. Исключения внутри.
Добавьте пакет NuGet, а затем добавьте enricher так:
using Serilog;
using Serilog.Exceptions;
ILogger logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.WriteTo.Sink(new RollingFileSink(
@"C:\logs",
new JsonFormatter(renderMessage: true))
.CreateLogger();
Теперь ваши журналы JSON будут дополнены подробной информацией об исключении и даже настраиваемыми свойствами исключения. Вот пример того, что происходит, когда вы регистрируете исключение DbEntityValidationException из EntityFramework (это исключение известно для наличия глубоко вложенных пользовательских свойств, которые не включены в .ToString()
).
try
{
...
}
catch (DbEntityValidationException exception)
{
logger.Error(exception, "Hello World");
}
В приведенном выше коде записывается следующее:
{
"Timestamp": "2015-12-07T12:26:24.0557671+00:00",
"Level": "Error",
"MessageTemplate": "Hello World",
"RenderedMessage": "Hello World",
"Exception": "System.Data.Entity.Validation.DbEntityValidationException: Message",
"Properties": {
"ExceptionDetail": {
"EntityValidationErrors": [
{
"Entry": null,
"ValidationErrors": [
{
"PropertyName": "PropertyName",
"ErrorMessage": "PropertyName is Required.",
"Type": "System.Data.Entity.Validation.DbValidationError"
}
],
"IsValid": false,
"Type": "System.Data.Entity.Validation.DbEntityValidationResult"
}
],
"Message": "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.",
"Data": {},
"InnerException": null,
"TargetSite": null,
"StackTrace": null,
"HelpLink": null,
"Source": null,
"HResult": -2146232032,
"Type": "System.Data.Entity.Validation.DbEntityValidationException"
},
"Source": "418169ff-e65f-456e-8b0d-42a0973c3577"
}
}
Serilog.Exceptions поддерживает стандарт.NET и поддерживает множество распространенных типов исключений без отражения, но мы хотели бы добавить больше, поэтому, пожалуйста, не стесняйтесь вносить свой вклад.
Top Tip - отслеживаемые трассировки стека
Вы можете использовать пакет Ben.Demystifier NuGet, чтобы получить отслеживаемые пользователем трассировки стека за исключениями или пакет NuGet с серилограммой-демистифицировать, если вы используете Serilog.
Ответ 3
Этого следует избегать вообще. И ElasticSearch, и Serilog не разработаны с учетом того, что вы будете сериализовывать произвольные объекты. Запись объектов с конфликтующими фигурами приведет к отображению исключений в ElasticSearch. Если вы используете приемник ElasticSearch в NuGet, все, что приводит к конфликту с отображением, будет потеряно. Кроме того, Serilog не обрабатывает циклические отношения, поэтому это приведет к ошибкам самобога. Существует проект, который пытается решить эту проблему путем деструктурирования в словарях и передачи этого в Serilog, но вы все равно столкнетесь с беспорядочными журналами и исключениями отображения.
Serilog: https://nblumhardt.com/2016/02/serilog-tip-dont-serialize-arbitrary-objects/
Я нашел, что лучше всего быть конкретным в том, чтобы регистрировать свойства исключений на основе того, что вы считаете полезным в исключении.