Is it possible to get the current LogLevel of an ILogger?
Asked Answered
L

3

7

I have a component defined like this:

public class MyClass
{
    public MyClass(ILogger<MyClass> logger)
    {
    }
}

I don't know if the developer using this component will configure the logger with an application.json or an environment variable.

Is there a way to get the current LogLevel of the logger instead of trying to guess using the IsEnabled method?

Leadin answered 21/6, 2021 at 20:10 Comment(10)
What's the purpose of knowing? You should categorize the level of your own log messages you are writing throughout your application independent from what some consumer of your library is configuring. That allows the consumer to choose how detailed they want your library to be logging.Kresic
Log levels vary by provider and category, so there is no general concept of a "current LogLevel".Grace
have you looked at other logging libraries?Geoffreygeoffry
Xerillio asks a very good question - why do you need this? The whole purpose of passing in an ILogger as a dependency is that you don't have to worry about the log level. ILogger.Log accepts a log level as a parameter, and you can just call it for all the log levels you deem appropriate in your function; if the users have enabled a particular log level in their configuration, it will show up in the log, if they haven't it won't. You don't have to examine anything.Squally
@Grace all ILoggers use Microsoft.Extensions.Logging.LogLevelLeadin
@Geoffreygeoffry I will try that to see if i find something usefulLeadin
@Xerillio, Filip Milovanović: I want to change the message based on the LogLevel, if the Log is in information just log a simple message, but if the configuration is Trace Or Debug log a more complete message but retrieving that information may have a performance penalty, I wanted to avoid having several IsEnabled with several LogLevels to see if the user wanted a more detailed message.Leadin
@JuanZamudio I think there is no reason to worry about performance. I bet that IsEnable method is much faster than any Log-method that you call. But if you don't want to check it every time before logging, I may suggest you to calculate minimum log level on application startup and inject it using custom interface like 'ILogLevelProvider' which returns your calculated value. If you have a problem with implementing caclulation of min-log-level, let me knowXerophyte
I see. You could write a small helper method, something like this: Enum.GetValues(typeof(LogLevel)).Cast<LogLevel>().FirstOrDefault(level => logger.IsEnabled(level)). This should return the log level for you.Squally
@JuanZamudio I know that. But each provider (console, app insights, etc) can have it's own default and each category of each provider can further define it's default. So if you have more than one provider configured then there is no single default log level. The source code shows how IsEnabled is true if any loggers have a certain level enabled.Grace
F
14

You can use the following function:

ILogger.IsEnabled(LogLevel)

https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger.isenabled?view=dotnet-plat-ext-5.0#Microsoft_Extensions_Logging_ILogger_IsEnabled_Microsoft_Extensions_Logging_LogLevel_

So you can either use it directly to check for a specific level or create your own function with a switch case and return the minimum level enabled in your context.

Fabrication answered 21/6, 2021 at 20:42 Comment(2)
I guess I will have to do something like this in the constructor to do it just onceLeadin
I don't know who marked this down as this is correct, it means that I can set it up so if the Class log level is not set to Trace I don't have to run some expensive methods that I would otherwise log to Trace! I wish I could double up this answer.Ylangylang
S
2

We can use some extension like this :

 public static class LoggerExtension
    {
        public static LogLevel CurrentLogLevel(this ILogger logger)
        {
            foreach(LogLevel logLevel in Enum.GetValues(typeof(LogLevel)))
            {
                if( logger.IsEnabled(logLevel))
                    return logLevel;
            }

            return LogLevel.None;
        }
    }
Sacaton answered 4/2 at 20:39 Comment(0)
B
0

IsEnabled won't actually work, even if you wrote a function and ran through each level looking for when the result changed from true to false. Based on this answer and looking at the source code here:

This is ConsoleLogger

public bool IsEnabled(LogLevel logLevel)
{
    return logLevel != LogLevel.None;
}

This is DebugLogger

public bool IsEnabled(LogLevel logLevel)
{
    // Everything is enabled unless the debugger is not attached
    return Debugger.IsAttached && logLevel != LogLevel.None;
}

and this is EventLogLogger

public bool IsEnabled(LogLevel logLevel)
{
    return logLevel != LogLevel.None &&
        (_settings.Filter == null || _settings.Filter(_name, logLevel));
}

So checking IsEnabled may tell you various things about their configuration, such as whether EventLogLogger is being filtered or not, but it's not going to tell you what the minimum loglevel is. I think to do that, you are going to have to get the data from the configuration system directly yourself (set up your own "loggingOptions" class, use config.bind or get, etc.) And even that isn't going to help if you happen to have something weird like "WarningLogAndAboveLogger" registered that ignores the config and hard-codes it's own default. And even when parsing config does work, you'd have to make sure you compare categories and handle all of the heirarchy and such, since ConsoleLogger with one category can have a different minimum level than ConsoleLogger with some other category.

Berkey answered 28/12, 2023 at 0:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.