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

时间:2018-08-29 19:17:45

标签: c# exception asp.net-core serilog

我正在使用Serilog记录有关IIS上托管的asp.net core 2.1应用程序的信息。发生例外情况时,会通过电子邮件通知我。事实是,发生了一些例外情况,而丝毫不伤害应用程序,我也不想每次发生时都被别人注意到。

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();
    }
}

编辑2:

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

谢谢

4 个答案:

答案 0 :(得分:4)

  

Serilog中是否有一种方法可以从中排除特定的异常类型   被记录?

我只会为该特定类型的异常创建一个空捕获,而在主体内部则什么也不做,例如

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

如果您想忽略更多的异常,我将创建一些额外的功能来检查是否要记录这种类型的错误。

// list of error codes:
// https://docs.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;
    }
}

然后在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");
}

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

答案 1 :(得分:2)

以下内容应该可以正常工作:

.Filter
   .ByExcluding(logEvent => 
       logEvent.Exception != null && 
       logEvent.Exception.GetType() == typeof(OperationCanceledException)
    )

答案 2 :(得分:1)

下面的代码可能会帮助您

catch (Exception ex)
{
    if (ex.GetType() != typeof(ExceptionTypeToExclude) ) {
         Log.Fatal(ex, "Host terminated unexpectedly");
    }
    return;
}

答案 3 :(得分:0)

您可以使用HashSet<TypeInfo>填充要排除的所有异常类型,然后检查其中是否包含当前的异常:

HashSet<TypeInfo> ignore = new HashSet<TypeInfo>();
ignore.Add(typeof(SomeExceptionType).GetTypeInfo());

//Add all the exceptions you want to exclude

您现在可以像这样测试您的异常类型:

try {
   //Critical code
}
catch (Exception e) {
    if (!ignore.Contains(e.GetType().GetTypeInfo())) //Do stuff
}

您需要添加using System.Reflection才能使用类型TypeInfo