如何抑制“执行请求时发生未处理的异常。”使用 Serilog 记录消息

问题描述 投票:0回答:3

当使用

app.UseExceptionHandler
和异常处理程序 lambda/委托(文档)实现我自己的异常处理程序时,我不希望 Microsoft 异常处理程序中间件 记录此错误:

执行请求时发生未处理的异常。

此异常消息使我的日志文件变得混乱,因为我自己使用适当的 LogLevel 来记录异常。

这就是我注册自己的 ErrorHandler 的方式:

app.UseExceptionHandler(errorApp =>
                errorApp.Run(ErrorHandler));

此问题中所述,过滤此确切消息并且没有其他以简单的方式是不可能的。

如何过滤这个确切的日志消息而不从中间件中过滤任何其他内容?

我正在使用:

  • ASP.NET Core 3.1
  • Serilog 3.4.0
asp.net-core exception logging .net-core serilog
3个回答
4
投票

正如上面提到的问题中所描述的,我们可以使用过滤表达式来实现这一点。不幸的是,该问题仅描述了已弃用包的解决方案,并且过滤了来自中间件的所有消息,而不仅仅是提到的消息。

  1. 安装Serilog.Expressions
  2. 使用此配置更新匹配的
    appsettings.json
  "Serilog": {
    "Using": [ "Serilog.Expressions" ],
    "Filter": [
      {
        "Name": "ByExcluding",
        "Args": {
          "expression": "@l='Error' and SourceContext='Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware' and @mt='An unhandled exception has occurred while executing the request.'"
        }
      }
    ]
  }
  1. 确保您具有从
    appsettings.json
    如文档中加载配置的匹配代码,例如:
Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();

这样您就可以保留来自

ExceptionHandlerMiddleware
的所有其他消息,并且只需禁用冗余错误日志消息。

旁注:如果响应已经开始,我们的自定义异常处理程序将不会被执行 - 但将记录一条警告,并且异常将被重新抛出并稍后由另一个应用程序层记录 - 至少在我测试的应用程序中。您可以通过在引发异常之前的某个位置添加此代码来测试此行为(

context
是当前的 HttpContext):

 await context.Response.WriteAsync("fish");

1
投票

我在程序中用自定义中间件替换了 app.UseExceptionHandler ,它的工作原理就像一个魅力。

启动.cs:

app.UseMiddleware<HttpExceptionMiddleware>();

HttpExceptionMiddleware.cs

using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;

internal class HttpExceptionMiddleware
{
    private readonly RequestDelegate next;

    public HttpExceptionMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await this.next.Invoke(context);
        }
        catch (HttpException e)
        {
            var response = context.Response;
            if (response.HasStarted)
            {
                throw;
            }
            response.StatusCode = (int) e.StatusCode;
            response.ContentType = "application/json; charset=utf-8";
            response.Headers[HeaderNames.CacheControl] = "no-cache";
            response.Headers[HeaderNames.Pragma] = "no-cache";
            response.Headers[HeaderNames.Expires] = "-1";
            response.Headers.Remove(HeaderNames.ETag);

            var bodyObj = new {
                Message = e.Message,
                Status = e.StatusCode.ToString()
            };
            var body = JsonSerializer.Serialize(bodyObj);
            await context.Response.WriteAsync(body);
        }
    }
}

HTTPException.cs

using System;
using System.Net;

public class HttpException : Exception
{
    public HttpStatusCode StatusCode { get; }

    public HttpException(HttpStatusCode statusCode)
    {
        this.StatusCode = statusCode;
    }

    public HttpException(int httpStatusCode)
        : this((HttpStatusCode) httpStatusCode)
    {
    }

    public HttpException(HttpStatusCode statusCode, string message)
        : base(message)
    {
        this.StatusCode = statusCode;
    }

    public HttpException(int httpStatusCode, string message)
        : this((HttpStatusCode) httpStatusCode, message)
    {
    }

    public HttpException(HttpStatusCode statusCode, string message, Exception inner)
        : base(message, inner)
    {
    }

    public HttpException(int httpStatusCode, string message, Exception inner)
        : this((HttpStatusCode) httpStatusCode, message, inner)
    {
    }
}

0
投票

我想我找到了更简单的解决方案:

"Serilog": {
  "MinimumLevel": {
    ...
    "Override": {
      ...
      "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "Fatal"
    }
  }

技巧是

ExceptionHandlerMiddleware
日志的情人级别=错误,但级别=致命在上面。

© www.soinside.com 2019 - 2024. All rights reserved.