Loggers (Логери)
Логерите записват информация за работата на програмата, като грешки, предупреждения, информационни съобщения и действия на потребителите. Те са критични за наблюдение, диагностика и отстраняване на проблеми.
ILogger интерфейс
public interface ILogger
{
void Log(LogLevel level, string message);
void LogError(string message);
void LogWarning(string message);
void LogInfo(string message);
void LogDebug(string message);
}
public enum LogLevel
{
Debug,
Info,
Warning,
Error,
Critical
}
ConsoleLogger
public class ConsoleLogger : ILogger
{
public void Log(LogLevel level, string message)
{
var color = GetColorForLevel(level);
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Console.ForegroundColor = color;
Console.WriteLine($"[{timestamp}] {level}: {message}");
Console.ResetColor();
}
public void LogError(string message) => Log(LogLevel.Error, message);
public void LogWarning(string message) => Log(LogLevel.Warning, message);
public void LogInfo(string message) => Log(LogLevel.Info, message);
public void LogDebug(string message) => Log(LogLevel.Debug, message);
private ConsoleColor GetColorForLevel(LogLevel level)
{
return level switch
{
LogLevel.Debug => ConsoleColor.Gray,
LogLevel.Info => ConsoleColor.White,
LogLevel.Warning => ConsoleColor.Yellow,
LogLevel.Error => ConsoleColor.Red,
LogLevel.Critical => ConsoleColor.DarkRed,
_ => ConsoleColor.White
};
}
}
FileLogger
public class FileLogger : ILogger, IDisposable
{
private readonly string filePath;
private readonly StreamWriter writer;
private readonly object lockObject = new object();
public FileLogger(string filePath)
{
this.filePath = filePath;
this.writer = new StreamWriter(filePath, true);
}
public void Log(LogLevel level, string message)
{
var logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}";
lock (lockObject)
{
writer.WriteLine(logEntry);
writer.Flush();
}
}
public void LogError(string message) => Log(LogLevel.Error, message);
public void LogWarning(string message) => Log(LogLevel.Warning, message);
public void LogInfo(string message) => Log(LogLevel.Info, message);
public void LogDebug(string message) => Log(LogLevel.Debug, message);
public void Dispose()
{
writer?.Dispose();
}
}
Serilog пример
public class SerilogExample
{
public static void ConfigureSerilog()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day)
.WriteTo.Seq("http://localhost:5341")
.Enrich.WithProperty("Application", "MyApp")
.Enrich.WithMachineName()
.CreateLogger();
Log.Information("Application Starting");
}
public static void LoggingExample()
{
try
{
throw new Exception("Something went wrong");
}
catch (Exception ex)
{
Log.Error(ex, "An error occurred");
}
}
}
Структурирано логване
public class StructuredLogging
{
private readonly ILogger<StructuredLogging> _logger;
public void ProcessOrder(Order order)
{
_logger.LogInformation(
"Processing order {OrderId} for customer {CustomerId} with total {Total:C}",
order.Id,
order.CustomerId,
order.Total);
try
{
// Обработка на поръчката
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Failed to process order {OrderId}. Error: {ErrorMessage}",
order.Id,
ex.Message);
}
}
}
Логване с контекст
public class ContextualLogging
{
private readonly ILogger _logger;
public async Task ProcessUserAction(string userId, string action)
{
using (var scope = _logger.BeginScope(new Dictionary<string, object>
{
["UserId"] = userId,
["Action"] = action,
["SessionId"] = Guid.NewGuid()
}))
{
_logger.LogInformation("Starting user action");
// Действия
_logger.LogInformation("Completed user action");
}
}
}
Композитен логер
public class CompositeLogger : ILogger
{
private readonly ILogger[] loggers;
public CompositeLogger(params ILogger[] loggers)
{
this.loggers = loggers;
}
public void Log(LogLevel level, string message)
{
foreach (var logger in loggers)
{
try
{
logger.Log(level, message);
}
catch (Exception ex)
{
// Логване на грешката в останалите логери
foreach (var otherLogger in loggers.Where(l => l != logger))
{
otherLogger.LogError($"Logger failed: {ex.Message}");
}
}
}
}
public void LogError(string message) => Log(LogLevel.Error, message);
public void LogWarning(string message) => Log(LogLevel.Warning, message);
public void LogInfo(string message) => Log(LogLevel.Info, message);
public void LogDebug(string message) => Log(LogLevel.Debug, message);
}
Добри практики
- Нива на логване
// Правилно използване на нивата
logger.LogDebug("Detailed information for debugging");
logger.LogInformation("General information about app operation");
logger.LogWarning("Warning messages for potentially harmful situations");
logger.LogError("Error messages for failures that should be investigated");
logger.LogCritical("Critical errors that require immediate attention");
- Структурирани данни
// Лошо
logger.LogInformation($"User {userId} logged in from IP {ipAddress}");
// Добре
logger.LogInformation(
"User logged in. {UserId} {IpAddress}",
userId,
ipAddress);
- Обработка на изключения
try
{
// Код
}
catch (Exception ex)
{
logger.LogError(
ex,
"Operation failed. {ErrorDetails}",
new { ex.Message, ex.StackTrace });
throw;
}
- Конфигурация
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.AddDebug();
logging.AddEventLog();
logging.SetMinimumLevel(LogLevel.Information);
});
HashLogger
HashLogger