ASP.NET Core startup logging with Console.WriteLine and Serilog

Posted: (EET/GMT+2)

 

Happy April! If your ASP.NET Core application fails very early during startup, you might not get any log output at all. A simple way to make startup failures easier to diagnose is to write a few bootstrap messages to the console first, then hand over to Serilog as early as possible.

The main issue is that logging can start too late. If configuration, service registration (dependency injection), or host building fails, the normal logging pipeline might never come alive. In that case, a small Console.WriteLine at the very beginning is still useful.

It is also worth including the application name and version in the very first console line. That helps confirm which binary is actually deployed when you are checking logs on a server.

Here is a small example, assuming you have a C# ASP.NET Core application at hand and the Serilog's NuGet package Serilog.AspNetCore installed.

using System.Reflection;
using Serilog;

Assembly assembly = Assembly.GetEntryAssembly();
string appName = assembly?.GetName().Name ?? "UnknownApp";
string version = assembly?.GetName().Version?.ToString() ?? "unknown";

Console.WriteLine($"{appName} starting, version {version}.");

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger();

try
{
    Log.Information("Building web application");

    var builder = WebApplication.CreateBuilder(args);

    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration)
        .ReadFrom.Services(services)
        .WriteTo.Console());

    Console.WriteLine("Configuring services");

    builder.Services.AddControllers();

    var app = builder.Build();

    Log.Information("Starting web application");

    app.MapControllers();

    app.Run();
}
catch (Exception ex)
{
    Console.WriteLine($"Fatal startup error: {ex}");
    Log.Fatal(ex, "Application startup failed");
}
finally
{
    Log.CloseAndFlush();
}

A few practical notes:

  • Console.WriteLine is useful for the first checkpoints only. Keep it short and focused.
  • Log the application name and version first. That makes it easier to confirm the deployed build.
  • Wrap startup in try/catch/finally so fatal exceptions are visible and buffered logs are flushed.
  • If dependency injection or configuration throws during startup, Serilog might not get far enough to help unless you initialize it very early.

One more thing: some failures happen even earlier than your own code. For example, if the required .NET runtime is missing or the installed runtime does not match what the application needs, the process may fail before your first log line is written. In that case, there may be no application logs at all, so it is worth checking the server runtime installation separately.

So the practical pattern is simple: write one early console line with name and version, initialize Serilog as early as possible, and always catch fatal startup exceptions.

Happy (early) logging!