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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:43:17