是否可以在 Serilog.Exceptions 中禁用基于反射的解构器?

Is it possible to disabled the reflection based destructurer in Serilog.Exceptions?

Serilog.Exceptions 非常适合记录异常。它有大量支持的异常类型。

例如当前设置:

Log.Logger = new LoggerConfiguration()
    .Enrich.WithExceptionDetails()
    .CreateLogger();

目前,如果没有找到异常类型的解构器,它会回退到 "reflection based destructurer"。

出于性能考虑,但更重要的是可预测性,我们希望禁用反射回退。

我尝试用 DestructuringOptions 配置它,例如禁用一些默认析构函数或将 DestructuringDepth 设置为 0.

不幸的是,这些选项不起作用:

知道如何为此配置 Serilog.Exceptions 吗?

我认为您最好的选择是实现自己的 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 类型的众所周知的属性。

这已添加到 Serilog.Exceptions 5.4.0,请参阅 changelog。有一个新方法WithoutReflectionBasedDestructurer

用法

帮手class

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();