.NET Core 3.1配置未就绪时如何初始化Serilog日志组件
.NET Core 3.1 场景下基于IConfiguration配置Serilog的正确实现
首先纠正一个常见认知偏差:IConfiguration的基础初始化不是在Startup类执行阶段才完成的。WebHost.CreateDefaultBuilder方法运行时,就会按照默认规则完成appsettings.json、appsettings.{Environment}.json、环境变量、命令行参数等配置源的加载,构建出可用的IConfiguration实例,这个时机远早于Startup类的实例化和执行,你完全可以在UseSerilog的委托中直接获取到该实例,不需要提前在Main方法中手动构建配置。
具体实现步骤
- 调整Main方法逻辑,移除提前手动初始化完整Serilog实例的代码,可选配置引导日志器捕获启动早期异常
- 在
UseSerilog的委托参数中,通过主机上下文获取已构建完成的IConfiguration实例,完成Serilog配置 - 若有自定义配置源,将配置源注册逻辑从Startup挪到
ConfigureAppConfiguration阶段,保证Serilog初始化时可读取到完整配置
1. Main方法实现
不需要提前手动构建IConfiguration,可先初始化一个极简的引导日志器,用来捕获主机构建启动阶段的异常,等正式的日志器初始化完成后会自动替换全局Log.Logger实例:
public static int Main(string[] args) { // 初始化引导日志器,仅做最简控制台输出,覆盖主机启动最早期的日志需求 Log.Logger = new LoggerConfiguration() .WriteTo.Console() .CreateBootstrapLogger(); try { Log.Information("Web host starting up"); var host = CreateWebHostBuilder(args).Build(); host.Run(); return 0; } catch (Exception ex) { Log.Fatal(ex, "Web host terminated unexpectedly"); return 1; } finally { Log.CloseAndFlush(); } }
2. WebHost构建阶段配置Serilog
在UseSerilog传入的委托中,直接通过context.Configuration获取已加载完成的配置实例,完成Serilog的配置加载,此时Serilog的初始化时机早于Startup执行,完全满足早期日志记录的要求:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) { return WebHost .CreateDefaultBuilder(args) // 所有自定义配置源统一在这里注册,不要放在Startup类中 .ConfigureAppConfiguration((context, configBuilder) => { // 示例:添加自定义配置源,如Apollo配置中心、自定义Json文件、数据库配置等 // configBuilder.AddJsonFile("customConfig.json", optional: true); // configBuilder.AddApollo(...); }) .UseStartup<Startup>() .UseSerilog((context, loggerConfiguration) => { // 直接读取已构建完成的IConfiguration实例加载Serilog配置 loggerConfiguration.ReadFrom.Configuration(context.Configuration); // 保留原有环境差异化配置逻辑 if (context.HostingEnvironment.IsDevelopment()) { loggerConfiguration.WriteTo.Console(LogEventLevel.Debug); return; } loggerConfiguration.WriteTo.ApplicationInsights(TelemetryConverter.Traces, LogEventLevel.Error); }); }
关键说明
- 执行顺序保证:
CreateDefaultBuilder加载默认配置 ->ConfigureAppConfiguration加载自定义配置 ->UseSerilog委托执行,用完整配置初始化全局Serilog实例 -> Startup类执行 -> 主机运行。不存在UseSerilog执行时日志未配置的问题。 - 如果自定义配置源写在Startup.ConfigureServices中,执行时机晚于UseSerilog,Serilog自然读不到这部分配置,这也是很多人误以为配置要等Startup执行完才可用的核心原因。只要把自定义配置源的注册挪到
ConfigureAppConfiguration阶段即可解决。
内容的提问来源于stack exchange,提问作者Jakob Busk Sørensen
相关产品推荐
相关产品推荐

