Serilog 序列化字段
Serilog serializing fields
如果我有以下class
public class Customer
{
public string Name;
}
然后在Serilog中有如下日志命令
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
var item = new Customer();
item.Name = "John";
Serilog.Log.Information("Customer {@item}", item);
日志在 Seq 中显示为
Customer {}
如果我将 Name 字段更改为 属性 它会起作用,但我不想在这个阶段这样做。有什么解决办法吗?
要仅针对一种类型执行此操作(推荐),您可以使用:
.Destructure.ByTransforming<Customer>(c => new { c.Name })
如果您想要包含所有类型的 public 个字段,或者那些匹配某种条件的字段,您可以插入一个策略来实现:
class IncludePublicFieldsPolicy : IDestructuringPolicy
{
public bool TryDestructure(
object value,
ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue result)
{
if (!(value is SomeBaseType))
{
result = null;
return false;
}
var fieldsWithValues = value.GetType().GetTypeInfo().DeclaredFields
.Where(f => f.IsPublic)
.Select(f => new LogEventProperty(f.Name,
propertyValueFactory.CreatePropertyValue(f.GetValue(value))));
result = new StructureValue(fieldsWithValues);
return true;
}
}
该示例将其范围缩小为仅查看从 SomeBaseType
派生的对象。
您可以将其插入:
.Destructure.With<IncludePublicFieldsPolicy>()
(我认为这可能需要一些调整,但应该是一个很好的起点。)
感谢 Nicholas Blumhardt 提供了一个很好的起点。我只是做了一个小调整。
我的class:
public class Dummy
{
public string Field = "the field";
public string Property { get; set; } = "the property";
}
记录调用:
Log.Information("Dummy = {@Dummy}", new Dummy());
IDestructuringPolicy 实现包括字段和属性:
internal class IncludePublicFieldsPolicy : IDestructuringPolicy
{
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
{
var typeInfo = value.GetType().GetTypeInfo();
var fieldsWithValues = typeInfo
.DeclaredFields
.Where(f => f.IsPublic)
.Select(f =>
{
var val = f.GetValue(value);
var propval = propertyValueFactory.CreatePropertyValue(val);
var ret = new LogEventProperty(f.Name, propval);
return ret;
})
;
var propertiesWithValues = typeInfo
.DeclaredProperties
.Where(f => f.CanRead)
.Select(f =>
{
var val = f.GetValue(value);
var propval = propertyValueFactory.CreatePropertyValue(val);
var ret = new LogEventProperty(f.Name, propval);
return ret;
})
;
result = new StructureValue(fieldsWithValues.Union(propertiesWithValues));
return true;
}
}
如果我有以下class
public class Customer
{
public string Name;
}
然后在Serilog中有如下日志命令
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
var item = new Customer();
item.Name = "John";
Serilog.Log.Information("Customer {@item}", item);
日志在 Seq 中显示为
Customer {}
如果我将 Name 字段更改为 属性 它会起作用,但我不想在这个阶段这样做。有什么解决办法吗?
要仅针对一种类型执行此操作(推荐),您可以使用:
.Destructure.ByTransforming<Customer>(c => new { c.Name })
如果您想要包含所有类型的 public 个字段,或者那些匹配某种条件的字段,您可以插入一个策略来实现:
class IncludePublicFieldsPolicy : IDestructuringPolicy
{
public bool TryDestructure(
object value,
ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue result)
{
if (!(value is SomeBaseType))
{
result = null;
return false;
}
var fieldsWithValues = value.GetType().GetTypeInfo().DeclaredFields
.Where(f => f.IsPublic)
.Select(f => new LogEventProperty(f.Name,
propertyValueFactory.CreatePropertyValue(f.GetValue(value))));
result = new StructureValue(fieldsWithValues);
return true;
}
}
该示例将其范围缩小为仅查看从 SomeBaseType
派生的对象。
您可以将其插入:
.Destructure.With<IncludePublicFieldsPolicy>()
(我认为这可能需要一些调整,但应该是一个很好的起点。)
感谢 Nicholas Blumhardt 提供了一个很好的起点。我只是做了一个小调整。
我的class:
public class Dummy
{
public string Field = "the field";
public string Property { get; set; } = "the property";
}
记录调用:
Log.Information("Dummy = {@Dummy}", new Dummy());
IDestructuringPolicy 实现包括字段和属性:
internal class IncludePublicFieldsPolicy : IDestructuringPolicy
{
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
{
var typeInfo = value.GetType().GetTypeInfo();
var fieldsWithValues = typeInfo
.DeclaredFields
.Where(f => f.IsPublic)
.Select(f =>
{
var val = f.GetValue(value);
var propval = propertyValueFactory.CreatePropertyValue(val);
var ret = new LogEventProperty(f.Name, propval);
return ret;
})
;
var propertiesWithValues = typeInfo
.DeclaredProperties
.Where(f => f.CanRead)
.Select(f =>
{
var val = f.GetValue(value);
var propval = propertyValueFactory.CreatePropertyValue(val);
var ret = new LogEventProperty(f.Name, propval);
return ret;
})
;
result = new StructureValue(fieldsWithValues.Union(propertiesWithValues));
return true;
}
}