是否可以在 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
.
不幸的是,这些选项不起作用:
ReflectionBasedDestructurer
不在默认析构函数列表中
- 不允许将
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();
包 Serilog.Exceptions
非常适合记录异常。它有大量支持的异常类型。
例如当前设置:
Log.Logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.CreateLogger();
目前,如果没有找到异常类型的解构器,它会回退到 "reflection based destructurer"。
出于性能考虑,但更重要的是可预测性,我们希望禁用反射回退。
我尝试用 DestructuringOptions
配置它,例如禁用一些默认析构函数或将 DestructuringDepth 设置为 0
.
不幸的是,这些选项不起作用:
ReflectionBasedDestructurer
不在默认析构函数列表中- 不允许将
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();