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.
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.
At the core of .NET Core's logging is the ILogger interface, which provides methods for logging messages at different severity levels.
Logging providers are responsible for sending the logs to various outputs such as:
.NET Core supports several logging levels:
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>();
});
}
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": {
"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.
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File
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>();
});
}
dotnet add package NLog.Web.AspNetCore
<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>
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
}try
{
throw new Exception("Something went wrong!");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred in business logic");
}
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.");
}
}
To reduce log verbosity, you can apply filters programmatically or via configuration.
logging.AddFilter("Microsoft", LogLevel.Warning);
logging.AddFilter("System", LogLevel.Error);
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.
Copyrights © 2024 letsupdateskills All rights reserved