question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Opinion: `UseSerilog` should not set the static `Logger.Log` by default (incompatibility with testing, mainly)

See original GitHub issue

I noticed that when SerilogWebHostBuilderExtensions.UseSerilog( this IWebHostBuilder builder, Action<WebHostBuilderContext, LoggerConfiguration> configureLogger ) is used then by default preserveStaticLogger == false - which causes this behaviour when called:

  1. It sets global::Serilog.Log.Logger (as expected) from configureLogger( new LoggerConfiguration ).CreateLogger().
  2. Then it registers a SerilogFactory which always uses global::Serilog.Log.Logger to log, instead of caching the logger from the CreateLogger() call (this was unexpected to me and caused problems down the line).

This is incompatible with WebApplicationFactory<TStartup>-based tests in ASP.NET Core testing projects - because xUnit runs tests in parallel by default, which means it creates multiple WebApplicationFactory instances, which will then run through their own UseSerilog call-sites - which then means different WebApplicationFactory instances (each with their own separate Startup and DI container roots) will be sharing the same Serilog.ILogger instances, which is undesirable.

…and generally, using mutable static state is a bad idea anyway (and I think the Serilog project should move the static Logger class to a separate NuGet package so projects don’t unintentionally use it either).

I think the UseSerilog call should be “safe” by default and require users to explicitly opt-in to mutating static state. I propose the two UseSerilog methods be replaced with:

  • AddSerilog( IWebHostBuilder builder, Serilog.ILogger logger, Boolean dispose = false )
    • This registers Serilog with DI so it can be injected into pre-Startup types but does not set it as the default ASP.NET Core Microsoft.Extensions.Logging logger.
  • UseSerilog( IWebHostBuilder builder, Serilog.ILogger logger, Boolean dispose = false )
    • Calls AddSerilog and then sets it as the MEL logger - the same as today.
  • UseSerilog( IWebHostBuilder builder, Action< WebHostBuilderContext, Serilog.LoggerConfiguration > configureLogger )
    • This would be the same as UseSerilog( builder, configureLogger, preserveStaticLogger = true );
  • UseSerilog( IWebHostBuilder builder, Action< WebHostBuilderContext, Serilog.LoggerConfiguration > configureLogger, Boolean setStaticLogger = false )
    • The same as above, with optionally setting Serilog.Log.Logger but will cache the generated Serilog.ILogger so the logging system in this host-builder won’t be affected by future changes to Serilog.Log.Logger.
    • The parameter is also renamed to setStaticLogger to make it clear what it actually does - because a name like preserveStaticLogger suggests that setting it to true will not do something rather than doing something.
  • AlwaysUseStaticSerilogLogger( IWebHostBuilder builder, Action< WebHostBuilderContext, Serilog.LoggerConfiguration > configureLogger )
    • Explicitly named extension-method which has the same behaviour as UseSerilog( builder, configureLogger, preserveStaticLogger: false ) does today, and makes it clear that it always uses Serilog.Log.Logger and does not cache the generated Serilog.ILogger.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
warmfire540commented, Sep 17, 2021

This was confusing for us too and caused some issues…

We used to use the first overload w/ just logger like so (worked great)

var logger = new LoggerConfiguration()
	.ReadFrom.Configuration(config.Build())                  
	.CreateLogger();

webHostBuilder.UseSerilog(logger);

we decided to use the other overload… but noticed it wasn’t logging anything…

.UseSerilog((webHostBuilderContext, loggerConfiguration) =>
{
	// register Serilog to be fully configurable
	loggerConfiguration
		.ReadFrom.Configuration(webHostBuilderContext.Configuration);
})

dug into code and saw that if we don’t pass preserveStaticLogger: true then a null logger is passed to SerilogLoggerFactory and subsequently registered w/ DI

We don’t use the static logger - so maybe that’s the issue - however preserveStaticLogger didn’t seem like something we needed to pass to have a proper logger registered w/ DI… so anyway - now we’re passing in preserveStaticLogger so that our DI logger is registered

1reaction
nblumhardtcommented, Feb 17, 2021

Just revamped the README, not sure exactly where it’d fit but something along the lines of “pass preserveStaticLogger: true to avoid setting Log.Logger.” might do the trick. Open to a PR if anyone has the time to figure out a nice uncluttered way to get this info in 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Logging with Serilog .NET Core not outputting
You need to configure your logger in the programs.cs public static IWebHostBuilder CreateWebHostBuilder(string[] args) { return WebHost.
Read more >
C# Logging with Serilog and Seq - YouTube
Serilog is an easy to configure and easy to use logging system that you can plug into a .NET Core project within minutes....
Read more >
Adding Serilog to the ASP.NET Core Generic Host
The recommended approach is to configure Serilog's static Log.Logger object first, before configuring your ASP.NET Core application. That way ...
Read more >
Serilog event log appsettings. c#; asp. MinimumLevel ...
AddSerilog registers a Serilog ILogger to receive logging events. ... The following test code does not return … ... Do not use “Serilog....
Read more >
Setting up Serilog in ASP.NET Core - Detailed Beginner ...
This article covers the implementation of Serilog in ASP.NET Core which provides structured logging that is easier to be read by programs.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found