29

Is it possible to get an ILogger inside Program.cs Main method? I want to pass it on to a service that's created inside that method.

I've only found this on SO How do I write logs from within Startup.cs , but that's logging within Startup.cs.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Maxim
  • 972
  • 2
  • 10
  • 18

7 Answers7

23

Accidentally stumbled upon the answer after googling a bit more.

using System;
using Microsoft.Extensions.Logging;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var logFactory = new LoggerFactory()
            .AddConsole(LogLevel.Debug)
            .AddDebug();

            var logger = logFactory.CreateLogger<Type>();

            logger.LogInformation("this is debug log");
        }
    }
}

Kudos to https://askguanyu.wordpress.com/2016/09/26/net-core-101-e06-net-core-logging/

Pang
  • 9,564
  • 146
  • 81
  • 122
Maxim
  • 972
  • 2
  • 10
  • 18
  • You should probably take a look at [this](https://stackoverflow.com/questions/45126149/configuring-dependencies-e-g-logging-in-program-cs-when-ef-migrations-dont-g) so you can use the same logger instance in the rest of your application. – anserk Jul 20 '17 at 17:21
  • @anserk Don't think that's possible, since ILogger instances are generically typed (i.e. `ILogger`). – Maxim Jul 21 '17 at 07:57
  • This no longer works for .NET Core 3.1 and up. – J.D. Mallen Apr 19 '21 at 12:56
  • 1
    See @RickAndMSFT answer below for .Net 6. You can access Logger directly via `Builder.WebApplication.Logger` now. – Nashmár Jul 27 '22 at 12:43
18

This is how I managed to get the ILogger interface configured in Startup.cs (in my case Log4Net) working when inside Program.cs:

public static void Main(string[] args)
{
    var host = BuildWebHost(args);

    ILogger logger = host.Services.GetService<ILogger<Program>>();

    try
    {
        logger.LogInformation("Starting web host");

        host.Run();
    }
    catch (Exception ex)
    {
        logger.LogCritical(ex, "Starting web host failed.");
    }
}
  • Add using Microsoft.Extensions.DependencyInjection; so that the generic type in GetService works as expected.
Pang
  • 9,564
  • 146
  • 81
  • 122
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
5

See the official doc Log in Program.cs

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogInformation("Adding Routes");
app.MapGet("/", () => "Hello World!");
app.Logger.LogInformation("Starting the app");
app.Run();
RickAndMSFT
  • 20,912
  • 8
  • 60
  • 78
4

What worked for me in combination with serilog based on the default template of Program.cs (.NET 6.0), was nearly the same approach as the one of Leniel Maccaferri.

ILogger logger = builder.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();
logger.LogInformation("This is a testlog");
Aage
  • 5,932
  • 2
  • 32
  • 57
Kraego
  • 2,978
  • 2
  • 22
  • 34
  • Where does "builder" come from and what is its type? – NickG Aug 18 '23 at 15:00
  • @NickG see official documentation: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-7.0#log-in-programcs - 'WebApplication.CreateBuilder' – Kraego Aug 26 '23 at 17:17
2

New in .net Core 6 (* I have no idea if this was new to.net core 6, 5 or 3 *)

var logger = LoggerFactory.Create(config =>
    {
        config.AddConsole();
        config.AddConfiguration(builder.Configuration.GetSection("Logging"));
    }).CreateLogger("Program");

This was my simple starting point, you don't actually have to pickup the Configuration section for logging, but I figured it makes sense. But you do need to specify an output; Console, although default for DI is not assumed in the factory.

Tod
  • 2,070
  • 21
  • 27
1

Following helped me to add logger for program.cs as well as for any of the static classes

private static void TemporaryLogger(string methodName, string lineNumber)
    {
        var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
        var logger = loggerFactory.CreateLogger(string.Empty);
        logger.LogInformation($"Test Logger for  class className: Identifier - {methodName} : Line number - {lineNumber}");
    }
Aathira
  • 655
  • 3
  • 14
  • 31
  • This approach has some performance issues. Calling `LoggerFactory.Create` every time you want to log is wasting cycles because under the covers it uses DI to create an ILogger, and then just throws it away after logging a single message. It would be better to only do it once and cache the ILogger instance. – Eric Erhardt Jun 14 '22 at 15:51
-2

Program.cs

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Log4Net.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddLog4Net();

Above worked for me in .net 6

Thanks to: https://onloupe.com/blog/does-log4net-work-on-net6/

Anish Kutti
  • 337
  • 2
  • 7