.NET 6 Web应用如何实现Shutdown Hook记录终止日志?
解决ASP.NET Core 6中Serilog无法记录应用终止事件的问题
问题原因
- 事件触发条件错误:在Visual Studio的IIS Express宿主环境下,关闭浏览器标签页不会直接终止应用——ASP.NET Core应用会保持 idle 状态,直到超时回收或手动停止调试。只有手动点击调试工具栏的「停止」按钮,或控制台宿主下按
Ctrl+C,才会触发ApplicationStopping和ApplicationStopped事件。 - Serilog日志未及时刷新:异步写入的日志 sink(如文件、控制台)可能在应用终止前未完成写入,导致日志丢失。
解决方案
1. 正确触发终止事件
在Visual Studio中测试时,不要通过关闭浏览器终止应用,而是:
- 点击调试工具栏的「停止」按钮(▶️旁边的方形按钮)
- 若使用控制台宿主(通过
dotnet run启动),按Ctrl+C组合键
2. 配置Serilog确保日志写入完整
在应用启动时配置Serilog,并在关闭事件中手动刷新日志,避免丢失:
var builder = WebApplication.CreateBuilder(args); // 配置Serilog,替换为你的日志输出目标 builder.Host.UseSerilog((context, config) => { config.WriteTo.Console() .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day) .Enrich.FromLogContext(); }); // 注册服务 builder.Services.AddControllers(); var app = builder.Build(); var logger = app.Services.GetRequiredService<ILogger<Program>>(); // 注册应用生命周期事件 app.Lifetime.ApplicationStarted.Register(() => { logger.LogInformation("应用已启动,开始运行"); }); app.Lifetime.ApplicationStopping.Register(() => { logger.LogInformation("应用进入关闭流程"); // 手动刷新Serilog日志,确保所有待写入日志完成 Log.CloseAndFlush(); }); app.Lifetime.ApplicationStopped.Register(() => { // 此事件触发时部分服务已释放,建议直接使用Serilog静态类 Log.Information("应用已完全终止"); Log.CloseAndFlush(); }); // 中间件配置 app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 优先使用ApplicationStopping记录关键日志
ApplicationStopped事件触发时,应用的服务容器已开始释放,部分依赖可能不可用。建议将核心的关闭日志放在ApplicationStopping事件中,此阶段服务仍处于可用状态。
内容的提问来源于stack exchange,提问作者Green Grasso Holm
相关产品推荐
相关产品推荐

