lonix
lonix

Reputation: 20709

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?

Upvotes: 1

Views: 2190

Answers (3)

lonix
lonix

Reputation: 20709

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();

Upvotes: 0

FantasticFiasco
FantasticFiasco

Reputation: 1193

I've run into the same issue, and I created a method with the responsibility to configure the builder. I then call the method from both Main and when I build the web host. Something like this:

public static class Program
{
  public static int Main()
  {
    var configuration = new ConfigurationBuilder()
      .AddConfiguration()
      .Build();

    // setup Serilog logging
    Log.Logger = new LoggerConfiguration()
      .ReadFrom.Configuration(configuration)
      .CreateLogger();

    // Code removed for brevity...
  }

  private static IWebHost BuildWebHost() =>
    WebHost.CreateDefaultBuilder()
      .UseSerilog()
      .UseStartup<Startup>()
      .ConfigureAppConfiguration((hostingContext, config) =>
      {
        // Clear default configuration
        config.Sources.Clear();

        // Replace with our own configuration
        config.AddConfiguration();
      })
      .Build();

  private static IConfigurationBuilder AddConfiguration(this IConfigurationBuilder self) =>
    self
      .SetBasePath(Directory.GetCurrentDirectory())
      .AddJsonFile("appsettings.json", optional:false, reloadOnChange:true)
      .AddJsonFile($"appsettings.{envName}.json", optional:true, reloadOnChange:true)
      .AddEnvironmentVariables();
}

Upvotes: 1

Stephen Zeng
Stephen Zeng

Reputation: 2818

From the document it is by design:

"UseConfiguration only copies keys from the provided IConfiguration to the host builder configuration. Therefore, setting reloadOnChange: true for JSON, INI, and XML settings files has no effect."

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.1&tabs=aspnetcore2x

Upvotes: 3

Related Questions