serilog-sinks-file icon indicating copy to clipboard operation
serilog-sinks-file copied to clipboard

CreateBootstrapLogger with file sink throws "File in use" exception sometimes

Open rmtexas opened this issue 1 year ago • 1 comments

Minor issue that might deserve a fix or at least a mention of the solution below added to doumentation somewhere or in the LoggerSinkConfiguration.File extension method summary.

Description Configuring both the boot strap logger and the main logger both with WriteTo.File to the same file path can frequently cause a "File in use" exception on the main logger.

Reproduction


          Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .MinimumLevel.Override("MassTransit", LogEventLevel.Debug)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
                .MinimumLevel.Override("Azure.Messaging.ServiceBus", LogEventLevel.Warning)
                .MinimumLevel.Override("Azure.Core", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} <{SourceContext}> {Level:u3}] {Message:lj}{NewLine}{Exception}")
    #if DEBUG
                .WriteTo.File(@$"C:\tmp\logs\{Assembly.GetEntryAssembly()?.GetName().Name ?? "un-configured"}.log")
    #else
                .WriteTo.Seq(seqUrl, apiKey: seqApiKey)
    #endif
                .CreateBootstrapLogger();

            loggerConfiguration
                .MinimumLevel.Information()
                .MinimumLevel.Override("MassTransit", LogEventLevel.Debug)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
                .MinimumLevel.Override("Azure.Messaging.ServiceBus", LogEventLevel.Warning)
                .MinimumLevel.Override("Azure.Core", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} <{SourceContext}>{Level:u3}] {Message:lj}{NewLine}{Exception}")
    #if DEBUG
                .WriteTo.File(@$"C:\tmp\logs\{Assembly.GetEntryAssembly()?.GetName().Name ?? "un-configured"}.log");
    #else
                .WriteTo.Seq(seqUrl, apiKey: seqApiKey);
    #endif


Expected behavior It should be ensure the reloadable logger flushes and closes the file handle, before it it reconfigured.

Relevant package, tooling and runtime versions What Serilog.Sinks.File version are you using, on what platform? .Net Core 8 Serilog.Sinks.File 5.0.0 Windows

Additional context I found adding the "shared: true" to both the WriteTo.File statements seems to resolve the issue.

rmtexas avatar Aug 02 '24 23:08 rmtexas

Thanks for the note. A more detailed code example and stack trace might be needed to pin this down - in normal usage CreateBootstrapLogger() and the file sink will coordinate shut-down/reopening of the file in order to prevent exactly this issue.

nblumhardt avatar Aug 02 '24 23:08 nblumhardt

Hi again! It doesn't look like any other reports or evidence have come in, so my best guess here is that an environmental issue (e.g. some kind of file scanning or synchronization process) is getting involved, or multiple loggers are being created within the app, or possibly multiple instances of the app are being run (e.g. by IIS overlapped recycling).

Hope you were able to track it down; closing for now but if you find further clues pointing to Serilog please feel free to jump back in with them. Cheers!

nblumhardt avatar Oct 04 '24 03:10 nblumhardt