You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:16:00