如何让Serilog日志属性展平且保留JsonFormatter的长字段名?
问题:Serilog日志自定义属性展平到顶层并保留长字段名
当前日志配置
Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .Enrich.FromGlobalLogContext() .WriteTo.Console(new JsonFormatter()) .CreateLogger();
当前日志输出格式
{ "Timestamp": "2023-02-23T20:36:15.0931656+00:00", "Level": "Information", "MessageTemplate": "Entered the Run method", "Properties": { "x-correlation-id": "00000000-0000-0000-0000-000000000000" } }
需求
希望把x-correlation-id这类自定义属性移到日志的顶层节点,同时保留JsonFormatter的长字段名(比如Timestamp、Level),而非使用CompactJsonFormatter的短命名(@t、@mt)。
解决方案:自定义FlattenedJsonFormatter
通过继承Serilog自带的JsonFormatter,重写事件和属性的写入逻辑,即可实现属性展平并保留原字段名:
1. 实现自定义格式化器
using Serilog.Formatting.Json; using Serilog.Events; using System.IO; using System.Collections.Generic; public class FlattenedJsonFormatter : JsonFormatter { public FlattenedJsonFormatter(bool renderMessage = false, string closingDelimiter = null) : base(renderMessage, closingDelimiter) { } // 重写事件写入逻辑,调整字段顺序并展平属性 protected override void WriteEvent(LogEvent logEvent, TextWriter output) { output.Write("{"); // 写入默认长命名字段 WriteJsonProperty("Timestamp", logEvent.Timestamp, output); output.Write(','); WriteJsonProperty("Level", logEvent.Level.ToString(), output); output.Write(','); WriteJsonProperty("MessageTemplate", logEvent.MessageTemplate.Text, output); // 可选:写入渲染后的消息文本 if (RenderMessage) { output.Write(','); WriteJsonProperty("Message", logEvent.RenderMessage(), output); } // 展平写入自定义属性到顶层 if (logEvent.Properties.Count > 0) { output.Write(','); WriteFlattenedProperties(logEvent.Properties, output); } // 写入异常信息(如果存在) if (logEvent.Exception != null) { output.Write(','); WriteJsonProperty("Exception", logEvent.Exception.ToString(), output); } output.Write("}"); if (ClosingDelimiter != null) output.Write(ClosingDelimiter); } // 自定义属性写入方法,直接输出键值对到顶层 private void WriteFlattenedProperties(IReadOnlyDictionary<string, LogEventPropertyValue> properties, TextWriter output) { var isFirstProperty = true; foreach (var prop in properties) { if (!isFirstProperty) output.Write(','); WriteJsonProperty(prop.Key, prop.Value, output); isFirstProperty = false; } } }
2. 修改日志配置使用自定义格式化器
Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .Enrich.FromGlobalLogContext() .WriteTo.Console(new FlattenedJsonFormatter()) // 使用自定义格式化器 .CreateLogger();
最终日志输出效果
{ "Timestamp": "2023-02-23T20:36:15.0931656+00:00", "Level": "Information", "MessageTemplate": "Entered the Run method", "x-correlation-id": "00000000-0000-0000-0000-000000000000" }
内容的提问来源于stack exchange,提问作者TortillaCurtain
相关产品推荐
相关产品推荐

