📝 Serilog = Structured Logging
Text logs are hard to search. Serilog provides structured logging with rich data for better observability.
📝 Serilog Setup
// Program.cs
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day)
.WriteTo.Elasticsearch()
.Enrich.WithProperty("Application", "MyApp")
.Enrich.WithProperty("Environment", "Production")
.CreateLogger();
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// appsettings.json
{
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
"MinimumLevel": "Information",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "logs/app.log",
"rollingInterval": "Day"
}
}
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"]
}
}
🎯 Structured Logging
// Traditional (bad)
_logger.LogInformation($"User {user.Id} logged in at {DateTime.Now}");
// Structured (good)
_logger.LogInformation("User {UserId} logged in at {LoginTime}",
user.Id, DateTime.UtcNow);
// With context
_logger.LogInformation(
"User {UserId} purchased {ProductName} for {Price:C}",
user.Id, product.Name, product.Price);
// Error with details
try {
// operation
} catch (Exception ex) {
_logger.LogError(ex,
"Failed to process order {OrderId} for user {UserId}",
order.Id, order.UserId);
}
// Using ForContext
var userLogger = _logger.ForContext("User", user);
userLogger.LogInformation("User logged in");
// Correlation IDs
using (_logger.BeginScope(new { CorrelationId = correlationId }))
{
// All logs in this scope include CorrelationId
_logger.LogInformation("Processing request");
}
// Timed operations
using var timer = _logger.BeginTimedOperation("Database query",
new { Query = sql, Parameters = parameters });
var result = await db.QueryAsync(sql, parameters);
💡 Logging Best Practices
- Use structured logging
- Include correlation IDs
- Log at appropriate levels
- Use property names consistently
- Don’t log sensitive data
Structured logging transforms debugging from guesswork to science. It’s essential for modern applications.
