40

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.

1

7 Answers 7

29

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/

Sign up to request clarification or add additional context in comments.

4 Comments

You should probably take a look at this so you can use the same logger instance in the rest of your application.
@anserk Don't think that's possible, since ILogger instances are generically typed (i.e. ILogger<Startup>).
This no longer works for .NET Core 3.1 and up.
See @RickAndMSFT answer below for .Net 6. You can access Logger directly via Builder.WebApplication.Logger now.
21

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.

1 Comment

Oddly enough, while I can get the logger inside the catch to work with NLog, I can't with Serilog. I've even created a new LoggerConfiguration() and called .CreateLogger() on it, and set it up just like I do before the try, and it won't log to serilog in the catch. The logger statement in the try logs correctly, as do all of the other places I log in other classes.
14

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();

2 Comments

But how to use the logger before the application is built?
before app is built the logging is configured so it doesn't exist. You can use std Console.WriteLine() or bootstrap serilog.
11

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.

Comments

7

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");

3 Comments

Where does "builder" come from and what is its type?
@NickG see official documentation: learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/… - 'WebApplication.CreateBuilder'
in .Net 8 rc2 worked
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}");
    }

1 Comment

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.
-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/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.