Aspnet Logging
title: ASP.NET Core Logging — Complete Guide to Application Logging description: 'Learn ASP.NET Core logging: ILogger interface, log levels, structured logging, Serilog, log providers, filtering, and best practices for production logging.' date: 2026-06-28 lastmod: 2026-06-28 weight: 30 tags: [backend, aspnet]
ASP.NET Core logging provides a built-in abstraction through ILogger, supporting structured logging, multiple providers (Console, Debug, EventLog), and third-party libraries like Serilog.
## What You'll Learn
By the end of this tutorial, you'll use ILogger for structured logging, configure log levels per category, integrate Serilog for file/JSON logging, filter sensitive data, and implement best practices.
## Real-World Use
A production API logs all requests with CorrelationId, user ID, and response time. Errors are sent to Elasticsearch via Serilog. The operations team monitors dashboards in Kibana.
## Logging Learning Path
```mermaid
flowchart LR
A[Testing] --> B[Logging]
B --> C[Health Checks]
C --> D[Docker]
D --> E[Deployment]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Basic Logging
public class ProductsController : ControllerBase
{
private readonly ILogger<ProductsController> _logger;
public ProductsController(ILogger<ProductsController> logger) => _logger = logger;
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById(int id)
{
_logger.LogInformation("Fetching product {ProductId}", id);
try
{
var product = await _service.GetByIdAsync(id);
if (product == null)
{
_logger.LogWarning("Product {ProductId} not found", id);
return NotFound();
}
return Ok(product);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching product {ProductId}", id);
throw;
}
}
}
Configuration
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"MyApp": "Debug"
},
"Console": {
"LogLevel": {
"MyApp.Services": "Information"
}
}
}
}
// Program.cs
builder.Logging.ClearProviders(); // Remove default providers
builder.Logging.AddConsole(); // Add console
builder.Logging.AddDebug(); // Add debug (VS Output)
builder.Logging.AddEventLog(); // Windows Event Log
builder.Logging.AddFilter("Microsoft", LogLevel.Warning); // Filter
Serilog Setup
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Seq
using Serilog;
// Configure early (before building app)
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}")
.WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)
.WriteTo.Seq("http://localhost:5341")
.Enrich.WithCorrelationId()
.CreateLogger();
builder.Host.UseSerilog();
// Or configure via appsettings.json
// "Serilog": {
// "MinimumLevel": { "Default": "Information" },
// "WriteTo": [
// { "Name": "Console" },
// { "Name": "File", "Args": { "path": "logs/app-.log", "rollingInterval": "Day" } }
// ]
// }
Structured Logging
// Bad - string concatenation
_logger.LogInformation("User " + userId + " logged in from " + ip);
// Good - structured (searchable)
_logger.LogInformation("User {UserId} logged in from {IpAddress}", userId, ip);
// With custom properties
using (_logger.BeginScope(new Dictionary<string, object>
{
["CorrelationId"] = httpContext.TraceIdentifier,
["UserId"] = userId
}))
{
_logger.LogInformation("Processing order {OrderId}", orderId);
// All logs in this scope include CorrelationId and UserId
}
Common Mistakes
1. String Interpolation in Logs
LogInterpolatedStringHandler may cause issues. Use structured placeholders {Name} instead of string interpolation.
2. Logging Exceptions Incorrectly
Always pass the exception as the first parameter: _logger.LogError(ex, "Message"). Don't log ex.ToString() in the message.
3. Too Much Logging in Hot Paths
Logging in performance-critical code (tight loops) slows the app. Log at higher levels or reduce frequency.
4. Logging Sensitive Data
Credit cards, passwords, and PII in logs create security risks. Use destructuring policies to mask sensitive fields.
5. Using Console.WriteLine in Production
Use ILogger everywhere. Console.WriteLine doesn't create structured logs and can't be filtered.
Practice Questions
1. What is structured logging?
Logging with named placeholders ({UserId}) instead of concatenation. Enables searchable, queryable logs.
2. How do you configure different log levels per category?
In appsettings.json: set LogLevel per namespace (Microsoft.AspNetCore: Warning, MyApp: Debug).
3. What is Serilog?
A popular third-party logging library for .NET with sinks to files, databases, Elasticsearch, Seq, and more.
4. How do you filter logs by level?
Set MinimumLevel or use AddFilter to suppress verbose logs from specific categories.
5. Challenge: Configure Serilog with console and file sinks, and structured logging.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
builder.Host.UseSerilog();
FAQ
Mini Project: Structured Logging with Serilog
Configure a complete logging pipeline with Serilog, console, file, and structured output.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
.WriteTo.Console()
.WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7)
.Enrich.WithMachineName()
.Enrich.WithThreadId()
.CreateLogger();
try {
var app = builder.Build();
app.UseSerilogRequestLogging(); // Log all HTTP requests
app.Run();
} finally { Log.CloseAndFlush(); }
What's Next
ASP.NET Core Health Checks ASP.NET Core Docker
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro