Search code examples
c#asp.net-coreserilogasp.net-core-2.1

Start logging before webhost in ASP.NET Core 2


I want to start logging before webhost, so startup errors are logged. So I followed Serilog's recommended init order: 1) configuration, 2) logging, 3) webhost. I'm not using CreateDefaultBuilder().

So my Program.cs has:

// setup config
var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
var configuration = new ConfigurationBuilder()
  .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional:false, reloadOnChange:true)
  .AddJsonFile($"appsettings.{envName}.json", optional:true, reloadOnChange:true)
  .AddEnvironmentVariables()
  .AddCommandLine(args)
  .Build();

// setup Serilog logging
Log.Logger = new LoggerConfiguration()
  .ReadFrom.Configuration(configuration)            // <<< uses config from above
  .CreateLogger()

// setup webhost
new WebHostBuilder()
  .UseConfiguration(configuration)                  // <<< uses config from above
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseStartup<Startup>()
  .UseSerilog()
  .Build()
  .Run();

This works, but changes in appsettings.json are not detected even though I specified reloadOnChange:true.

However when I use ConfigureAppConfiguration() then changes are detected:

new WebHostBuilder()
  .ConfigureAppConfiguration((context, config) => {
    // .. duplicate config here
  })
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseStartup<Startup>()
  .UseSerilog()
  .Build()
  .Run();

But that means duplication and possibly unforseen problems - i.e. this is a hack. How do I solve this?

UPDATE

As per @StephenZeng's answer, UseConfiguration won't help me here, so I suppose I need to use ConfigureAppConfiguration. But the problem remains - how do I init my config first, then use it multiple times without redefining it?


Solution

  • The solution is to avoid UseConfiguration and use ConfigureAppConfiguration instead:

    // setup config
    // ..as before
    // ..this is done only once
    
    // setup Serilog logging
    // ...as before
    
    // setup webhost
    new WebHostBuilder()
      .ConfigureAppConfiguration((context, config) => {
        config.AddConfiguration(configuration);  // <<< uses config from above
      })
      .UseKestrel()
      .UseContentRoot(Directory.GetCurrentDirectory())
      .UseStartup<Startup>()
      .UseSerilog()
      .Build()
      .Run();