如何在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
相关产品推荐
相关产品推荐

