Rod
Rod

Reputation: 15423

.Net Core Console Logging not appearing

Found this article on .Net logging in a console app but it's not working for me. The sample log doesn't appear in the console.

I am using the latest logging packages

The References

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.7" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.7" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.7" />
  </ItemGroup>

The Code

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
    static void Main(string[] args)
    {
        // instantiate DI and configure logger
        var serviceProvider = new ServiceCollection()
            .AddLogging(cfg => cfg.AddConsole())
            .AddTransient<Program>()
            .Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information)
            .BuildServiceProvider();
        // get instance of logger
        var logger = serviceProvider.GetService<ILogger<Program>>();
        // use the logger
        logger.LogInformation("Woo Hooo");
    }
}

enter image description here

Upvotes: 6

Views: 9068

Answers (5)

Granger
Granger

Reputation: 4379

Dispose of your ServiceCollection before exiting. That'll trigger disposal of your services, which, in turn, will flush the logs.

If you're in C# 8+, just add "using" in front of your var serviceProvider = new ServiceCollection() line. That's literally the only change required to the code you had.

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
    static void Main(string[] args)
    {
        // instantiate DI and configure logger
        using var serviceProvider = new ServiceCollection()
            .AddLogging(cfg => cfg.AddConsole())
            .AddTransient<Program>()
            .Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information)
            .BuildServiceProvider();
        // get instance of logger
        var logger = serviceProvider.GetService<ILogger<Program>>();
        // use the logger
        logger.LogInformation("Woo Hooo");
    }
}

Upvotes: 3

Jason
Jason

Reputation: 1555

Your configuration is correct, the provider just doesn't get enough time to flush the output before you exit the main thread:

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
    static void Main(string[] args)
    {
        // instantiate DI and configure logger
        var serviceProvider = new ServiceCollection()
            .AddLogging(cfg => cfg.AddConsole())
            .AddTransient<Program>()
            .Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information)
            .BuildServiceProvider();
        // get instance of logger
        var logger = serviceProvider.GetService<ILogger<Program>>();
        logger.LogInformation("Woo Hooo");

        // This will allow enough time to flush
        Console.ReadLine();
    }
}

enter image description here

Additionally, I do not think that you need .AddTransient<Program>() unless you intend on creating more than one Program instance.

Upvotes: 7

vernou
vernou

Reputation: 7590

The NuGet packageMicrosoft.Extensions.Logging write to the console from a background thread : https://github.com/dotnet/extensions/blob/v3.1.7/src/Logging/Logging.Console/src/ConsoleLoggerProcessor.cs

The code is open source, then don't hesitate to open the source.

In your code, the program close and the background thread is killed before it write the log. You can add a sleep to wait the log message :

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
    static void Main(string[] args)
    {
        // instantiate DI and configure logger
        var serviceProvider = new ServiceCollection()
            .AddLogging(cfg => cfg.AddConsole())
            .AddTransient<Program>()
            .Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information)
            .BuildServiceProvider();
        // get instance of logger
        var logger = serviceProvider.GetService<ILogger<Program>>();
        // use the logger
        logger.LogInformation("Woo Hooo");
        Thread.Sleep(TimeSpan.FromSeconds(1));
    }
}

Upvotes: 0

Paul
Paul

Reputation: 73

    var serviceProvider = new ServiceCollection()
        .AddLogging(cfg => cfg.AddConsole()
                             .AddFilter(lvl => lvl == LogLevel.Information))
        .AddTransient<Program>()
        .BuildServiceProvider();
    // get instance of logger
    var logger = serviceProvider.GetService<ILogger<Program>>();

Upvotes: 0

mm8
mm8

Reputation: 169150

Install the Microsoft.Extensions.Logging.Console NuGet package and try this:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
            builder.AddFilter("*.Program", LogLevel.Information)
                   .AddConsole());

        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Woo Hooo");

        Console.ReadLine();
    }
}

This is how logging fundamentally works in .NET Core 3.

Or using a service provider:

class Program
{
    static void Main(string[] args)
    {
        ServiceProvider serviceProvider = new ServiceCollection()
            .AddLogging(x => x.AddFilter("*.Program", LogLevel.Information)
                .AddConsole())
            .BuildServiceProvider();

        ILogger<Program> logger = serviceProvider.GetService<ILogger<Program>>();
        logger.LogInformation("Woo Hooo");

        Console.ReadLine();
    }
}

Upvotes: 1

Related Questions