Destructure.ByTransforming<System.Type>好像没有生效
Destructure.ByTransforming<System.Type> does not appear to take effect
我试图通过仅使用类型名称、无命名空间来解构 System.Type
,但得到了意外的结果。
设置
第一个转换按预期工作,生成短字符串(Guid
的前 8 个字符)。然而,第二个从未被调用:
.Destructure.ByTransforming<Id>(id => id.ToShortString())
.Destructure.ByTransforming<Type>(type => UseUnqualifiedName(type) ? type.Name : type.ToString())
用法
_logger.LogInfo("Instance loaded: {@Type}.{@Id}", typeof(MyProject.MyNamespace.MyType), id);
预计
[INF] Instance: MyType.64b8ac0d
实际
[INF] Instance: MyProject.MyNamespace.MyType.64b8ac0d
此外,控制台输出中的完全限定名称为绿色。我注意到 System.Uri
也是这种情况,想知道 Serilog 是否特别对待这些类型。
我能做些什么来影响 System.Type
的解构?
有两个问题阻止了您预期的行为。
首先,Destructure.ByTransforming<T>()
对于T
是不变的,但是在运行时你会发现你遇到的“真正的”System.Type
对象是像RuntimeType
这样的子类.
适用于 System.Type
及其子类的自定义 IDestructuringPolicy
可以解决此问题。
但是,其次,不幸的是 - Serilog 已经默认插入其中之一:
因为 System.Type
可以生成如此巨大的对象图,并且由于像上面提到的 RuntimeType
陷阱这样的各种 footguns,Serilog 很早就禁用了 System.Type
和各种其他的结构化捕获反射值。
为了解决这个问题,您需要一个 ILogEventEnricher
来检测 属性 匹配 ScalarValue { Value: System.Type }
的值并将它们替换为修改后的 ScalarValue
.
// `Enrich.With(new RecaptureTypeEnricher())`
class RecaptureTypeEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
List<LogEventProperty> updates = null;
foreach (var property in logEvent.Properties)
{
if (property.Value is ScalarValue { Value: Type type })
{
updates ??= new List<LogEventProperty>();
updates.Add(new LogEventProperty(property.Key, new ScalarValue(UseUnqualifiedName(type))));
}
}
if (updates != null)
{
foreach (var update in updates)
{
logEvent.AddOrUpdateProperty(update);
}
}
}
}
如果您只关心格式设置,Serilog.Expressions 可能还会提供一些选项。
我试图通过仅使用类型名称、无命名空间来解构 System.Type
,但得到了意外的结果。
设置
第一个转换按预期工作,生成短字符串(Guid
的前 8 个字符)。然而,第二个从未被调用:
.Destructure.ByTransforming<Id>(id => id.ToShortString())
.Destructure.ByTransforming<Type>(type => UseUnqualifiedName(type) ? type.Name : type.ToString())
用法
_logger.LogInfo("Instance loaded: {@Type}.{@Id}", typeof(MyProject.MyNamespace.MyType), id);
预计
[INF] Instance: MyType.64b8ac0d
实际
[INF] Instance: MyProject.MyNamespace.MyType.64b8ac0d
此外,控制台输出中的完全限定名称为绿色。我注意到 System.Uri
也是这种情况,想知道 Serilog 是否特别对待这些类型。
我能做些什么来影响 System.Type
的解构?
有两个问题阻止了您预期的行为。
首先,Destructure.ByTransforming<T>()
对于T
是不变的,但是在运行时你会发现你遇到的“真正的”System.Type
对象是像RuntimeType
这样的子类.
适用于 System.Type
及其子类的自定义 IDestructuringPolicy
可以解决此问题。
但是,其次,不幸的是 - Serilog 已经默认插入其中之一:
因为 System.Type
可以生成如此巨大的对象图,并且由于像上面提到的 RuntimeType
陷阱这样的各种 footguns,Serilog 很早就禁用了 System.Type
和各种其他的结构化捕获反射值。
为了解决这个问题,您需要一个 ILogEventEnricher
来检测 属性 匹配 ScalarValue { Value: System.Type }
的值并将它们替换为修改后的 ScalarValue
.
// `Enrich.With(new RecaptureTypeEnricher())`
class RecaptureTypeEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
List<LogEventProperty> updates = null;
foreach (var property in logEvent.Properties)
{
if (property.Value is ScalarValue { Value: Type type })
{
updates ??= new List<LogEventProperty>();
updates.Add(new LogEventProperty(property.Key, new ScalarValue(UseUnqualifiedName(type))));
}
}
if (updates != null)
{
foreach (var update in updates)
{
logEvent.AddOrUpdateProperty(update);
}
}
}
}
如果您只关心格式设置,Serilog.Expressions 可能还会提供一些选项。