如何从 Serilog 中排除特定的异常类型?

Jim*_*ues 6 c# exception serilog asp.net-core

我正在使用 Serilog 来记录有关asp.net core 2.1托管在 IIS 上的应用程序的信息。发生异常时,我会收到电子邮件通知。问题是,一些异常发生时根本不会损害应用程序,我不想每次发生时都被注意到。

Serilog 中有没有办法从记录中排除特定的异常类型?

编辑 :

这是我在 Program.cs 中配置 Serilog 的方式:

using System;
using System.Data;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Sinks.MSSqlServer;

namespace WindZone_Warehouse_Mobile_App
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                .AddJsonFile(Environment.CurrentDirectory + "/appsettings.json")
                .Build();

            var columnOptions = new ColumnOptions {
                AdditionalDataColumns = new System.Collections.ObjectModel.Collection<DataColumn>
                {
                    new DataColumn {DataType = typeof (string), ColumnName = "email", DefaultValue = "myemail@myemail.com", MaxLength = 4000},
                    new DataColumn {DataType = typeof (string), ColumnName = "subject", DefaultValue = "Application error", MaxLength = 4000},
                }
            };
            columnOptions.Store.Remove(StandardColumn.Level);
            columnOptions.Store.Remove(StandardColumn.LogEvent);
            columnOptions.Store.Remove(StandardColumn.Message);
            columnOptions.Store.Remove(StandardColumn.MessageTemplate);
            columnOptions.Store.Remove(StandardColumn.Properties);
            columnOptions.Store.Remove(StandardColumn.TimeStamp);
            columnOptions.Exception.ColumnName = "message";
            columnOptions.Id.ColumnName = "id";
            columnOptions.DisableTriggers = true;

            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Information)
                .Enrich.FromLogContext()
                .Filter.ByExcluding(ObjectDisposedException) //What is the right way to tell Serilog to ignore this type of exception?
                .WriteTo.RollingFile("logs\\log-{Hour}.txt", retainedFileCountLimit: 168)
                .WriteTo.MSSqlServer(
                connectionString: configuration.GetConnectionString("DefaultConnection"),
                tableName: "emailtosend",
                columnOptions: columnOptions,
                restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error
                )
                .CreateLogger();

            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseSerilog();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

@reza baiat、@GoldenAge 和 @Alessandro Di Cicco:当然,您的回答将允许我处理异常,但仅限于发生在 Serilog 记录器之外的异常。Serilog 是一个日志库,它取代了 Microsoft 的默认库,使我能够省略其余代码中的所有 Try/Catch,因为它将全部记录在(在我的情况下)日志文件和 SQL 表中。我想做的事情是告诉 Serilog 不要记录,例如,ObjectDisposedException在关键代码中发生的异常。我猜我的代码中的 Try/Catch 令人困惑,所以我将从我的示例中删除它,因为它不相关。一旦应用程序构建并运行,Serilog 将捕获抛出的任何异常。我在想的可能是像这样的额外 Serilog 配置行: .Filter.ByExcluding(ObjectDisposedException)或类似的东西。是否可以?

谢谢

Grz*_*lko 14

在声明 LoggerConfiguration 时添加过滤器应该可以正常工作:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    ...
    .Filter
      .ByExcluding(logEvent => 
         logEvent.Exception != null && 
         logEvent.Exception.GetType() == typeof(OperationCanceledException))
    ...
    .CreateLogger();

Run Code Online (Sandbox Code Playgroud)

  • `logEvent.Exception is OperationCanceledException` 更加简洁,并且还将涵盖继承的类型。不需要空检查。 (2认同)

Gol*_*Age 1

编辑

让我澄清一下,我主要考虑的是生产代码,我仍然坚持之前编写的内容,即每个未处理的异常都应该由记录器记录,以便能够捕获一些通常您永远无法预测的边缘情况。如果您不同意,请写下评论,以便我们讨论。对于其他环境,例如本地主机,您可以使用Grzegorz Smulko 答案

回答:

Serilog 中有没有办法排除记录特定异常类型?

我只会为该特定类型的异常创建一个空捕获,并且在体内不执行任何操作,例如

try
{
    // invoke some function/s
}
catch (BlahException)
{
    // do nothing
}
catch (Exception e)
{
    Log.Fatal(ex, "Host terminated unexpectedly");
    // do something
}
finally
{
    Log.CloseAndFlush();
}
Run Code Online (Sandbox Code Playgroud)

如果您想忽略更多异常,我将创建一些额外的函数来检查您是否想记录此类错误。

// list of error codes:
// https://learn.microsoft.com/en-gb/windows/desktop/Debug/system-error-codes
public static bool IgnoreError(int errorCode)
{
    switch (errorCode)
    {
        case 16389:
            return true;
        case 16387:
            return true;
        default:
            return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在 catch 块内,您可以将异常代码传递给此方法。例如

try
{
    throw new ArgumentNullException("value");
}
catch (Exception e) 
{
    // Using an AND operation will retrieve the error code from the HRESULT:
    if (IgnoreError(e.HResult & 0xFFFF))
    {
        return;
    }
    Log.Fatal(e, "message");
}
Run Code Online (Sandbox Code Playgroud)

我认为每个未处理的异常都应该由记录器记录,因为这是它的主要职责。我看不出忽略记录未处理的异常有任何好处,并且不应该有这样的设置,这太可怕了!如果您知道在给定位置可能会发生异常,那么您应该创建 try 和 catch 块以捕获尽可能多的预期异常。然后,您可以决定是否要忽略 catch 块中的某些特定异常或否。