90

The ConsoleLoggerProvider has four constructors:

  1. ConsoleLoggerProvider(IConsoleLoggerSettings)
  2. ConsoleLoggerProvider(IOptionsMonitor<ConsoleLoggerOptions>)
  3. ConsoleLoggerProvider(Func<String,LogLevel,Boolean>, Boolean)
  4. ConsoleLoggerProvider(Func<String,LogLevel,Boolean>, Boolean, Boolean)

Three of them are declared obsolete with this message:

This method is obsolete and will be removed in a future version. The recommended alternative is using LoggerFactory to configure filtering and ConsoleLoggerOptions to configure logging options.

With constructor #3, creating a LoggerFactory with a ConsoleLoggerProvider is straightforward (as documented on Entity Framework Core - Logging):

var loggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((category, level) => level >= LogLevel.Information, true) });

But since it's deprecated, we are left with constructor #2. Here's what I found to be equivalent:

var configureNamedOptions = new ConfigureNamedOptions<ConsoleLoggerOptions>("", null);
var optionsFactory = new OptionsFactory<ConsoleLoggerOptions>(new []{ configureNamedOptions }, Enumerable.Empty<IPostConfigureOptions<ConsoleLoggerOptions>>());
var optionsMonitor = new OptionsMonitor<ConsoleLoggerOptions>(optionsFactory, Enumerable.Empty<IOptionsChangeTokenSource<ConsoleLoggerOptions>>(), new OptionsCache<ConsoleLoggerOptions>());
var loggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider(optionsMonitor) }, new LoggerFilterOptions { MinLevel = LogLevel.Information });

This seems overly complicated, am I missing something simpler?

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
0xced
  • 25,219
  • 10
  • 103
  • 255

4 Answers4

142

In Microsoft.Extensions.Logging 3.0+, you can use the much simpler LoggerFactory.Create:

var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddFilter("Microsoft", LogLevel.Warning)
           .AddFilter("System", LogLevel.Warning)
           .AddFilter("SampleApp.Program", LogLevel.Debug)
           .AddConsole();
});

For Microsoft.Extensions.Logging version 2.2+, you can build an ILoggerFactory without using obsolete methods via Microsoft's dependency injection framework. It's a little less verbose than the 2.1 version where everything is constructed by hand. Here’s how:

var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder => builder
    .AddConsole()
    .AddFilter(level => level >= LogLevel.Information)
);
var loggerFactory = serviceCollection.BuildServiceProvider()
    .GetService<ILoggerFactory>();

See also:

0xced
  • 25,219
  • 10
  • 103
  • 255
  • 18
    That's great for application composition, but what about when I'm writing test or working with REPL? It would be nice to be able to fulfill `ILogger` dependencies in a more straightforward manner. `LoggerFactory` is almost short enough, but the discoverability is not ideal... – Lukáš Lánský Mar 25 '19 at 15:08
  • 8
    FYI first example .AddConsole() requires a reference to Microsoft.Extensions.Logging.Console – blackboxlogic Aug 27 '19 at 18:27
  • 59
    something goes completely wrong @microsoft, when for such a simple task we need a dependency injection and a whole bunch of options, providers and factories – python_kaa Sep 12 '19 at 20:51
11

Just in case, if someone wants to do it in ASP.NET Core composition root for efcore:

services.AddDbContext<DbContext>(opt => {
    opt.AddSqlServer(Configuration.GetConnectionString("DefaultConnection"));
    opt.UseLoggerFactory(LoggerFactory.Create(builder => { builder.AddConsole(); }));
});
Pang
  • 9,564
  • 146
  • 81
  • 122
Daniel B
  • 3,109
  • 2
  • 33
  • 42
0

@0xced thanks for your deconstructed example, since delegates don't work in Powershell this helped me to do the same in Powershell:

$optionsFactory = [OptionsFactory[ConsoleLoggerOptions]]::new(
    [List[ConfigureNamedOptions[ConsoleLoggerOptions]]]@(
        [ConfigureNamedOptions[ConsoleLoggerOptions]]::new('',$null)
    ),
    [List[IPostConfigureOptions[ConsoleLoggerOptions]]]::new()
)

$optionsMonitor = [OptionsMonitor[ConsoleLoggerOptions]]::new(
    $optionsFactory,
    [List[IOptionsChangeTokenSource[ConsoleLoggerOptions]]]::new(),
    [OptionsCache[ConsoleLoggerOptions]]::new()
)

$consoleLoggerProvider = [ConsoleLoggerProvider]$OptionsMonitor
$consoleLoggerProviderList = [List[ILoggerProvider]]::new()
$consoleLoggerProviderList.add($consoleLoggerProvider)

$loggerFactory = [LoggerFactory]::new(
    $consoleLoggerProviderList,
    [LoggerFilterOptions]@{
        MinLevel = [LogLevel]::Information
    }
)
Justin Grote
  • 579
  • 5
  • 12
-1

@Justin-Grote's answer worked for me. Here is C# version of the code.

            var loggerFactory = new LoggerFactory();
        var optionsFactory = new OptionsFactory<ConsoleLoggerOptions>(
            new List<ConfigureNamedOptions<ConsoleLoggerOptions>>()
            {
                new ConfigureNamedOptions<ConsoleLoggerOptions>("", null)
            },
            new List<IPostConfigureOptions<ConsoleLoggerOptions>>()
        );

        var optionsMonitor = new OptionsMonitor<ConsoleLoggerOptions>(
            optionsFactory,
            new List<IOptionsChangeTokenSource<ConsoleLoggerOptions>>(),
            new OptionsCache<ConsoleLoggerOptions>()
        );
        var consoleLoggerProvider = new ConsoleLoggerProvider(optionsMonitor);
zendu
  • 1,108
  • 1
  • 14
  • 36