在Serilog中记录异常时减少堆栈跟踪帧数的方法
解决Serilog限制异常堆栈跟踪长度的问题
你说的maximumDestructuringDepth是用来控制复杂对象解构的嵌套深度,和异常堆栈跟踪的截断完全不搭边,所以它解决不了你的问题。下面给你两种针对性的解决方案:
方案1:仅保留异常消息(完全移除堆栈跟踪)
如果只需要记录异常消息,不需要堆栈跟踪,有两种实现方式:
方式A:修改输出模板
直接在appsettings.json的File/Console sink配置里指定输出模板,去掉{Exception}字段即可:
"WriteTo": [ { "Name": "File", "Args": { "path": "./logs/log-.txt", "rollingInterval": "Day", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}" } } ]
方式B:自定义异常解构策略
如果需要保留异常的基础信息但去掉堆栈,可以写一个自定义的解构策略,只提取异常的核心信息:
public class ExceptionMessageOnlyPolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { if (value is Exception ex) { result = propertyValueFactory.CreatePropertyValue(new { ex.Message, ex.Source }, destructureObjects: false); return true; } result = null; return false; } }
然后在Serilog配置里添加这个策略:
builder.Host.UseSerilog((context, services, configuration) => configuration .ReadFrom.Configuration(context.Configuration) .ReadFrom.Services(services) .Enrich.FromLogContext() .Destructure.With<ExceptionMessageOnlyPolicy>()); // 新增这一行
方案2:保留堆栈跟踪的第一帧
如果需要保留堆栈的第一行信息,可以通过解析StackTrace实现,同样用自定义解构策略:
public class LimitedStackTracePolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { if (value is Exception ex) { var firstStackFrame = string.Empty; if (!string.IsNullOrEmpty(ex.StackTrace)) { // 拆分堆栈文本,取第一行内容 firstStackFrame = ex.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? string.Empty; } result = propertyValueFactory.CreatePropertyValue(new { ex.Message, ex.Source, StackTrace = firstStackFrame }, destructureObjects: false); return true; } result = null; return false; } }
然后把这个策略注册到Serilog配置中:
builder.Host.UseSerilog((context, services, configuration) => configuration .ReadFrom.Configuration(context.Configuration) .ReadFrom.Services(services) .Enrich.FromLogContext() .Destructure.With<LimitedStackTracePolicy>());
额外提示
- 只要你是用
Log.Error(ex, "发生错误")这种带异常参数的方式记录日志,上述策略都会自动生效; - 如果只想针对特定异常(比如实体未找到的自定义异常)生效,可以在策略里添加类型判断:
if (value is EntityNotFoundException ex) // 替换成你要处理的目标异常类型 { // 这里写对应的处理逻辑 }
内容的提问来源于stack exchange,提问作者thran
相关产品推荐
相关产品推荐

