如何格式化serilog属性名称?

时间:2019-06-16 15:37:22

标签: c# asp.net serilog

我正在使用SerilogSerilog.Formatting.Compact将日志写入文件。如何动态格式化属性名称?

我希望每个属性名称都包括其类型。

例如:bool_property_name,string_property_name,date_property_name ....

logger.Information("this is a message with {property_name}", "value");

logger
    .ForContext("property_name", "value")
    .Information("this is a message");

应该在日志中:

{ ...., string_property_name: "value" }

2 个答案:

答案 0 :(得分:0)

logger.Information($"this is a message with {property_name}");

您可以在消息中记录您的请求,只需将$放在属性的起始{}中即可。

答案 1 :(得分:0)

这就是我找到的解决方案。

关于此解决方案的一些重要注意事项:

  • 它不格式化消息模板。
  • 它格式化所有属性,例如包括第三方浓缩器添加的属性。
  • 它仍然没有生产。如果发现任何错误,我将进行更新。
public class LogEventPropertiesNameFormatter
{
    public void Format(LogEvent logEvent)
    {
        var keys = new List<string>(logEvent.Properties.Keys);

        foreach (var key in keys)
        {
            logEvent.AddPropertyIfAbsent(Visit(key, logEvent.Properties[key]));
            logEvent.RemovePropertyIfPresent(key);
        }
    }

    private LogEventProperty Visit(string name, LogEventPropertyValue value)
    {
        switch (value)
        {
        case null:
            throw new ArgumentNullException(nameof(value));
        case ScalarValue scalar:
            return VisitScalar(name, scalar);
        case SequenceValue sequence:
            return VisitSequence(name, sequence);
        case StructureValue scalar:
            return VisitStructure(name, scalar);
        case DictionaryValue dictionary:
            return VisitDictionary(name, dictionary);
        default:
            return new LogEventProperty(name, value);
    }

    private LogEventProperty VisitDictionary(string name, DictionaryValue dictionary)
    {
        var formattedElements = new Dictionary<ScalarValue, LogEventPropertyValue>(dictionary.Elements.Count);

        foreach (var element in dictionary.Elements)
        {
            var property = Visit(element.Key.Value.ToString(), element.Value);
            formattedElements.Add(new ScalarValue(property.Name), property.Value);
        }

        return LogEventProperty($"dict_{name}", new DictionaryValue(formattedElements));
    }

    private LogEventProperty VisitStructure(string name, StructureValue structure)
    {
        var properties = structure.Properties.Select(p => Visit(p.Name, p.Value));
        return new LogEventProperty($"struct_{name}", new StructureValue(properties));
    }

    private LogEventProperty VisitSequence(string name, SequenceValue sequence)
    {
        var elements = sequence.Elements.Select(e => Visit(null, e).Value);
        return new LogEventProperty($"seq_{name}", new SequenceValue(elements));
    }

    private LogEventProperty VisitScalar(string name, ScalarValue scalar)
    {
        return new LogEventProperty($"{GetScalarValueType(scalar)}_{name}", scalar);
    }

    private string GetScalarValueType(ScalarValue value)
    {
        switch (value.Value)
        {
            case null:
                return "null";
            case string _:
            case TimeSpan _:
                return "s";
            case int _:
            case uint _:
            case long _:
            case ulong _:
            case decimal _:
            case byte _:
            case sbyte _:
            case short _:
            case ushort _:
            case double _:
            case float _:
                return "n";
            case bool _:
                return "b";
            case DateTime _:
            case DateTimeOffset _:
                return "d";
            default:
                return "o";
        }
    }
}

public class CompactJsonFormatterTypeOverride : ITextFormatter
{
    private readonly ITextFormatter _textFormatter;
    private readonly LogEventPropertiesNameFormatter _logEventPropertiesNameFormatter;

    public CompactJsonFormatterTypeOverride()
    {
        _textFormatter = new CompactJsonFormatter();
        _logEventPropertiesNameFormatter = new LogEventPropertiesNameFormatter();
    }

    public void Format(LogEvent logEvent, TextWriter output)
    {
        _logEventPropertiesNameFormatter.Format(logEvent);
        _textFormatter.Format(logEvent, output);
    }
}

然后在记录器配置中:

new LoggerConfiguration().
    WriteTo.File(new CompactJsonFormatterTypeOverride(), "log.log")
    .CreateLogger();