.NET - Logging in .NET Core

Logging in .NET Core - Complete Guide with Examples

Logging in .NET Core

Logging in .NET Core is a fundamental part of building robust, maintainable, and production-ready applications. Effective logging helps developers track the application's behavior, troubleshoot errors, and understand performance issues. This tutorial provides a comprehensive guide to logging in .NET Core, covering built-in logging support, third-party providers like Serilog and NLog, best practices, and practical examples to enhance your application's observability.

What is Logging in .NET Core?

Logging in .NET Core refers to the process of capturing and recording diagnostic information from your application while it runs. It can be used to log information, warnings, errors, and critical failures to various output destinations such as the console, file system, or cloud-based services.

Key Concepts of Logging in .NET Core

ILogger Interface

At the core of .NET Core's logging is the ILogger interface, which provides methods for logging messages at different severity levels.

Logging Providers

Logging providers are responsible for sending the logs to various outputs such as:

  • Console
  • File
  • Debug
  • Azure Application Insights
  • EventLog (Windows)
  • Third-party (Serilog, NLog, etc.)

Logging Levels

.NET Core supports several logging levels:

  • Trace
  • Debug
  • Information
  • Warning
  • Error
  • Critical
  • None

Setting Up Logging in ASP.NET Core

Default Logging with Console and Debug Providers

ASP.NET Core comes with built-in logging providers. By default, the Console and Debug providers are included.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.AddConsole();
                logging.AddDebug();
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Using ILogger in a Controller

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        _logger.LogInformation("Index page visited at {Time}", DateTime.UtcNow);
        return View();
    }
}

Logging Configuration in appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

You can control the verbosity of logs based on the namespace or source. This is very helpful in filtering out noisy logs from the framework libraries.

Structured Logging with Serilog

Installing Serilog

dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File

Program.cs Setup

public class Program
{
    public static void Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .WriteTo.Console()
            .WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();

        try
        {
            Log.Information("Starting up...");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Application start-up failed");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseSerilog() // Add this line
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Using NLog with .NET Core

Installing NLog

dotnet add package NLog.Web.AspNetCore

Setting Up NLog.config

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <targets>
    <target name="logfile" xsi:type="File" fileName="nlog-file.txt" />
    <target name="logconsole" xsi:type="Console" />
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="logconsole,logfile" />
  </rules>

</nlog>

Program.cs with NLog

public class Program
{
    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();

        try
        {
            logger.Debug("init main");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception exception)
        {
            logger.Error(exception, "Stopped program because of exception");
            throw;
        }
        finally
        {
            NLog.LogManager.Shutdown();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .UseNLog();  // NLog: Setup NLog for Dependency injection
}

Logging Exceptions

try
{
    throw new Exception("Something went wrong!");
}
catch (Exception ex)
{
    _logger.LogError(ex, "Exception occurred in business logic");
}

Custom Logging Middleware

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestLoggingMiddleware> _logger;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        _logger.LogInformation("Handling request: {Method} {Url}", context.Request.Method, context.Request.Path);
        await _next(context);
        _logger.LogInformation("Finished handling request.");
    }
}

Filtering Logs

To reduce log verbosity, you can apply filters programmatically or via configuration.

logging.AddFilter("Microsoft", LogLevel.Warning);
logging.AddFilter("System", LogLevel.Error);

Exporting Logs to External Services

  • Elasticsearch using Serilog Sink
  • Azure Application Insights
  • Logstash via TCP
  • CloudWatch for AWS deployments


Logging in .NET Core is essential for diagnosing issues, tracking the behavior of your applications, and maintaining healthy production systems. Whether you use the built-in providers or third-party tools like Serilog and NLog, understanding the logging infrastructure can significantly boost your app’s maintainability and reliability. Make sure to configure logging according to your environment and follow best practices like structured logging and error-level filtering to avoid unnecessary clutter and data loss.

This guide to Logging in .NET Core is not only intended for beginners but also for seasoned developers looking to implement scalable logging infrastructure in ASP.NET Core Web APIs, MVC applications, and background services.

Beginner 5 Hours
Logging in .NET Core - Complete Guide with Examples

Logging in .NET Core

Logging in .NET Core is a fundamental part of building robust, maintainable, and production-ready applications. Effective logging helps developers track the application's behavior, troubleshoot errors, and understand performance issues. This tutorial provides a comprehensive guide to logging in .NET Core, covering built-in logging support, third-party providers like Serilog and NLog, best practices, and practical examples to enhance your application's observability.

What is Logging in .NET Core?

Logging in .NET Core refers to the process of capturing and recording diagnostic information from your application while it runs. It can be used to log information, warnings, errors, and critical failures to various output destinations such as the console, file system, or cloud-based services.

Key Concepts of Logging in .NET Core

ILogger Interface

At the core of .NET Core's logging is the ILogger interface, which provides methods for logging messages at different severity levels.

Logging Providers

Logging providers are responsible for sending the logs to various outputs such as:

  • Console
  • File
  • Debug
  • Azure Application Insights
  • EventLog (Windows)
  • Third-party (Serilog, NLog, etc.)

Logging Levels

.NET Core supports several logging levels:

  • Trace
  • Debug
  • Information
  • Warning
  • Error
  • Critical
  • None

Setting Up Logging in ASP.NET Core

Default Logging with Console and Debug Providers

ASP.NET Core comes with built-in logging providers. By default, the Console and Debug providers are included.

public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.ClearProviders(); logging.AddConsole(); logging.AddDebug(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }

Using ILogger in a Controller

public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { _logger.LogInformation("Index page visited at {Time}", DateTime.UtcNow); return View(); } }

Logging Configuration in appsettings.json

{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } } }

You can control the verbosity of logs based on the namespace or source. This is very helpful in filtering out noisy logs from the framework libraries.

Structured Logging with Serilog

Installing Serilog

dotnet add package Serilog.AspNetCore dotnet add package Serilog.Sinks.File

Program.cs Setup

public class Program { public static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); try { Log.Information("Starting up..."); CreateHostBuilder(args).Build().Run(); } catch (Exception ex) { Log.Fatal(ex, "Application start-up failed"); } finally { Log.CloseAndFlush(); } } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSerilog() // Add this line .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }

Using NLog with .NET Core

Installing NLog

dotnet add package NLog.Web.AspNetCore

Setting Up NLog.config

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="logfile" xsi:type="File" fileName="nlog-file.txt" /> <target name="logconsole" xsi:type="Console" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="logconsole,logfile" /> </rules> </nlog>

Program.cs with NLog

public class Program { public static void Main(string[] args) { var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); try { logger.Debug("init main"); CreateHostBuilder(args).Build().Run(); } catch (Exception exception) { logger.Error(exception, "Stopped program because of exception"); throw; } finally { NLog.LogManager.Shutdown(); } } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .UseNLog(); // NLog: Setup NLog for Dependency injection }

Logging Exceptions

try { throw new Exception("Something went wrong!"); } catch (Exception ex) { _logger.LogError(ex, "Exception occurred in business logic"); }

Custom Logging Middleware

public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestLoggingMiddleware> _logger; public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) { _next = next; _logger = logger; } public async Task Invoke(HttpContext context) { _logger.LogInformation("Handling request: {Method} {Url}", context.Request.Method, context.Request.Path); await _next(context); _logger.LogInformation("Finished handling request."); } }

Filtering Logs

To reduce log verbosity, you can apply filters programmatically or via configuration.

logging.AddFilter("Microsoft", LogLevel.Warning); logging.AddFilter("System", LogLevel.Error);

Exporting Logs to External Services

  • Elasticsearch using Serilog Sink
  • Azure Application Insights
  • Logstash via TCP
  • CloudWatch for AWS deployments


Logging in .NET Core is essential for diagnosing issues, tracking the behavior of your applications, and maintaining healthy production systems. Whether you use the built-in providers or third-party tools like Serilog and NLog, understanding the logging infrastructure can significantly boost your app’s maintainability and reliability. Make sure to configure logging according to your environment and follow best practices like structured logging and error-level filtering to avoid unnecessary clutter and data loss.

This guide to Logging in .NET Core is not only intended for beginners but also for seasoned developers looking to implement scalable logging infrastructure in ASP.NET Core Web APIs, MVC applications, and background services.

Related Tutorials

Frequently Asked Questions for General

line

Copyrights © 2024 letsupdateskills All rights reserved