Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to log NLog calls from a class library in my ASP.NET Core MVC app?

Let's pretend I have two projects.

The first one is an ASP.NET Core MVC project that relies on NLog.Extensions.Logging for its logging. This is great; I can use dependency injection on my controllers to get an ILogger instance, and the nlog.config file contains, well, my NLog config.

The second one is a class library, which the API depends on, that relies directly on NLog for its logging. It contains calls like this:

public class SampleClass
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public void DoStuff()
    {
        if (_failed) Logger.Error("oh no");
    }
}

These classes are instantiated with some reflexive wizardry, and I can't use dependency injection to replace their logger. You can also think of them as some sort of model, which can't get instantiated at startup.


How do I get my library's logs to show up in the API's logging output? I would expect them to get caught by the nlog.config automatically, but they don't seem to be.

like image 858
Baptiste Candellier Avatar asked Oct 23 '18 15:10

Baptiste Candellier


2 Answers

  1. You don't need separate configuration file. If your ASP.net MVC core project has nlog.config and it is successfully copied during build process then same configuration will get load when

    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
    
  2. Make sure you have copied file correctly. Also MinLevel properly set in configuration NLog.config.

  3. Make sure you have .NET Core ClassLibrary ( Just to make sure it is loading successfully)

  4. In your case too you can use Dependency Injection but it is different Story.

Here is the complete example with NLog

  1. You need to get NLog and NLog.Web.AspnetCore Package

  2. In Program.cs

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
         return  WebHost.CreateDefaultBuilder(args)
                    .ConfigureLogging(logging =>
                    {
                        logging.ClearProviders();
                        logging.SetMinimumLevel(LogLevel.Trace);
                    }).UseNLog()
                .UseStartup<Startup>();
        }
    
  3. Now In ClassLibrary Project Just Add Referece for NLog. Note : Here Make sure that ILogger is from Microsoft.Extensions.Logging not from NLog.

    public class Class1
    {
        //private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private ILogger<Class1> _logger = null;
        public Class1(ILogger<Class1> logger)
        {
            this._logger = logger;
        }
    
        public void DoStuff()
        {
            var _failed = true;
            if (_failed) _logger.LogError("oh no");
        }
    }
    

Now it will work without any issue as well.

like image 100
dotnetstep Avatar answered Oct 04 '22 00:10

dotnetstep


Class libraries should never depend on a particular logging implementation. Instead, you should use an abstraction, referred to as a facade. The Microsoft.Extensions.Logging library is one such facade you can utilize, but there's others like Common.Logging. Regardless, the classes that need to utilize logging should be injected with this abstract logging facade. For example:

public class SampleClass
{
    private readonly ILogger _logger;

    public SampleClass(ILogger<SampleClass> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public void DoStuff()
    {
        if (_failed) _logger.LogError("oh no");
    }
}

Then, in your web application or whatever other concrete application that is utilizing your class library, that is where you actually set up your logging implementation, and register that via your DI container to injected in into your logging facade.

Long and short, your class library depends only on your logging facade, which allows it to generically call stuff like LogError. The application that uses your library sets up its actual concrete logging implementation, which will then be utilized under the hood by the facade for the logging the library does.

like image 29
Chris Pratt Avatar answered Oct 03 '22 23:10

Chris Pratt