Home > Software design >  How to use Logger in program.cs in .NET 6, before builder.Build()
How to use Logger in program.cs in .NET 6, before builder.Build()

Time:08-24

Using the default WebAPI framework VS2022 in .NET 6. I would like to log information using ILogger, but before the call of "var app = builder.Build();". How should I do that?

Here the code of program.cs

var builder = WebApplication.CreateBuilder(args);

string insightConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");

builder.Host.ConfigureLogging(logging =>
{
    logging.ClearProviders();
    logging.AddApplicationInsights(insightConnectionString);
    logging.AddConsole();
});

// -----> I want to log information here, before the call of "var app = builder.Build();" <-----

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// -----> And I want to log information here, before the call of "var app = builder.Build();" <-----

var app = builder.Build();

app.Logger.LogInformation("Log some information #1");

//...

app.Logger.LogInformation("Log some information #2");

app.Run();

CodePudding user response:

There is actually a better reason to do it like this: FLUSH of logs. When your app stops on error immediately your logs can be lost because they often written in queue first and then at your destination in some other thread. For example ASP apps write console/file logs this way, which different from Console apps - they stop execution on writes/reads. You have to give it some time to roll through this queue because it helps to see why it crashed. It is not guaranteed that queue will be flushed, but in most cases simple wait is enough, especially if your service crashes on restarts.

This way you can also use it in Program.cs

public static class Program
{
    public static async Task Main(string[] args)
    {
        var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: false)
            .AddJsonFile($"appsettings.{env}.json", optional: true)
            .AddEnvironmentVariables()
            .AddCommandLine(args)
            .Build();
        
        var logFactory = SerilogLogFactory.Create(configuration);
        AppDomain.CurrentDomain.UnhandledException  = (sender, e) =>
        {
            using (var log = logFactory.CreateLog("Unhandled"))
            {
                log.WriteError(e.ExceptionObject);
            }
            logFactory.Flush(TimeSpan.FromSeconds(5));
        };

        try
        {
            await Host
                  .CreateDefaultBuilder(args)
                  .ConfigureAppConfiguration(
                      (context, builder) =>
                      {
                          builder.AddConfiguration(configuration, shouldDisposeConfiguration: true);
                      })
                  .ConfigureLogging(x =>
                  {
                      x.ClearProviders();
                      x.AddProvider(logFactory);
                  })
                  .Build()
                  .RunAsync();
        }
        catch (Exception e)
        {
            using var log = logFactory.CreateLog("Startup");
            log.WriteError(e);

            throw;
        }
        finally
        {
            logFactory.Flush(TimeSpan.FromSeconds(5));
        }
    }
}

CodePudding user response:

You can manually create LoggerFactory and Logger:

using var loggerFactory = LoggerFactory.Create(loggingBuilder => loggingBuilder
    .SetMinimumLevel(LogLevel.Trace)
    .AddConsole());

ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
  • Related