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

如何配置Serilog与Sentry忽略指定异常?从配置文件读取忽略列表

解决Serilog+Sentry忽略指定异常不生效的问题

问题根源

  1. 配置的异常类型不完整:你在appsettings.json里只写了NotImplementedException,但代码中判断的是异常类型的完整命名空间+类型名(比如System.NotImplementedException),导致匹配失败。
  2. Sentry中间件与Serilog的冲突:builder.WebHost.UseSentry()会独立捕获未处理异常,绕开Serilog的过滤逻辑。
  3. 过滤逻辑仅检查顶层异常:未考虑异常链中的内部异常,若异常被包装则无法被识别。

分步解决方案

1. 修正配置文件的异常类型

修改appsettings.json中Serilog:IgnoreList:ExceptionTypes,补充完整命名空间:

{
  "Logfile": {"Name": "/logs/log-Service-.txt"},
  "Sentry": {"Dsn": "https://sentry.dns"},
  "Serilog": {
    "IgnoreList": {
      "ExceptionTypes": ["System.NotImplementedException"]
    }
  },
  "ConnectionStrings": {"DefaultConnection": "myconnection"}
}

2. 优化Serilog的Sentry过滤逻辑

更新SetBeforeSend逻辑,递归检查整个异常链:

public static class HostBuilderExtensions
{
    public static IHostBuilder UseCustomSerilog(this IHostBuilder builder, IConfiguration configuration)
    {
        var ignoreList = configuration.GetSection("Serilog:IgnoreList:ExceptionTypes").Get<string[]>() ?? Array.Empty<string>();

        return builder.UseSerilog((context, config) =>
        {
            config.MinimumLevel.Verbose()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Fatal)
                .WriteTo.Udp(
                    remoteAddress: configuration.GetSection("Logstash")["Host"] ?? throw new InvalidOperationException(),
                    remotePort: int.Parse(configuration.GetSection("Logstash")["Port"] ?? throw new InvalidOperationException()),
                    family: AddressFamily.InterNetwork, formatter: new CompactJsonFormatter()
                )
                .Enrich.WithProperty("type", configuration.GetSection("Logstash")["Type"] ?? throw new InvalidOperationException())
                .WriteTo.File(
                    new CompactJsonFormatter(),
                    configuration.GetSection("Logfile")["Name"] ?? throw new InvalidOperationException(),
                    rollingInterval: RollingInterval.Day
                )
                .WriteTo.Console()
                .WriteTo.Sentry(o =>
                {
                    o.Dsn = configuration.GetSection("Sentry")["Dsn"];
                    o.MinimumEventLevel = LogEventLevel.Error;
                    o.MinimumBreadcrumbLevel = LogEventLevel.Error;
                    o.SetBeforeSend((sentryEvent, _) =>
                    {
                        if (ShouldIgnoreException(sentryEvent.Exception, ignoreList))
                        {
                            Console.WriteLine("Ignored");
                            return null;
                        }
                        return sentryEvent;
                    });
                })
                .Enrich.FromLogContext();
        });
    }

    // 递归检查异常链的辅助方法
    private static bool ShouldIgnoreException(Exception? ex, IEnumerable<string> ignoreTypes)
    {
        if (ex == null) return false;
        // 检查当前异常是否在忽略列表
        if (ignoreTypes.Contains(ex.GetType().FullName))
        {
            return true;
        }
        // 递归检查内部异常
        return ShouldIgnoreException(ex.InnerException, ignoreTypes);
    }
}

3. 处理Sentry中间件的冲突

以下两种方案任选其一:

方案A:禁用Sentry自身的异常捕获

让所有异常都通过Serilog处理,关闭Sentry中间件的自动捕获:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 修改Sentry配置,禁用自动捕获
builder.WebHost.UseSentry(options =>
{
    options.Dsn = builder.Configuration.GetSection("Sentry")["Dsn"];
    options.EnableGlobalErrorCapture = false; // 关闭全局异常捕获
    options.AutoSessionTracking = false;
    options.CaptureConsole = false;
});

builder.Host.UseCustomSerilog(builder.Configuration);

// 后续代码不变...

方案B:在Sentry中间件中添加过滤

若需要保留Sentry中间件的其他功能,同步添加配置文件中的忽略规则:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var ignoreList = builder.Configuration.GetSection("Serilog:IgnoreList:ExceptionTypes").Get<string[]>() ?? Array.Empty<string>();

builder.WebHost.UseSentry(options =>
{
    options.Dsn = builder.Configuration.GetSection("Sentry")["Dsn"];
    // 从配置文件添加异常过滤
    foreach (var typeName in ignoreList)
    {
        var exceptionType = Type.GetType(typeName);
        if (exceptionType != null)
        {
            // 通过反射调用泛型方法添加过滤
            var filterMethod = typeof(SentryAspNetCoreOptionsExtensions)
                .GetMethod(nameof(SentryAspNetCoreOptionsExtensions.AddExceptionFilterForType))
                ?.MakeGenericMethod(exceptionType);
            filterMethod?.Invoke(null, new[] { options });
        }
    }
});

builder.Host.UseCustomSerilog(builder.Configuration);

// 后续代码不变...

内容的提问来源于stack exchange,提问作者Ahmed Elshorbagy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:36:06