ASP.NET Core – custom ILogger<T> and Nlog callsite layout renderer issue

1. Introduction

In my current project, we use Microsoft.Extensions.Logging.ILogger<T> default implementation as our logging mechanism. This basically comes with the ASP.NET Core 2.0 package and it was working fine so far. However recently we decided to switch the default implementation with a custom one, due to the fact that we wanted to have some additional logic applied for all of the logging providers.

2. Implementation

The custom implementation itself is very similar to the original one, we came up with something like that

and we replaced the default logger with this code

As you can see we basically wanted to add information from custom exceptions to the message. Due to the fact that this is added in here, we don’t have to modify all of our existing logging providers.

3. NLog call site renderer issue

Once we run the application all of the providers were working fine and were producing expected output apart from NLog provider. Originally NLog provider for the following code

was producing this output

However, after introducing new implementation of ILogger<T>, it started appending wrong caller member name

After some digging, it turned out that the issue lies in the (indirect)configuration of NLog’s callsite layout renderer. Long story short, when you add NLog provider to your logger providers, under the hood it adds Microsoft.Extensions.Logging.Abstractions assembly(among others) to something called hidden assembly collection. Once the NLog tries to figure out what is the caller member name, it crawls the stack trace to find a method name. If the method in current frame comes from a hidden assembly, logger skips it and continues iteration. As we changed the Logger<T> to our custom one, it is no longer part of Microsoft.Extensions.Logging.Abstractions assembly, so the NLog reports Log method from our custom logger as a caller member name.

4. The fix

In order to restore previous behavior you have to add custom logger assembly to the hidden assembly collection. You can do it via

Of course, if the logger is located in the same assembly as rest of your code, this might not be the perfect solution – as this will impact the way the callsite is rendered for other parts of your code in this assembly. In that case, you might consider moving the logging piece to separate assembly or resign from using callsite layout renderer at all. We decided to replace it with logger layout renderer as callsite layout renderer, either way, wouldn’t be used in production environments.

Source code for this post can be found here

ASP.NET Core – custom ILogger<T> and Nlog callsite layout renderer issue

2 thoughts on “ASP.NET Core – custom ILogger<T> and Nlog callsite layout renderer issue

Comments are closed.