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

如何在Serilog表达式格式中实现单行异常的自定义JSON日志输出?

Serilog自定义JSON日志异常重复问题解决及目标格式实现

当前配置与问题

现有Serilog表达式模板

"template": "{{\"Time\": \"{@t:yyyy-MM-ddTHH:mm:ss.fffffffzzz}\", \"Level\": \"{@l}\", \"Event\": \"{@m}\" {#if TraceId is not null}(, \"TraceId\": \"{@tr}\" ){#end} \"context\": {@p} , \"exception\":\"{@x}\"}}\n"

遇到的问题

  • 日志包含多行异常时,原始@x输出会破坏JSON结构
  • 自定义Enricher修复换行问题后,异常被加入到@p(上下文属性集合)中,导致exception字段与context.Exception重复显示

自定义Enricher代码:

using Serilog.Core;
using Serilog.Events;
using System;

namespace CatalogService.Common.Enricher
{
    public class CustomLogEnricher : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            if (logEvent?.Exception != null)
            {
                string? formattedException = logEvent.Exception.ToString().Replace(Environment.NewLine, "\\n");

                logEvent.RemovePropertyIfPresent("Exception");
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Exception", formattedException));
            }
        }
    }
}

期望的日志格式

{
  "time": "2024-05-20T12:34:56.7890123+08:00",
  "level": "Error",
  "event": "Failed to process request",
  "exception": "System.NullReferenceException: Object reference not set to an instance of an object\\n   at MyService.Method() in C:\\code\\MyService.cs:line 42",
  "context": {
    "RequestId": "abc123",
    "UserId": "user456"
  }
}

解决方案

方案1:模板内直接处理异常换行(推荐)

无需自定义Enricher,利用Serilog Expressions的replace函数在模板中直接将异常的换行符转义,同时避免属性重复:

修改后的模板:

"template": "{{\"time\": \"{@t:yyyy-MM-ddTHH:mm:ss.fffffffzzz}\", \"level\": \"{@l}\", \"event\": \"{@m}\" {#if TraceId is not null}(, \"traceId\": \"{@tr}\" ){#end}{#if @x is not null}(, \"exception\": \"{replace(@x, '\n', '\\n')}\" ){#end}, \"context\": {@p} }}\n"
  • replace(@x, '\n', '\\n')将异常中的换行符替换为JSON兼容的转义格式
  • 仅在存在异常时输出exception字段,避免空值
  • 不需要Enricher,自然不会出现context.Exception重复的问题

方案2:保留Enricher并排除重复属性

如果必须保留自定义Enricher,可在模板中使用exclude函数从@p中移除Exception属性,避免重复:

完整模板:

"template": "{{\"time\": \"{@t:yyyy-MM-ddTHH:mm:ss.fffffffzzz}\", \"level\": \"{@l}\", \"event\": \"{@m}\" {#if TraceId is not null}(, \"traceId\": \"{@tr}\" ){#end}, \"exception\":\"{@x}\", \"context\": {exclude(@p, 'Exception')} }}\n"
  • exclude(@p, 'Exception')会从上下文属性集合中移除Exception字段
  • 配合原Enricher的异常格式化,实现目标格式且无重复

内容的提问来源于stack exchange,提问作者ayush garg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:44:50