58

I've created a .NET Core 3.1 project using a Host, the IoC container with IServiceCollection and implemented logging allover the place using the ILogger<T> interface from Microsoft.Extensions.Logging. I now need to implement more advanced logging and decided to use Serilog.

I assumed that it would be a breeze to switch from .NET built-in loggers to Serilog. But to my surprise, Serilog is using it's own ILogger interface - bummer! So now I needed to update ALL places to use Serilog ILogger, or to implement Serilog with a .NET Core ILogger<T> interface.

My question is - is it really not possible to use Serilog with the ILogger interface in Microsoft.Extensions.Logging? Would be so much smarter!

John Smith
  • 7,243
  • 6
  • 49
  • 61
morteng
  • 1,133
  • 2
  • 9
  • 22
  • 1
    "_I kinda assumed that it would be a breeze to switch from .NET built-in loggers to Serilog_" - It is... Just use [Serilog's provider for Microsoft.Extensions.Logging](https://github.com/serilog/serilog-extensions-logging) – C. Augusto Proiete May 01 '20 at 15:17
  • 1
    Also, you might be interested in this other question: "[Serilog DI in ASP.NET Core, which ILogger interface to inject?](https://stackoverflow.com/q/61411759/211672)" – C. Augusto Proiete May 01 '20 at 15:20

4 Answers4

50

In the Serilog.Extensions.Logging assembly there is a extension method on IloggingBuilder called AddSerilog (it's in the Serilog namespace) that will allow you to use Serilog for logging. For example:

.NET Core 2.2 and earlier (using WebHost):

WebHost.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        logging.ClearProviders();
        logging.AddSerilog();
    });

.NET Core 3.1 and later (using generic Host for either web or console apps):

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>()})
    .UseSerilog();

Now the ILogger and ILogger<> implementation will call into Serilog.

Thiago Silva
  • 14,183
  • 3
  • 36
  • 46
Sean
  • 60,939
  • 11
  • 97
  • 136
  • 19
    And if you're using Generic Host, there is Serilog.Extensions.Hosting package which has a UseSerilog method to configure the Serilog setup – pinkfloydx33 May 01 '20 at 14:31
27

For .NET 6 and later

using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog((ctx, lc) => lc
    .WriteTo.Console()
    .ReadFrom.Configuration(ctx.Configuration));

Reference: Here

Shuvo Amin
  • 631
  • 8
  • 14
5

In addition to ways by using builder.host.UseSeriLog() extensions method. Here is more elegant way (we can use in external console or unit test ILogger without implementation of main project).

  1. Install Nuget Package Serilog.Extensions.Logging along with core package Serilog.
  2. Initialize Logger Configuration like you already doing. For example a typical logging configuration would be write to Console would be like Log.Logger = new LoggerConfiguration).WriteTo.Console().CreateLogger().
  3. Use ILoggerFactory extension method AddSeriLog() like this ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
  4. Simply return factory.CreateLogger<T>();
public static Microsoft.Extensions.Logging.ILogger LoggingInstance<T>()
{
  Serilog.Log.Logger = Serilog.Log.Logger ?? new LoggerConfiguration().WriteTo.(xxxxYourSinksxxxx).CreateLogger();
  ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);            
  return factory.CreateLogger<T>();
}

Its usage be like

var logger = LoggingInstance<YourModel>();

morteng
  • 1,133
  • 2
  • 9
  • 22
vibs2006
  • 6,028
  • 3
  • 40
  • 40
0

I had a need for logging in a very simple console app (.NET6) and started wondering what the absolute minimal Serilog implementation would look like. Contrary to many SO questions about this, Serilog is not "heavyweight" by any means. The total DLL size for this is smaller than the MS Logging extensions (since the extensions pull in stuff like DI that isn't needed here).

Packages:

  • Microsoft.Extensions.Logging v6.0.0
  • Serilog v3.0.1
  • Serilog.Extensions.Logging v3.1.0
  • Serilog.Sinks.Async v1.5.0
  • Serilog.Sinks.Console v4.1.0
  • Serilog.Sinks.File v5.0.0

Console program:

static void Main(string[] args)
{
    var iLogger = GetILogger("ConsoleProgram", "./test.log");

    // uses MS ILogger to write to console and file
    iLogger.LogInformation("this is a test"); 

    Log.CloseAndFlush();
}

static ILogger GetILogger(string categoryName, string pathname)
{
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .WriteTo.Console()
        .WriteTo.Async(a => a.File(pathname))
        .CreateLogger();

    return new SerilogLoggerFactory()
        .CreateLogger(categoryName);
}

Of course, you could break up the fluent config to make the console output optional, or store the factory reference if you have multiple categories, etc, but the point is you don't need all that DI Service, Configuration, Hosting, or Builder overhead.

McGuireV10
  • 9,572
  • 5
  • 48
  • 64