using TradingBot.Models; using System.Collections.Concurrent; namespace TradingBot.Services; /// /// Centralized logging service for application events /// public class LoggingService { private readonly ConcurrentQueue _logs = new(); private const int MaxLogEntries = 500; public event Action? OnLogAdded; /// /// Get all log entries /// public IReadOnlyList GetLogs() { return _logs.ToList().AsReadOnly(); } /// /// Add a debug log entry /// public void LogDebug(string category, string message, string? details = null) { AddLog(Models.LogLevel.Debug, category, message, details); } /// /// Add an info log entry /// public void LogInfo(string category, string message, string? details = null, string? symbol = null) { AddLog(Models.LogLevel.Info, category, message, details, symbol); } /// /// Add a warning log entry /// public void LogWarning(string category, string message, string? details = null, string? symbol = null) { AddLog(Models.LogLevel.Warning, category, message, details, symbol); } /// /// Add an error log entry /// public void LogError(string category, string message, string? details = null, string? symbol = null) { AddLog(Models.LogLevel.Error, category, message, details, symbol); } /// /// Add a trade log entry /// public void LogTrade(string symbol, string message, string? details = null) { AddLog(Models.LogLevel.Trade, "Trading", message, details, symbol); } /// /// Clear all logs /// public void ClearLogs() { _logs.Clear(); OnLogAdded?.Invoke(); } /// /// Get logs filtered by level /// public IReadOnlyList GetLogsByLevel(Models.LogLevel level) { return _logs.Where(l => l.Level == level).ToList().AsReadOnly(); } /// /// Get logs filtered by category /// public IReadOnlyList GetLogsByCategory(string category) { return _logs.Where(l => l.Category.Equals(category, StringComparison.OrdinalIgnoreCase)) .ToList() .AsReadOnly(); } /// /// Get logs filtered by symbol /// public IReadOnlyList GetLogsBySymbol(string symbol) { return _logs.Where(l => l.Symbol != null && l.Symbol.Equals(symbol, StringComparison.OrdinalIgnoreCase)) .ToList() .AsReadOnly(); } private void AddLog(Models.LogLevel level, string category, string message, string? details = null, string? symbol = null) { var logEntry = new LogEntry { Level = level, Category = category, Message = message, Details = details, Symbol = symbol }; _logs.Enqueue(logEntry); // Maintain max size while (_logs.Count > MaxLogEntries) { _logs.TryDequeue(out _); } OnLogAdded?.Invoke(); } }