Можно ли отключить деструктурирование на основе отражения в Serilog.Exceptions?
Пакет Serilog.Exceptions
удобен для регистрации исключений. Он имеет большой список поддерживаемых типов исключений.
например, текущая настройка:
Log.Logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.CreateLogger();
В настоящее время он возвращается к "деструктурированию на основе отражения", если для типа исключения не найдено деструктурирование.
Из-за производительности, но что более важно для предсказуемости, мы хотели бы отключить резервное отображение отражения.
Я попытался настроить это с помощью DestructuringOptions
, например, отключите некоторые из деструкторов по умолчанию или установите для DestructuringDepth значение 0
.
К сожалению, эти варианты не работают:
- то
ReflectionBasedDestructurer
отсутствует в списке деструкторов по умолчанию - установка
DestructuringDepth
к0
не разрешено (исключение)
Есть идеи, как настроить для этого Serilog.Exceptions?
2 ответа
Это было добавлено в Serilog.Exceptions 5.4.0, см. Журнал изменений. Есть новый методWithoutReflectionBasedDestructurer
.
Применение
Класс помощника
public static class LoggerEnrichmentConfigurationExtensions
{
public static LoggerConfiguration WithExceptionDetailsWithoutReflection(
this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
{
if (loggerEnrichmentConfiguration is null)
{
throw new ArgumentNullException(nameof(loggerEnrichmentConfiguration));
}
var options = new DestructuringOptionsBuilder()
.WithDefaultDestructurers()
.WithoutReflectionBasedDestructurer() //new in 5.4.0!
.WithIgnoreStackTraceAndTargetSiteExceptionFilter();
var logEventEnricher = new ExceptionEnricher(options);
return loggerEnrichmentConfiguration.With(logEventEnricher);
}
}
Конфиг
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.WithExceptionDetailsWithoutReflection()
.CreateLogger();
Думаю, лучший вариант - это реализовать свой собственный ExceptionDecostructor
, что-то вроде этого:
public class FallbackExceptionDestructurer : ExceptionDestructurer
{
public override Type[] TargetTypes => new[]
{
typeof(Exception),
};
public override void Destructure(
Exception exception,
IExceptionPropertiesBag propertiesBag,
Func<Exception, IReadOnlyDictionary<string, object>> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
}
}
Таким образом вы сохраните все доступные деструкторы, а отражение будет проигнорировано, потому что FallbackExceptionDestructurer
будет охватывать все неизвестные исключения из-за этого кода:
public override Type[] TargetTypes => new[]
{
typeof(Exception),
};
Вот как вы регистрируете деструкторы
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
.WithDefaultDestructurers()
.WithDestructurers(new[] { new FallbackExceptionDestructurer () }))
Если вы проверите исходный код ExceptionDestructurer.Decostruct(...), он не использует никакого отражения - только хорошо известные свойства из типа Exception.