alefranz / MELT

MELT is a free, open source, testing library for the .NET Standard Microsoft Extensions Logging library. It is a solution to easily test logs.
Apache License 2.0
72 stars 5 forks source link

NLog support #13

Closed jdelucaa closed 3 years ago

jdelucaa commented 4 years ago

Hi,

Can I use this library in combination with NLog? What I am trying to achieve is to get the timestamp from the log entries. I am using the test logging and I am able to get the LogEntries from the testSink, but it doesn't contain the timestamp.

Ah, I am using it for .NET Core Integration Tests.

How can I achieve that?

Thanks in advance!!

alefranz commented 4 years ago

Hello!

I haven't looked into NLog yet as I'm not using it at the moment, so I will have to check. There is no timestamp concept in Microsoft.Extensions.Logging, but if it is handled by the NLog provider (and not by the formatter) it should be possible to expose the information.

Are you using NLog.Web.AspNetCore?

jdelucaa commented 4 years ago

Yes, it's NLog.Web.AspNetCore, I am currently trying to figure out if the timestamp is handled by it or not.

alefranz commented 4 years ago

I had a look at this and the timestamp is not passed through the logging infrastructure. It is generated only later when writing the logs, so it is not possible to assert on that with this library.

May I ask you in which kind of scenario do you need this? I have a couple of ideas in mind on how it could be done, but it depends on what you are trying to achieve.

FYI the NLog examples I've added are LoggingTest and LoggingTestWithInjectedFactory.

jdelucaa commented 4 years ago

Hey,

Thanks for taking your time to look into this. I actually solved it already, let me explain to you what I was trying to achieve and how I solved it. So, I configure NLog through the nlog.config file and I have the following layout for the log message:

<target xsi:type="Console" name="logconsole" layout="${longdate:universalTime=true}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />

You can see that I have a ConsoleTarget and for the longdate attribute I explicilty set universalTime=true, so I was writting a test to assert that the log output contains the UTC time, so in case someone changes this configuration my test would break.

To be able to do that, I programatically created a new target in NLog, which is a MemoryTarget based on the ConsoleTarget above.

var consoleTarget = configuration.FindTargetByName<ConsoleTarget>("logconsole");
var memoryTarget = new MemoryTarget("memory") { Layout = consoleTarget.Layout };
configuration.AddTarget(memoryTarget);
LogManager.Configuration = configuration;

NLog keeps the configuration in a static LogManager class so I can change it, then from the test I can access the logs in memory for my assertions:

var memory = LogManager.Configuration.FindTargetByName<MemoryTarget>("memory");
var logs = memory.Logs;

Not sure if there is a fancier way of doing it, because it feels dirty to override the static configuration, but anyways, this works.

Thanks for your help!

alefranz commented 3 years ago

I don't think there is a better way to achieve what you are trying to do. It can't be tested on the Microsoft.Extensions.Logging abstraction as it is a specific behaviour of NLog.

I've anyway added the examples of testing when using NLog (but doesn't include the internals of the NLog formatters).

https://github.com/alefranz/MELT/tree/main/samples/current/NLog/SampleWebApplicationNLog.IntegrationTests

I'll close this for now, but let me know if you think there could be something to add to the library.

Thank you, Alessio