using System.Runtime.CompilerServices; namespace IBKRTrader.Core.Logging; /// /// Thread-sicherer Logging-Service. /// – Schreibt farbig in die RichTextBox (UI-Thread-safe via BeginInvoke) /// – Schreibt in Logs\{Module}\{Level}-dd-MM-yy.txt /// public class LoggingService { private RichTextBox? _rtb; private AppLogLevel _minLevel = AppLogLevel.Info; private readonly object _fileLock = new(); private static readonly string LogBaseDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); // ─── Konfiguration ──────────────────────────────────────────────────────── public void AttachRichTextBox(RichTextBox rtb) => _rtb = rtb; public void SetMinLevel(AppLogLevel level) => _minLevel = level; // ─── Öffentliche API ───────────────────────────────────────────────────── public void Info (string module, string message, Exception? ex = null) => Write(AppLogLevel.Info, module, message, ex); public void Warn (string module, string message, Exception? ex = null) => Write(AppLogLevel.Warn, module, message, ex); public void Error(string module, string message, Exception? ex = null) => Write(AppLogLevel.Error, module, message, ex); public void Write(AppLogLevel level, string module, string message, Exception? ex = null) { if (level < _minLevel) return; var entry = new LogEntry(DateTime.Now, level, module, message, ex); WriteToFile(entry); WriteToRtb(entry); } // ─── Datei ──────────────────────────────────────────────────────────────── private void WriteToFile(LogEntry e) { try { var dir = Path.Combine(LogBaseDir, e.Module); Directory.CreateDirectory(dir); var file = Path.Combine(dir, $"{e.Level}-{e.Timestamp:dd-MM-yy}.txt"); var line = $"[{e.Timestamp:HH:mm:ss}] {e.Message}"; if (e.Exception != null) line += $"\r\n {e.Exception}"; lock (_fileLock) File.AppendAllText(file, line + "\r\n"); } catch { /* Logging darf niemals abstürzen */ } } // ─── RichTextBox ────────────────────────────────────────────────────────── private static readonly Color ColorInfo = Color.FromArgb(150, 210, 150); private static readonly Color ColorWarn = Color.FromArgb(255, 190, 60); private static readonly Color ColorError = Color.FromArgb(255, 80, 80); private void WriteToRtb(LogEntry e) { if (_rtb == null) return; try { var color = e.Level switch { AppLogLevel.Warn => ColorWarn, AppLogLevel.Error => ColorError, _ => ColorInfo }; var text = $"[{e.Timestamp:HH:mm:ss}] [{e.Level.ToString().ToUpper(),-5}] [{e.Module}] {e.Message}"; if (e.Exception != null) text += $"\r\n {e.Exception.Message}"; text += "\r\n"; if (_rtb.InvokeRequired) _rtb.BeginInvoke(() => AppendColored(text, color)); else AppendColored(text, color); } catch { } } private void AppendColored(string text, Color color) { if (_rtb == null) return; _rtb.SelectionStart = _rtb.TextLength; _rtb.SelectionLength = 0; _rtb.SelectionColor = color; _rtb.AppendText(text); _rtb.SelectionColor = _rtb.ForeColor; if (_rtb.TextLength > 0) _rtb.ScrollToCaret(); } }