ASP.Net Core 5中Serilog静态Logger在IHost.Run()终止后无法输出日志及SelfLog启用问题
问题分析与解决方案
为什么IHost.Run()终止后日志无法输出?
核心原因在于你当前的Serilog集成方式中,IHost会接管全局Log.Logger的生命周期:当host.Run()终止(无论是正常退出还是异常崩溃),Host会释放所有注册的服务,其中就包括Serilog的日志提供者。这个过程会关闭或置无效全局的Log.Logger实例,导致后续catch/finally块中的日志调用完全失效。
另外你重复初始化了两次Logger:一次是CreateLogger()中的全局实例,一次是UseSerilog()中Host内部的实例,这也会导致生命周期管理混乱。
修复步骤
1. 保留全局Logger的生命周期
修改UseSerilog的调用,添加preserveStaticLogger: true参数,阻止Host在销毁时关闭全局的Log.Logger:
public static IHostBuilder CreateHostBuilder(string[] args) { BuildConfiguration(); IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) // 添加preserveStaticLogger: true,保留全局Logger实例 .UseSerilog((hostingContext, loggerConfiguration) => { loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration) .Enrich.With(new ThreadIdEnricher()); }, preserveStaticLogger: true); return hostBuilder .UseWindowsService() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseConfiguration(Configuration); webBuilder.UseStartup<Startup>(); webBuilder.UseHttpSys(options => { ... }); }); }
2. 整合Logger初始化逻辑(可选但推荐)
移除独立的CreateLogger()方法,将全局Logger的初始化整合到UseSerilog中,避免重复配置:
public static IHostBuilder CreateHostBuilder(string[] args) { BuildConfiguration(); IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) .UseSerilog((hostingContext, loggerConfiguration) => { // 初始化全局Logger Log.Logger = loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration) .Enrich.With(new ThreadIdEnricher()) .CreateLogger(); // 配置SelfLog Serilog.Debugging.SelfLog.Enable(msg => File.AppendAllText("serilog-selflog.txt", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {msg}{Environment.NewLine}") ); Serilog.Debugging.SelfLog.WriteLine("Serilog SelfLog initialized"); Log.Information("Application startup ..."); }, preserveStaticLogger: true); return hostBuilder .UseWindowsService() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseConfiguration(Configuration); webBuilder.UseStartup<Startup>(); webBuilder.UseHttpSys(options => { ... }); }); }
3. 优化SelfLog配置
你的SelfLog配置本身没问题,但之前因为Logger失效导致没有输出。现在可以将SelfLog输出到文件(而非仅控制台),更方便排查问题:
// 替换原Console输出,改为写入文件 Serilog.Debugging.SelfLog.Enable(msg => File.AppendAllText("serilog-selflog.txt", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {msg}{Environment.NewLine}") );
验证效果
修改完成后,当OptionsValidationException抛出并进入catch块时,Log.Fatal等日志会正常写入你的日志文件;finally块中的Log.CloseAndFlush()也能正确执行,确保所有缓存日志被写入。
内容的提问来源于stack exchange,提问作者sawie
相关产品推荐
相关产品推荐

