Makla
Makla

Reputation: 10459

ILogger (ASP.NET Core) Log is called even IsEnabled return false

I am trying to understand the purpose of IsEnabled method in ILogger interface. I would expect that method is automatically called every time something can be log, but method Log is called no mater what returned IsEnabled.

Should I check IsEnabled inside Log method?

    public bool IsEnabled(LogLevel logLevel)
    {
        return logLevel >= this.level;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (this.IsEnabled(logLevel))   //it seams that this is required ????
        {
            string s = formatter(state, exception);
            string formatted = s.Replace("\r\n", "\r\n                          ");
            Console.WriteLine(string.Format("{0,-15} {1,-5} - {2}", logLevel, eventId, formatted));
        }
    }

Then what is the purpose and who(why) calls IsEnabled.

Upvotes: 10

Views: 5791

Answers (3)

Yennefer
Yennefer

Reputation: 6214

As of .NET 6, you can use logger delegates to avoid explicitly calling the IsEnabled method, since it is automatically done.

This approach allows you to have additional benefits since the formatter is created once and is optimized for high volume calls.

Upvotes: 1

Grant
Grant

Reputation: 1164

IsEnabled is especially important when you pass parameters.

Without IsEnabled

logger.LogDebug("My debug message with {payload}", Serialize(myPayload));

In this case, myPayload is serialized on EVERY call to LogDebug regardless of your log level settings. This could be an unnecessary hit in a production environment, and potentially lead to unexpected errors. What if Serialize method fails due to unexpected data?

With IsEnabled

if (logger.IsEnabled(LogLevel.Debug))
{
    logger.LogDebug("My debug message with {payload}", Serialize(myPayload));
}

In this case, myPayload is only serialized when LogDebug is enabled in your settings.

Balanced approach

Personally, I skip IsEnabled checks with "constant text" calls to Log() methods (e.g., logger.LogDebug("constant string")), and only test IsEnabled when I need to log with parameters.

Upvotes: 13

MichaC
MichaC

Reputation: 13381

Unless Microsoft changed it, yes you are supposed to call IsEnabled yourself.

The reasoning is that if the API would call IsEnabled, and then the user's code calls IsEnabled, that would double the calls per log operation and would hit performance more than it helps eventually.

Also, the logging framework would always respect filters and min log level before writing something to the log sinks. Meaning, if you always call LogDebug for example and Information is your configured minimum log level, the debug messages will not appear in the log.

But! the code to call LogDebug and filtering gets excecuted if you do not check for logger.IsEnabled(LogLevel.Debug) and run the code only if necessary.

Hope that makes sense

Upvotes: 4

Related Questions