Skip to content

Add LoggerMessage.Define overload to disable IsEnabled check #45290

@davidfowl

Description

@davidfowl

Background and Motivation

LoggerMessage.Define allows skipping various overheads in logging (parsing the template etc) and returns delegate that performs logging and includes a check if that logging category is enabled before performing the call to log. In some cases it's important that check be moved higher up the stack to avoid transformation of parameters before calling log, for e.g.

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

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

    public static void ConnectionStarted(ILogger logger, Connection connection)
    {
          _connectionStart(logger, connection.ConnectionId, null);
    }
}

The above logic ends up eagerly allocating the ConnectionId even when the log level isn't enabled. The code could be changed to this:

public static void ConnectionStarted(ILogger logger, Connection connection)
{
+    if (logger.IsEnabled(LogLevel.Debug))
+    {
        _connectionStart(logger, connection.ConnectionId, null);
+    }
}

It would end up checking if the category is enabled multiple times when the category is on.

Proposed API

namespace Microsoft.Extensions.Logging
{
    public static class LoggerMessage
    {
+        public static Action<ILogger, T1...T6, Exception> Define<T1...T6>(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck);
    }

The ... are overloads T1 to T6 (or more).

Usage Examples

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

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

    public static void ConnectionStarted(ILogger logger, Connection connection)
    {
        if (logger.IsEnabled(LogLevel.Debug))
        {
            _connectionStart(logger, connection.ConnectionId, null);
        }
    }
}

Risks

None.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions