5

I am using NLog as logging provider in my solution, but some projects have migrated to Microsoft.Extensions.Logging. We're still evaluating if migrating also the rest of the code to this, but in the meantime we need somehow to convert our NLog.ILogger instance to Microsoft.Extensions.Logging.ILogger<T> instance.

I know it can be quite easily done using NLog.Extensions.Logging package, adding NLog as provider:

ILoggerFactory factory = LoggerFactory.Create(builder =>
{
    builder.AddNLog();
});
return factory.CreateLogger<MyClass>();

but this approach actually creates an NLog provider using the static NLog stuff, not the NLog.ILogger instance I receive from other code parts.

So, is there a way to use this NLog.ILogger instance in this conversion? Am I missing something?

HackSlash
  • 4,944
  • 2
  • 18
  • 44
maradev21
  • 576
  • 2
  • 6
  • 20
  • When having decided to use Microsoft `ILogger` then usually all relevant classes will receive their `ILogger` through their constructor with help from dependency-injection. One should not create custom instances of Microsoft LoggerFactory but always resolve it using the dependency-injection. Dependency-injection is viral, so everyone needs to jump on the wagon. [Example of dependency injection and LoggerFactory](https://github.com/NLog/NLog/wiki/Getting-started-with-.NET-Core-2---Console-application#32-setup-microsoft-logging-with-dependency-injection) – Rolf Kristensen May 18 '22 at 17:03
  • @RolfKristensen the problem is that in that code dependency injection is not handled so well, and so we really need to pass some kind of logger or, as an alternative, `ILoggerFactory` (really, there is a method called `AddLogging(ILoggerFactory)` and we can't avoid it). We can't change this code since it's developed by another team – maradev21 May 19 '22 at 07:29

2 Answers2

3

Unless you are using isolated NLog LogFactory-instances, then you can always just do this:

AddLogging(new NLog.Extensions.Logging.NLogLoggerFactory());

And you can also store the NLogLoggerFactory as static singleton, so you can reuse it everywhere, until everyone have converted to dependency-injection.

But if you want to make it pretty (and it sounds like it will never be), then sadly enough the NLog ILogger has a reference to NLog LogFactory, so you can do this:

NLog.ILogger nlogLogger = ??;
var nlogProvider = new NLog.Extensions.Logging.NLogLoggerProvider(nlogLogger.Factory);
var nlogFactory = new NLog.Extensions.Logging.NLogLoggerFactory(nlogProvider);
AddLogging(nlogFactory);
Rolf Kristensen
  • 17,785
  • 1
  • 51
  • 70
  • Thanks Rolf. Only one issue: using the latest NLog.Extensions.Logging version (5.0.0), `NLogLoggerProvider` constructor requires also a `NLogProviderOptions` instance to be passed, with the factory. Is it ok if I create it simply as `new NLogProviderOptions()`? Is it somehow independent from the `NLog.ILogger` instance? – maradev21 May 20 '22 at 12:50
  • @maradev21 The `NLogProviderOptions` only controls how cool the NLog integration with Microsoft Extensions Logging should be. – Rolf Kristensen May 20 '22 at 20:18
2

The accepted answer did not work for me. I noticed that builder.AddNLog accepts a LoggingConfiguration argument and my NLog.ILogger can expose its configuration!

Looks like this:

private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
...
    using (ILoggerFactory factory = LoggerFactory.Create(builder =>
        builder.AddNLog(Logger.Factory.Configuration))
    )
    {
        return factory.CreateLogger<MyClass>();
    }
...
danronmoon
  • 3,814
  • 5
  • 34
  • 56
HackSlash
  • 4,944
  • 2
  • 18
  • 44