当使用
app.UseExceptionHandler
和异常处理程序 lambda/委托(文档)实现我自己的异常处理程序时,我不希望 Microsoft 异常处理程序中间件 记录此错误:
执行请求时发生未处理的异常。
此异常消息使我的日志文件变得混乱,因为我自己使用适当的 LogLevel 来记录异常。
这就是我注册自己的 ErrorHandler 的方式:
app.UseExceptionHandler(errorApp =>
errorApp.Run(ErrorHandler));
如此问题中所述,过滤此确切消息并且没有其他以简单的方式是不可能的。
如何过滤这个确切的日志消息而不从中间件中过滤任何其他内容?
我正在使用:
正如上面提到的问题中所描述的,我们可以使用过滤表达式来实现这一点。不幸的是,该问题仅描述了已弃用包的解决方案,并且过滤了来自中间件的所有消息,而不仅仅是提到的消息。
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.'"
}
}
]
}
appsettings.json
如文档中加载配置的匹配代码,例如:Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
这样您就可以保留来自
ExceptionHandlerMiddleware
的所有其他消息,并且只需禁用冗余错误日志消息。
旁注:如果响应已经开始,我们的自定义异常处理程序将不会被执行 - 但将记录一条警告,并且异常将被重新抛出并稍后由另一个应用程序层记录 - 至少在我测试的应用程序中。您可以通过在引发异常之前的某个位置添加此代码来测试此行为(
context
是当前的 HttpContext):
await context.Response.WriteAsync("fish");
我在程序中用自定义中间件替换了 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)
{
}
}
我想我找到了更简单的解决方案:
"Serilog": {
"MinimumLevel": {
...
"Override": {
...
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "Fatal"
}
}
技巧是
ExceptionHandlerMiddleware
日志的情人级别=错误,但级别=致命在上面。