33

I have code that logs to Microsoft.Extensions.Logging.ILogger (and extension methods, mostly).

I have configured Serilog to actually do the logging.

I can't find a way to convert a Serilog.ILogger to Microsoft.Extensions.Logging.ILogger. I assumed that Serilog would be implementing Microsoft.Extensions.Logging.ILogger, but it doesn't seem to.

Is there a way to get a Microsoft.Extensions.Logging.ILogger interface on the Serilog Logger?? --- Thanks

The code I have is:

        Serilog.Core.Logger seriLogger = new Serilog.LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();
        Serilog.ILogger seriILogger = seriLogger;

        Microsoft.Extensions.Logging.ILogger msLogger = seriILogger;

produces

Cannot implicitly convert type 'Serilog.ILogger' to 'Microsoft.Extensions.Logging.ILogger'. An explicit conversion exists (are you missing a cast?)

a cast gets me a runtime error:

Unable to cast object of type 'Serilog.Core.Logger' to type 'Microsoft.Extensions.Logging.ILogger'

MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Chris
  • 959
  • 2
  • 9
  • 20

3 Answers3

45

Apart from installing Serilog.AspNetCore you could also install Serilog.Extensions.Logging and use these lines of code. This will give you some ideas how UseSerilog() works under the hood (well, more or less this way :D).

var serilogLogger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .MinimumLevel.Verbose()
    .WriteTo.Debug() // Serilog.Sinks.Debug
    .CreateLogger();

var microsoftLogger = new SerilogLoggerFactory(serilogLogger)
    .CreateLogger<IMyService>(); // creates an instance of ILogger<IMyService>

Or if you need to use the logger in the DI container use these lines of code:

Log.Logger = serilogLogger;

var container = new ServiceCollection()
    .AddLogging(x => x.AddSerilog())
    .BuildServiceProvider(true);
mihails.kuzmins
  • 1,140
  • 1
  • 11
  • 19
  • 4
    I like this because it is independent of all the ASPNET Core infrastructure, allows me to pass ILogger to libraries and remove dependency of Serilog from them. – Larry Smith Aug 10 '21 at 18:19
  • In the .CreateLogger(), what is IMyService? – Michael Oct 27 '21 at 14:32
  • 1
    @Michael, I have added a command about it. It's a random service which is a generic type argument in `ILogger` – mihails.kuzmins Oct 27 '21 at 15:51
  • @mihails.kuzmins Yours is the first suggestion I have seen that makes it this easy to get an instance of ILogger, I wonder why that is? This seems like a super usefull way to get an instance that can be used for passing into class constructors. – Bjørn Otto Vasbotten May 29 '22 at 16:17
7

TL;DR No, not directly. The compiler is correctly refusing to convert as the Serilog ILogger / Logger does not directly implement the MEL ILogger interface (The Serilog project started ~2012 and has always been designed to operate independent of any specific frameworks of that, or later times...)

There is however a bridging layer that implements the MEL ILogger interface, forwarding to the Serilog ILogger - There's an intro article on this topic which presents a good overview. Depending on your app type, you may not need all of that, but it should give you some context as to how it all fits together.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • Perfect - that's just what I needed. I thought it had been written to plug into the MEL. Thanks – Chris Dec 27 '20 at 00:34
0

Maybe try this and register DI Serilog.ILogger to SerilogToMsLog

public class SerilogToMsLog: Serilog.ILogger
{
    private readonly ILogger<SerilogToMsLog> _logger;

    public SerilogToMsLog(ILogger<SerilogToMsLog> logger)
    {
        _logger = logger;
    }

    public void Write(LogEvent logEvent)
    {
        if (logEvent.Level == LogEventLevel.Error)
        {
            _logger.LogError(logEvent.Exception,logEvent.RenderMessage());
        }
        
    }
}
Van Vu
  • 1