Serilog不会破坏对象的集合

时间:2018-06-11 15:11:21

标签: logging asp.net-core serilog destructuring

MVC核心Web服务项目,使用AspNetCore 2.0.0和Serilogger 2.1.1。

当调用Serilog来记录集合/ IEnumerable /对象列表时,它所做的就是列出对象类型。如果我们遍历集合中的项目并单独记录它们,Serilog会将它们解构为正常,并且它们会在我们的日志中正确显示。

基本代码示例:

List<MyResponse> results = ValidateResourceCollection(events);
_logger.LogInformation("EventController.Post response {@results}", results);

我们会收到这样的日志消息:

2018-06-11 10:53:35.952 -04:00 [Information] EventController.Post response "Blah.Models.Response.MyResponse, Blah.Models.Response.MyResponse"

有没有办法让Serilog正确地解构这个列表? 我尝试通过实现IDestructuringPolicy来解决这个问题,但只有在有一个对象要进行解构时才会调用它。如果将对象集合用作参数,则永远不会调用IDestructuringPolicy。

1 个答案:

答案 0 :(得分:0)

您可以使用解构策略来记录对象的集合:

public class CollectionDestructuringPolicy<T> : IDestructuringPolicy
{
    public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory,
        out LogEventPropertyValue result)
    {

        switch (value)
        {
            case City city:
                result = Destruct(city,propertyValueFactory);
                return true;
            case ICollection<T> collection:
                result = Destruct(collection,propertyValueFactory);
                return true;
        }
        result = null;
        return false;
    }

    private static LogEventPropertyValue Destruct(object collectionItem, ILogEventPropertyValueFactory propertyValueFactory)
    {
        var collectionItemPropertiesNamePerValue = new List<(string propertyName, object propertyValue)>();
        var collectionItemProperties = collectionItem.GetType().GetProperties().ToList();
        collectionItemProperties.ForEach(p => collectionItemPropertiesNamePerValue.Add((propertyName:p.Name, propertyValue:p.GetValue(collectionItem))));
        var properties = new List<LogEventProperty>(collectionItemPropertiesNamePerValue.Count);
        collectionItemPropertiesNamePerValue.ForEach(namePerValue =>
            properties.Add(new LogEventProperty(namePerValue.propertyName,
                propertyValueFactory.CreatePropertyValue(namePerValue.propertyValue))));
        LogEventPropertyValue result = new StructureValue(properties);
        return result;
    }

    private static LogEventPropertyValue Destruct(IEnumerable<T> collection,
        ILogEventPropertyValueFactory propertyValueFactory)
    {
        var elements = collection.Select(e => propertyValueFactory.CreatePropertyValue(e, true));
        LogEventPropertyValue result = new SequenceValue(elements);
        return result;
    }
}
//In Logger Factory:
public static class LoggerFactory
{
    public static Logger Create()
    {
        return new LoggerConfiguration()
            .WriteTo.Console()
            .Destructure.With<CollectionDestructuringPolicy<City>>()
            .CreateLogger();
    }
}

RMK。一个完善的asp.net核心解决方案sample