A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/dotnet/runtime/issues/51927 below:

Logging-Generator should allow to skip the IsEnabled check · Issue #51927 · dotnet/runtime · GitHub

Taking the example from #45290 and bring it to the logging-generator:

public class Connection
{
    private string? _connectionId;
    public string ConnectionId => _connectionId ??= GenerateConnectionId();

    private string GenerateConnectionId() => Guid.NewGuid().ToString();    // or something more expensive
}

public static partial class Log
{
    public static void ConnectionStarted(this ILogger logger, Connection connection)
    {
        if (logger.IsEnabled(LogLevel.Debug))
        {
            ConnectionStarted(logger, connection.ConnectionId);
        }
    }

    [LoggerMessage(EventId = 1, EventName = "ConnectionStarted", Level = LogLevel.Debug, Message = "Connection {ConnectionId} started")]
    private static partial void ConnectionStarted(this ILogger logger, string connectionId);
}

The key-point of the logger.IsEnabled check is to avoid the creation of a expensive resource if not needed.

The generated code looks like (simplifyed some names, to make it easiert to read):

partial class Log
{
    private static readonly Action<ILogger, string, Exception?> __ConnectionStartedCallback =
        LoggerMessage.Define<string>(LogLevel.Debug, new EventId(1, "ConnectionStarted"), "Connection {ConnectionId} started", true);

    private static partial void ConnectionStarted(this global::Microsoft.Extensions.Logging.ILogger logger, global::System.String connectionId)
    {
        if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug))
        {
            __ConnectionStartedCallback(logger, connectionId, null);
        }
    }
}

So in LoggerMessage.Define true is passed in to skip the IsEnabled-check, which is good.
But in the "logging method" IsEnabled is checked, regardless if our code already checked it.

Note: the IsEnabled check isn't free either, I'll defer to @davidfowl's comment: #50334 (comment)

Thus I propose to extend

[AttributeUsage(AttributeTargets.Method)]
public sealed class LoggerMessageAttribute : Attribute
{
    public LoggerMessageAttribute() { }
    public int EventId { get; set; } = -1;
    public string? EventName { get; set; }
    public LogLevel Level { get; set; } = LogLevel.None;
    public string Message { get; set; } = "";
+   public bool SkipEnabledCheck { get; set; } = false;
}

so the above example could be written as:

public static partial class Log
{
    // ...

    [LoggerMessage(EventId = 1, EventName = "ConnectionStarted", Level = LogLevel.Debug, Message = "Connection {ConnectionId} started", SkipEnabledCheck = true)]
    private static partial void ConnectionStarted(this ILogger logger, string connectionId);
}

and the generated code to be like:

partial class Log
{
    private static readonly Action<ILogger, string, Exception?> __ConnectionStartedCallback =
        LoggerMessage.Define<string>(LogLevel.Debug, new EventId(1, "ConnectionStarted"), "Connection {ConnectionId} started", true);

    private static partial void ConnectionStarted(this global::Microsoft.Extensions.Logging.ILogger logger, global::System.String connectionId)
    {
        __ConnectionStartedCallback(logger, connectionId, null);
    }
}

That way IsEnabled is checked only once, if the user is aware of that pattern and opts-into this behaviour.

/cc: @maryamariyan

PS: should this be a formal api proposal? I didn't chose that template, as this api isn't shipped public


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4