Search code examples
.net-coreserilog.net-core-3.1

Unable to use Serilog with .Net Core 3 IHostBuilder


I'm trying to use Serilog in a .Net Core project. I have 2 services, the 1st one was upgraded from .Net Core 2.2 and in Program.cs it uses IWebHostBuilder to start the application. Here I created my logger and passed it as a parameter to UseSerilog() and everything works as expected.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(services => services.AddAutofac())
        .UseStartup<Startup>()
        .UseSerilog(_logger);

My 2nd Service was created using the .Net Core 3 templates and it uses IHostBuilder. When I try and use Serilog in either of the following ways I get the same error.

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureWebHostDefaults(webBuilder =>
    {
      webBuilder.UseStartup<Startup>()
        .UseSerilog(_logger);
    });

or

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureWebHostDefaults(webBuilder =>
    {
      webBuilder.UseStartup<Startup>();
    })
    .UseSerilog(_logger);

Gives me this error

System.InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger`1[MyService.Startup]' while attempting to activate 'MyService.Startup'.

I have found blog posts that support either apporach but it is the 2nd one that I feel is more correct but neither work. Here is a link to it. The other blog is here.


Solution

  • You do not have to instantiate an instance of a Logger in that way. Instead you can use LoggerConfiguration and its builder methods to create a logger. You can then initialize the static logger on Log.Logger. Calling UseSerilog without any argument should be enough.

    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.Console()
                .CreateLogger();
    
            try
            {
                Log.Information("app starting");
                CreateHostBuilder(args).Build().Run();
                Log.Information("app terminated");
            }
            catch (Exception e)
            {
                Log.Fatal("app crashed", e);
            }
            
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .UseSerilog();
    }
    

    Configuration Basics: https://github.com/serilog/serilog/wiki/Configuration-Basics

    Setting up a new Console app: https://github.com/serilog/serilog/wiki/Getting-Started#example-application

    You need to take on a dependency on Serilog.Extensions.Hosting to be able to call UseSerilog on the Host builder.