【发布时间】:2021-03-11 09:52:59
【问题描述】:
使用 Serilog 的 ASP.NET Core 5 Razor 页面
UseStatusCodePagesWithReExecute 按预期工作,并在进入我的 /CustomError 页面后重新执行页面。
如何抑制对重新执行页面的第二次调用的 Serilog 日志记录?
password-postgres 完整样本
// program.cs
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
// if only do warning, then will get duplicate error messages when an exception is thrown, then again when re-executed
// we do get 2 error message per single error, but only 1 stack trace
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Fatal)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
try
{
Log.Information("Starting up");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // <- Add this line
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
然后
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// snip
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/CustomError");
}
app.UseStaticFiles();
// https://khalidabuhakmeh.com/handle-http-status-codes-with-razor-pages
// https://andrewlock.net/retrieving-the-path-that-generated-an-error-with-the-statuscodepages-middleware/
app.UseStatusCodePagesWithReExecute("/CustomError", "?statusCode={0}");
app.UseRouting();
// don't want request logging for static files so put this serilog middleware here in the pipeline
app.UseSerilogRequestLogging(); // <- add this
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Strict });
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
然后
// CustomError.cshtml.cs
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class CustomErrorModel : PageModel
{
public int? CustomStatusCode { get; set; }
public void OnGet(int? statusCode = null)
{
var feature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
// a non 500 eg 404
// this can be non page requests eg /js/site-chart.js
// feature can be null when a 500 is thrown
if (feature != null)
{
//Log.Warning($"Http Status code {statusCode} on {feature.OriginalPath}");
CustomStatusCode = statusCode;
return;
}
// a 500
// relying on serilog to output the error
//var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
// integration tests can call a page where the exceptionHandlerPathFeature can be null
CustomStatusCode = 500;
// somewhere else is emitting the Log.Error stacktracke
//Log.Error($"Exception is {exceptionHandlerPathFeature.Error}");
//OriginalPath = exceptionHandlerPathFeature.Path;
//Exception exception = exceptionHandlerPathFeature.Error;
}
public void OnPost()
{
Log.Warning( "ASP.NET failure - maybe antiforgery. Caught by OnPost Custom Error. Sending a 400 to the user which is probable");
Log.Warning("Need to take off minimumlevel override in Program.cs for more information");
CustomStatusCode = 400;
}
}
错误的重复日志条目,例如 404 - 理想情况下只需要 1 个
更新
感谢 Alan 在下面的回答,我已将 SerilogRequestLogging 放在配置的开头。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSerilogRequestLogging();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/CustomError");
}
app.UseStaticFiles();
app.UseStatusCodePagesWithReExecute("/CustomError", "?statusCode={0}");
// snip..
}
这会在日志中提供 2 条 ERR 消息:
我觉得很好。
可能有一种方法可以合并 2 个ERR 条目,但这很简单。这两个条目也适用于不同的概念。请求和例外。
可以像样板文件 Error.cshtml.cs 给出的那样,为每个日志条目提供 RequestId。
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
但是,嘿,这个解决方案对我来说已经足够好了。谢谢艾伦!
【问题讨论】:
标签: c# asp.net-core razor-pages serilog