Skip to content

[API Proposal]: Allow ILoggerProvider(s) to conditionally create ILoggers #117241

@petrroll

Description

@petrroll

Background and motivation

Imagine you have logging setup so that all logging is supposed to be handled/go to one place. But some events you also want to handle separately.

.NET logging has support for that via multiple ILoggerProvider all of which are used to create a composite logger and then all are invoked for every log event.

This is, however, not conditional. An ILoggerProvider must always provide an ILogger instance, no matter the category. And so, even if you need two (default and your additional one) ILogger (via default your additional one ILoggerProvider) only for one category, you still need to live with two Loggers for every category. Probably implementing it as returning NullLogger for every not-desired category.

This is rather wasteful.

API Proposal

namespace Microsoft.Extensions.Logging;
// Maybe it should be separate interface not "super" interface, I'm not sure how to decide which is better
public interface IMaybelLoggerProvider : ILoggerProvider // I'm not good at naming things 😅
{
    /// <summary>
    /// Create a new <see cref="ILogger"/> instance if provider wants to handle this <param=categoryName>.
    /// </summary>
    /// <param name="categoryName">The category name for messages produced by the logger.</param>
    /// <returns>The instance of <see cref="ILogger"/> that was created or null.</returns>
    ILogger? TryCreateLogger(string categoryName);
}

API Usage

public class MyLoggerProvider : IMaybelLoggerProvider
{
    public ILogger CreateLogger(string categoryName) => new MyLogger();

    public void Dispose() { }

    public ILogger? TryCreateLogger(string categoryName)
        => categoryName == "TheOnlyCategoryWeAreInterestedIn" 
        ? CreateLogger(categoryName) 
        : null;
}

The LoggerFactory's LoggerInformation[] CreateLoggers(string categoryName) would also be adjusted to only create loggers where the provider returns not-null. And to invoke the Try version if available.

Alternative Designs

Separate interface instead of super interface :).

Alternatively, you can always just produce null loger as right now.

Risks

Complicate the API surface which can cause user confusion.

Creating array of loggers in performant and minimal-alloc (just the resulting array) will be more complex to do, as before running each provider the final amount of loggers is not known.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions