1

I am using NLog in a .Net Core 2.2 project.

I want to implement a category system for my logs using EventId (supported in NLog).

Currently I am using the logger like this:

logger.LogInformation(new EventId(5, "UserLogin"), "The user: {username} logged in.", username);
logger.LogInformation(new EventId(6, "UserChangedPassword"), "The user: {username} changed their password.", username);

But I would much prefer to be able to use it like this:

logger.LogUserLogin(username);
logger.LogUserChangedPassword(username);

Where LogUserLogin and LogUserChangedPassword are custom functions that would add in the correct EventId id and name and then log the event as LogInformation.

My questions are:

  1. How can I extend the logger with my custom functions?
  2. Is this the wrong/non-ideal way to implement a category system for NLog? Should I rather define the EventId as I'm writing the logs, like I'm doing currently?

I feel like this should be relatively simple, but my googling skills seem to be failing me at the moment.

Julian
  • 33,915
  • 22
  • 119
  • 174
Fridrik
  • 53
  • 6
  • `logger.LogInformation` with `EventId` is not related to NLog, but extension-method for Microsoft Extension Logging ILogger-interface. It is perfectly okay to create your own extension-methods for the ILogger-interface. Maybe check this "high performance" using `LoggerMessage.Define`: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/loggermessage#loggermessagedefine – Rolf Kristensen May 17 '20 at 22:08
  • Thank you for the response, I will check out the link. – Fridrik May 20 '20 at 18:28

1 Answers1

1

The LogInformation is from the Microsoft abstraction (not NLog), but no problem!

Just write two C# extension methods:

/// <summary>
/// Extensions for <see cref="Microsoft.Extensions.Logging.ILogger"/>
/// </summary>
public static class LoggerExtensions
{
    public static void LogUserLogin<T>(this ILogger<T> logger, string username)
    {
        logger.LogInformation(new EventId(5, "UserLogin"), "The user: {username} logged in.", username);
    }  

    public static void LogUserChangedPassword<T>(this ILogger<T> logger, string username)
    {
        logger.LogInformation(new EventId(6, "UserChangedPassword"), "The user: {username} changed their password.", username);
    }
}

Is this the wrong/non-ideal way to implement a category system for NLog? Should I rather define the EventId as I'm writing the logs, like I'm doing currently?

I think this is a nice way. There are other ways to do abstractions but this is IMO not a bad choice.

Julian
  • 33,915
  • 22
  • 119
  • 174
  • This is perfect, just what I was looking for :) Thank you! – Fridrik May 20 '20 at 18:27
  • I'm not greatly experienced with reading log messages, but with this solution is there not a concern about logging an event outside the scope of where is happened? What I mean is that the code to sign in the user was in another class, but it was instead logged inside `LoggerExtensions` class thus losing information such as the line number of where the message was logged in the parent class. So, if extension methods are reused, they'll always log the event in `LoggerExtensions` and not provide information about what part of the parent class this was logged at, but maybe I'm misunderstanding. – Lukas Sep 16 '21 at 13:47