using System; using System.IO; namespace PulseDock.App.Services.Implementations { public class LoggerService : Interfaces.ILoggerService { private readonly string _logDir; private readonly string _logFilePath; private readonly object _lock = new(); private const long MaxLogFileSizeBytes = 2 * 1024 * 1024; // 2 MB public LoggerService() { var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); _logDir = Path.Combine(appData, "PulseDock", "logs"); Directory.CreateDirectory(_logDir); _logFilePath = Path.Combine(_logDir, "pulse_dock.log"); } public void LogInfo(string message) => WriteLog("INFO", message); public void LogWarning(string message) => WriteLog("WARN", message); public void LogError(string message, Exception? exception = null) { var fullMessage = exception != null ? $"{message} | Exception: {exception}" : message; WriteLog("ERROR", fullMessage); } private void WriteLog(string level, string message) { lock (_lock) { try { RotateLogsIfNeeded(); var line = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{level}] {message}{Environment.NewLine}"; File.AppendAllText(_logFilePath, line); } catch { // Fail silently to avoid crash from logger } } } private void RotateLogsIfNeeded() { if (!File.Exists(_logFilePath)) return; var fileInfo = new FileInfo(_logFilePath); if (fileInfo.Length >= MaxLogFileSizeBytes) { var backupPath = Path.Combine(_logDir, $"pulse_dock_{DateTime.Now:yyyyMMdd_HHmmss}.log"); File.Move(_logFilePath, backupPath); // Keep only top 3 oldest logs var oldLogs = Directory.GetFiles(_logDir, "pulse_dock_*.log"); if (oldLogs.Length > 3) { Array.Sort(oldLogs); for (int i = 0; i < oldLogs.Length - 3; i++) { try { File.Delete(oldLogs[i]); } catch { } } } } } } }