📝 Logging = Observability
Logging is essential. ILogger best practices provide effective logging in .NET Core.
📝 Logging Basics
// Basic Logging
public class UserService
{
private readonly ILogger _logger;
public UserService(ILogger logger)
{
_logger = logger;
}
public async Task GetUserAsync(int id)
{
_logger.LogInformation("Getting user {UserId}", id);
try
{
var user = await _repository.GetUserAsync(id);
if (user == null)
{
_logger.LogWarning("User {UserId} not found", id);
return null;
}
_logger.LogInformation("User {UserId} found: {UserName}", id, user.Name);
return user;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting user {UserId}", id);
throw;
}
}
}
// Log Levels
_logger.LogTrace("Trace message");
_logger.LogDebug("Debug message");
_logger.LogInformation("Information message");
_logger.LogWarning("Warning message");
_logger.LogError("Error message");
_logger.LogCritical("Critical message");
🎯 Advanced Logging
// Scoped Logging
using (_logger.BeginScope(new { UserId = userId, RequestId = requestId }))
{
_logger.LogInformation("Processing request");
// All logs in this scope include UserId and RequestId
}
// Structured Logging
_logger.LogInformation(
"User {UserId} purchased {ProductName} for {Price:C}",
user.Id, product.Name, product.Price);
// Performance Logging
var stopwatch = Stopwatch.StartNew();
await ProcessDataAsync();
stopwatch.Stop();
_logger.LogInformation("Processing took {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
// Conditional Logging
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Detailed debug information");
}
// Factory Pattern
public class LoggerFactoryService
{
private readonly ILogger _logger;
public LoggerFactoryService(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger();
}
}
💡 Logging Tips
- Use appropriate log levels
- Log structured data
- Include correlation IDs
- Don’t log sensitive data
- Use scopes for context
Good logging practices make applications observable. They help you understand and debug issues.
