Logging in .NET and ASP.NET Core
Logging in .NET and ASP.NET Core
Logging in an ASP.NET Web API relies on the built-in ILogger interface provided by Microsoft, which supports various built-in and third-party logging providers (sinks). Core Concepts
ILogger: The interface used within your application code to write log messages.
ILoggerFactory / ILoggerProvider: These manage the creation of
ILoggerinstances and determine where logs are sent (e.g., Console, Debug window, files, databases, or cloud services).Log Levels: Messages are categorized by severity:
Trace, Debug, Information, Warning, Error, and Critical.
Severities are ranked from most to least detailed:
Trace (0):Very detailed, often sensitive data.Debug (1):Short-term usefulness during development.Information (2):General flow of the application.Warning (3):Abnormal flow that doesn't stop the app.Error (4):Failures that stop the current operation.Critical (5):Total system failuresDependency Injection (DI): In modern ASP.NET Core, the logging infrastructure is automatically available via DI, making it easy to inject
ILogger<T>into controllers and services.
Step-by-Step Implementation (ASP.NET Core)
The default web API template automatically sets up console, debug, and EventSource providers, with configuration managed in appsettings.json. 1. Configuration in appsettings.json You can control the minimum log level for different categories here.
{
"Logging": {
"LogLevel": {
"Default": "Information", // Default minimum level for all categories
"Microsoft": "Warning" // Overrides the default for Microsoft framework logs
}
}
}
2. Injecting and Using ILogger in a Controller Inject the logger into your controller's constructor. The category name defaults to the class's fully qualified name, aiding organization.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
[ApiController]
[Route("api/[controller]")]
public class SampleController : ControllerBase
{
private readonly ILogger<SampleController> _logger;
// Inject ILogger via constructor
public SampleController(ILogger<SampleController> logger)
{
_logger = logger;
}
[HttpGet]
public IActionResult Get()
{
// Use extension methods to log messages at specific levels
_logger.LogInformation("GET request received for SampleController.");
try
{
// ... application logic ...
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred during the GET request.");
return StatusCode(500, "Internal server error");
}
}
}
Built-in vs. Third-Party Providers
By default, logs are sent to the Console and Debug output. For more robust needs like writing to files or databases, popular third-party libraries include:
Serilog:Known for structured logging (logs as searchable JSON rather than plain text).NLog:Highly flexible with many targets (File, Email, Database).log4net:A classic, modular framework often used in legacy systems.
Implementation of log in file using Serilog
1. Install Required Packages
Use the NuGet Package Manager or the .NET CLI to install the essential library:
- Serilog.AspNetCore
- Serilog.Sinks.File
2. Configure and Register Serilog
Method1: Configure and Register Serilog in Program.cs
// configure serilog to write in a file
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
.WriteTo.File("log/villaLog.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
// register Serilog
builder.Host.UseSerilog();
Method2: Configure via appsettings.json (Recommended)
Add a Serilog section to your appsettings.json file. This allows you to change logging settings without recompiling the code
//JSON
{
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/webapi-.log",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
}
}
path:Specifies the folder and filename (e.g., Logs/webapi-20241027.log).rollingInterval:Set to Day to create a new log file every 24 hours.
Initialize in Program.cs Update your Program.cs to use Serilog as the primary logging provider.
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// Configure Serilog to read from appsettings.json
builder.Host.UseSerilog((context, configuration) =>
configuration.ReadFrom.Configuration(context.Configuration));
builder.Services.AddControllers();
// ... other services
var app = builder.Build();
// Optional: Streamlined request logging (logs every HTTP request)
app.UseSerilogRequestLogging();
app.UseAuthorization();
app.MapControllers();
app.Run();
3. Use the Logger in Controllers
Integrate ILogger<T> via dependency injection in your controllers to use Serilog
Advanced Features
HTTP Logging Middleware: You can log entire HTTP requests and responses (headers, bodies, status codes) by adding
app.UseHttpLogging()inProgram.cs.Step1: - Add Service
builder.Services.AddHttpLogging(options =>
{
options.LoggingFields = Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All;
options.RequestBodyLogLimit = 4096; // Set limits to avoid performance issues
options.ResponseBodyLogLimit = 4096;
});
Step2: Use Middleware (in
Program.cs, before other middleware likeUseAuthorization):app.UseHttpLogging();Configuration: Adjust log levels without changing code by editing the
Loggingsection in appsettings.json.Redaction: Prevent sensitive data (like passwords or PII) from appearing in logs using data redaction tools.
Custom Logging
You can use DI for Logging vai custom class & its interfce
step by step Implementation using Example
1. Create ILogging Interface and Logging class
// ILogging Interface
namespace WebApplication1.Logging
{
public interface ILogging
{
public void Log(string message, string type);
}
}
// Logging class which implement ILogging
namespace WebApplication1.Logging
{
public class Logging : ILogging
{
public void Log(string message, string type)
{
if(type == "error")
{
Console.WriteLine("Error - " +message);
}
else
{
Console.WriteLine(message);
}
}
}
}
2. register a service using lifetime
// In Program.cs
builder.Services.AddSingleton<ILogging, Logging>();
3. Use in controller
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class VillaController : ControllerBase
{
// Inject logging via constrouctor
private readonly ILogging _logger;
public VillaController(ILogging logger)
{
_logger = logger;
}
[ProducesResponseType(StatusCodes.Status200OK)]
[HttpGet]
public ActionResult<IEnumerable<VillaDTO>>GetVillas()
{
// Implement in Http Method
_logger.Log("Getting all Villa.", "");
// _logger.Log("Get villa Error with id: " + id, "error");
return Ok(VillaStore.VillaList);
}
more details: in i want to use another Logging class LoggingV2 we can do as well
step1: Create LoggingV2 class which Implemets same ILogging Interface.
namespace WebApplication1.Logging
{
public class LoggingV2 : ILogging
{
public void Log(string message, string type)
{
if(type == "error")
{
Console.BackgroundColor = ConsoleColor.Red;
Console.WriteLine("Error - "+ message);
Console.BackgroundColor= ConsoleColor.Black;
}else if(type == "warning")
{
Console.BackgroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("Warning - " + message);
Console.BackgroundColor = ConsoleColor.Black;
}
else
{
Console.WriteLine(message);
}
}
}
}
step 2: register service using lifecycle
//builder.Services.AddSingleton<ILogging, Logging>();
builder.Services.AddSingleton<ILogging, LoggingV2>();
DONE ✅✅
Comments
Post a Comment