ASP.NET Core Web应用启动后Serilog日志无法正常输出的问题排查
我一眼就看到你代码里的致命问题——你在应用还没真正启动服务的时候,就把Serilog的日志管道给关了!这就像你刚打开水龙头准备接水,结果先把水管给拔了,后面自然没水流出来。下面给你详细拆解原因和修复方案:
核心问题:过早调用Log.CloseAndFlush()
看你的Program.cs,finally块里的Log.CloseAndFlush()居然放在app.Run()前面!app.Run()才是启动Web应用、处理用户请求的核心啊!当用户访问Index页面触发OnGet方法时,Serilog已经被你提前关闭了,那日志肯定打不出来。
另外,你一开始初始化的Log.Logger = new LoggerConfiguration().CreateLogger();是个空架子Logger,虽然之后用builder.Host.UseSerilog重新配置了,但这个空Logger不仅没用,还可能干扰后续的日志初始化。
修复步骤来咯
第一步:调整代码顺序,把日志关闭移到应用启动之后
正确的姿势应该是:先配置好Serilog,启动应用处理请求,等应用完全关闭后再清理日志。
第二步:修正后的Program.cs代码
把try/catch/finally的位置彻底调整,确保app.Run()在日志关闭前执行:
using Serilog; var builder = WebApplication.CreateBuilder(args); // 先把Serilog配置好,替换掉默认的日志系统 builder.Host.UseSerilog((ctx, lc) => lc .ReadFrom.Configuration(ctx.Configuration) .Enrich.FromLogContext() .Enrich.WithMachineName() .Enrich.WithProcessId() .Enrich.WithThreadId() ); // 添加RazorPages服务 builder.Services.AddRazorPages(); var app = builder.Build(); app.UseSerilogRequestLogging(); try { Log.Information("--> App is starting up ...."); // 配置HTTP请求管道 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); // 启动应用,这会一直阻塞到应用关闭 await app.RunAsync(); } catch (Exception e) { Log.Fatal(e, "The app failed to start bruh!!"); throw; } finally { // 等应用彻底关闭了,再关闭日志 Log.CloseAndFlush(); }
第三步:优化appsettings.json(可选但推荐)
你的配置本身没问题,但可以把Using数组补全,明确指定用到的Serilog组件,让配置更清晰:
{ "AllowedHosts": "*", "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Enrichers.Environment", "Serilog.Enrichers.Process", "Serilog.Enrichers.Thread" ], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning" } }, "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], "WriteTo": [ { "Name": "Console" } ] } }
验证效果
现在启动应用,访问Index页面,你就能看到所有想要的日志了:
- 启动时的
--> App is starting up .... - OnGet开头的
My exercise app web app logging is here <---- - 循环计数的
the value {LoopCountValue}(一直到i=56) - 捕获异常后的
--> I caught you man yoooo!! <<***--错误日志
小提醒
用await app.RunAsync()代替app.Run()能更好地配合ASP.NET Core的异步生命周期,确保日志在应用完全停止后才被清理。而且builder.Host.UseSerilog已经会自动把Serilog设为默认日志提供器,不需要手动初始化那个空的Log.Logger啦!
内容的提问来源于stack exchange,提问作者Soner from The Ottoman Empire

