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.
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();
Make sure you have copied file correctly. Also MinLevel properly set in configuration NLog.config.
Make sure you have .NET Core ClassLibrary ( Just to make sure it is loading successfully)
In your case too you can use Dependency Injection but it is different Story.
Here is the complete example with NLog
You need to get NLog and NLog.Web.AspnetCore Package
In Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
}).UseNLog()
.UseStartup<Startup>();
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With