ASP.NET Core 8 Web API -

Logging

Logging is an essential part of any web application. It helps you track application behavior, diagnose issues, and analyze application performance. This guide provides a detailed overview of implementing logging in ASP.NET Core 8 Web API, covering built-in logging, third-party logging providers, structured logging, and best practices.


1. Introduction to Logging

Logging in ASP.NET Core is built around the ILogger interface, which provides methods to log messages at different levels (e.g., Information, Warning, Error). The logging infrastructure is flexible and allows you to plug in various logging providers such as console, file, and third-party services.


2. Built-in Logging

ASP.NET Core includes built-in logging providers that can log to the console, debug window, and more.

2.1 Configuring Logging

Logging is configured in the Program.cs file.

Example:
        
            
var builder = WebApplication.CreateBuilder(args);

// Configure logging
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();

var app = builder.Build();

app.MapControllers();
app.Run();

        
    

2.2 Using ILogger

You can inject ILogger<T> into your controllers or services to log messages.

Example:
        
            
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly ILogger<ProductsController> _logger;

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

    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        _logger.LogInformation("Getting product with id {ProductId}", id);
        
        // Simulate fetching product
        var product = new { Id = id, Name = "Sample Product" };
        
        if (product == null)
        {
            _logger.LogWarning("Product with id {ProductId} not found", id);
            return NotFound();
        }

        return Ok(product);
    }

    [HttpPost]
    public IActionResult CreateProduct([FromBody] Product product)
    {
        if (!ModelState.IsValid)
        {
            _logger.LogWarning("Invalid product model received");
            return BadRequest(ModelState);
        }

        _logger.LogInformation("Creating a new product: {ProductName}", product.Name);

        // Simulate saving product
        product.Id = new Random().Next(1, 1000);

        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
}

        
    

3. Third-Party Logging Providers

ASP.NET Core allows you to integrate third-party logging providers like Serilog, NLog, and log4net for more advanced logging features.

3.1 Serilog Install Serilog:
        
            
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File

        
    
Configure Serilog:
        
            
using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Configure Serilog
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog();

var app = builder.Build();

app.MapControllers();
app.Run();

        
    


3.2 NLog Install NLog:
        
            
dotnet add package NLog.Web.AspNetCore

        
    
Configure NLog:
        
            
using NLog.Web;

var builder = WebApplication.CreateBuilder(args);

// Configure NLog
builder.Logging.ClearProviders();
builder.Host.UseNLog();

var app = builder.Build();

app.MapControllers();
app.Run();

        
    

4. Structured Logging

Structured logging allows you to log data in a structured format, making it easier to query and analyze.

Example with Serilog:
        
            
[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
    if (!ModelState.IsValid)
    {
        _logger.LogWarning("Invalid product model received");
        return BadRequest(ModelState);
    }

    _logger.LogInformation("Creating a new product: {@Product}", product);

    // Simulate saving product
    product.Id = new Random().Next(1, 1000);

    return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

        
    

5. Logging Scopes

Logging scopes provide a way to group a set of log messages together, making it easier to trace the flow of a particular operation.

Example:
        
            
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
    using (_logger.BeginScope("Getting product with id {ProductId}", id))
    {
        _logger.LogInformation("Fetching product");

        // Simulate fetching product
        var product = new { Id = id, Name = "Sample Product" };

        if (product == null)
        {
            _logger.LogWarning("Product with id {ProductId} not found", id);
            return NotFound();
        }

        _logger.LogInformation("Returning product with id {ProductId}", id);
        return Ok(product);
    }
}

        
    

6. Log Filtering

You can control which logs are written based on their log level and category.

Configure Log Levels in appsettings.json:
        
            
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

        
    

7. Best Practices


8. Comprehensive Example

Here is a comprehensive example combining various logging techniques.

Program.cs:
        
            
using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Configure Serilog
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog();

// Add services to the container
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.Run();

        
    


Product Model:
        
            
public class Product
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Name is required")]
    [StringLength(100, ErrorMessage = "Name can't be longer than 100 characters")]
    public string Name { get; set; }

    [Range(0.01, 1000.00, ErrorMessage = "Price must be between 0.01 and 1000.00")]
    public decimal Price { get; set; }
}

        
    


Products Controller:
        
            
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly ILogger<ProductsController> _logger;

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

    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        using (_logger.BeginScope("Getting product with id {ProductId}", id))
        {
            _logger.LogInformation("Fetching product");

            // Simulate fetching product
            var product = new Product { Id = id, Name = "Sample Product", Price = 9.99m };

            if (product == null)
            {
                _logger.LogWarning("Product with id {ProductId} not found", id);
                return NotFound();
            }

            _logger.LogInformation("Returning product with id {ProductId}", id);
            return Ok(product);
        }
    }

    [HttpPost]
    public IActionResult CreateProduct([FromBody] Product product)
    {
        if (!ModelState.IsValid)
        {
            _logger.LogWarning("Invalid product model received");
            return BadRequest(ModelState);
        }

        _logger.LogInformation("Creating a new product: {@Product}", product);

        // Simulate saving product
        product.Id = new Random().Next(1, 1000);

        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
}

        
    

9. Conclusion

Logging is a critical aspect of any ASP.NET Core 8 Web API application. By using built-in logging providers, integrating third-party logging frameworks like Serilog, implementing structured logging, and following best practices, you can effectively monitor and troubleshoot your application. This comprehensive guide provides the foundation for implementing robust logging in your ASP.NET Core 8 Web API projects.