如何修改Serilog解构复杂对象时的默认分隔符为等号?
可以实现,通过自定义Serilog的格式化逻辑即可替换解构对象的键值分隔符
Serilog默认的解构输出使用冒号分隔属性名和值,要改成等号,有两种常用实现方式:
方式一:正则替换输出文本(简单场景适用)
通过自定义ITextFormatter捕获原始日志输出,再用正则替换属性的冒号为等号:
using Serilog; using Serilog.Events; using Serilog.Formatting; using Serilog.Formatting.Display; using System.IO; public class EqualSignObjectFormatter : ITextFormatter { private readonly MessageTemplateTextFormatter _innerFormatter; public EqualSignObjectFormatter(string outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}") { _innerFormatter = new MessageTemplateTextFormatter(outputTemplate); } public void Format(LogEvent logEvent, TextWriter output) { using var stringWriter = new StringWriter(); _innerFormatter.Format(logEvent, stringWriter); var originalOutput = stringWriter.ToString(); // 匹配属性名:值的格式,替换为属性名=值 var modifiedOutput = System.Text.RegularExpressions.Regex.Replace(originalOutput, @"(\w+):""([^""]+)""", "$1=\"$2\""); output.Write(modifiedOutput); } }
配置Logger时指定该格式化器:
public class myClass { public void myMethod() { var logger = new LoggerConfiguration() .WriteTo.EventLog("myapp", formatter: new EqualSignObjectFormatter()) .CreateLogger(); var myComplexObject = new { property1 = "prop1", property2 = "prop2" }; logger.Information("{@complex}", myComplexObject); } }
注意:这种方式适合属性值不含引号的简单场景,若值中有引号会导致正则匹配错误。
方式二:自定义解构策略(严谨场景适用)
实现IDestructuringPolicy完全控制对象的解构输出逻辑,避免正则的局限性:
using Serilog.Core; using Serilog.Events; using System.Reflection; public class EqualSignDestructuringPolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { // 跳过值类型、字符串等不需要解构的类型 if (value == null || value.GetType().IsValueType || value is string) { result = null; return false; } // 获取对象的所有属性并转换为LogEventProperty var properties = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Select(p => new LogEventProperty(p.Name, propertyValueFactory.CreatePropertyValue(p.GetValue(value), true))); // 使用自定义的StructureValue控制输出格式 result = new CustomStructureValue(properties); return true; } // 自定义StructureValue重写渲染逻辑,用等号分隔键值 private class CustomStructureValue : StructureValue { public CustomStructureValue(IEnumerable<LogEventProperty> properties) : base(properties) { } public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) { output.Write("{ "); var isFirst = true; foreach (var prop in Properties) { if (!isFirst) output.Write(", "); output.Write(prop.Name); output.Write("=\""); prop.Value.Render(output, format, formatProvider); output.Write("\""); isFirst = false; } output.Write(" }"); } } }
配置Logger时添加该解构策略:
public class myClass { public void myMethod() { var logger = new LoggerConfiguration() .Destructure.With<EqualSignDestructuringPolicy>() .WriteTo.EventLog("myapp") .CreateLogger(); var myComplexObject = new { property1 = "prop1", property2 = "prop2" }; logger.Information("{@complex}", myComplexObject); } }
两种方式都能实现你想要的输出:{ complex:{ property1="prop1", property2="prop2" }}
内容的提问来源于stack exchange,提问作者Breakwin
相关产品推荐
相关产品推荐

