【问题标题】:Serilog serializing fieldsSerilog 序列化字段
【发布时间】:2017-09-11 09:15:35
【问题描述】:

如果我有以下课程

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 字段更改为一个属性,它可以工作,但我不想在这个阶段这样做。有什么办法解决吗?

【问题讨论】:

  • 一种选择可能是在LoggerConfiguration 上使用Destructure 配置对象,如下所述:github.com/serilog/serilog/wiki/…
  • Name 是财产时是否有效?
  • 是的,如果我将 Name 设为一个属性,它就可以工作。

标签: c# .net serilog seq seq-logging


【解决方案1】:

要仅针对一种类型(推荐)执行此操作,您可以使用:

.Destructure.ByTransforming<Customer>(c => new { c.Name })

如果你想包含所有类型的公共字段,或者那些匹配某种条件的,你可以插入一个策略来做到这一点:

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

(我认为这可能需要一些调整,但应该是一个很好的起点。)

【讨论】:

    【解决方案2】:

    感谢 Nicholas Blumhardt 提供了一个良好的起点。我只是做了一个小调整。

    我的班级:

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-10-10
      • 2017-06-08
      • 2020-12-02
      • 2022-01-12
      • 2014-08-10
      • 2019-10-11
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多