serilog / serilog-extensions-hosting

Serilog logging for Microsoft.Extensions.Hosting
Apache License 2.0
141 stars 34 forks source link

BootstrapLogger and reading config from appsettings (using Serilog.Settings.Configuration) not playing well together #88

Open gthvidsten opened 7 months ago

gthvidsten commented 7 months ago

I'm following the example and have the following code:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .CreateBootstrapLogger();

try
{
    Log.Information("Starting");

    HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
    builder.Services.AddSerilog((services, loggerConfiguration) =>
    {
        loggerConfiguration
            .ReadFrom.Configuration(builder.Configuration)
            .ReadFrom.Services(services);
    });

    IHost host = builder.Build();
    await host.RunAsync();

    Log.Information("Stopping");
}
catch (Exception ex)
{
    Log.Fatal(ex, "Failing");
}
finally
{
    await Log.CloseAndFlushAsync();
}

And this appsettings.json:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "Filename.log",
          "fileSizeLimitBytes": "10485760",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "retainedFileCountLimit": 30
        }
      }
    ],
    "Enrich": [ "FromLogContext" ]
  }
}

Using the following packages:

<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

When starting this I would expect all the messages appearing in Filename.log, but the "Starting" message appears in the Console. Everything else appears in the file as expected. Why doesn't the "Starting" message appear in the log file, and what can I do to have everything appear in the file? (and everything logged to console if something fails)

nblumhardt commented 7 months ago

Hi @gthvidsten; at the point Log.Information("Starting") is called, the bootstrap logger hasn't been reconfigured to write to the file, yet.

If you can move everything to the initial LoggerConfiguration (and customize the file path using environment variables, perhaps?) you can get around this:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File(...)
    .CreateLogger();

try
{
    Log.Information("Starting");

    HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
    builder.Services.AddSerilog();

    IHost host = builder.Build();
    await host.RunAsync();

    Log.Information("Stopping");
}
catch (Exception ex)
{
    Log.Fatal(ex, "Failing");
}
finally
{
    await Log.CloseAndFlushAsync();
}
gthvidsten commented 7 months ago

Thanks for the reply. I really don't want to have to read configurations this soon in the startup, but I see I might have been mistaken about how the BootstrapLogger is working:

I thought that it would create a logger, but not log anything to it until .AddSerilog() had been properly called, so that any messages logged before this would be cached and written to the correct place when it was available, and writing to the defaults only happens if something went wrong.

For now I may just remove the "Starting" message alltogether, though I'm open to other suggestions, of course :)

nblumhardt commented 7 months ago

The buffering style of design would be very interesting to explore, but you're correct - that's not how CreateBootstrapLogger() works today.