using System; using System.IO; using System.Text; using System.Threading; namespace VideoReader { public static class DetailedLogger { private static readonly object _lockObject = new object(); private static string _logFilePath; private static bool _isInitialized = false; public static void Initialize() { if (_isInitialized) return; var timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); _logFilePath = $"videoreader_detailed_{timestamp}.log"; lock (_lockObject) { try { File.WriteAllText(_logFilePath, $"=== VideoReader Global Edition Detailed Log ===\n"); File.AppendAllText(_logFilePath, $"Session started: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}\n"); File.AppendAllText(_logFilePath, $"Process ID: {Environment.ProcessId}\n"); File.AppendAllText(_logFilePath, $"Machine: {Environment.MachineName}\n"); File.AppendAllText(_logFilePath, $"User: {Environment.UserName}\n"); File.AppendAllText(_logFilePath, "==============================================\n\n"); _isInitialized = true; Console.WriteLine($"Detailed logging initialized: {_logFilePath}"); } catch (Exception ex) { Console.WriteLine($"Failed to initialize logging: {ex.Message}"); } } } public static void LogConnection(string message) { WriteLog("CONNECTION", message); } public static void LogPacket(string direction, byte[] data, string description = "") { var hexData = BitConverter.ToString(data).Replace("-", " "); var asciiData = GetAsciiRepresentation(data); var logMessage = new StringBuilder(); logMessage.AppendLine($"Direction: {direction}"); logMessage.AppendLine($"Size: {data.Length} bytes"); if (!string.IsNullOrEmpty(description)) logMessage.AppendLine($"Description: {description}"); logMessage.AppendLine($"HEX: {hexData}"); logMessage.AppendLine($"ASCII: {asciiData}"); logMessage.AppendLine($"Binary dump:"); // Форматированный hex dump как в hex editor for (int i = 0; i < data.Length; i += 16) { var offset = $"{i:X8}"; var hexLine = new StringBuilder(); var asciiLine = new StringBuilder(); for (int j = 0; j < 16; j++) { if (i + j < data.Length) { hexLine.Append($"{data[i + j]:X2} "); asciiLine.Append(data[i + j] >= 32 && data[i + j] <= 126 ? (char)data[i + j] : '.'); } else { hexLine.Append(" "); asciiLine.Append(" "); } } logMessage.AppendLine($"{offset}: {hexLine} | {asciiLine}"); } WriteLog("PACKET", logMessage.ToString()); } public static void LogPhoneConnection(string phoneInfo, string action) { WriteLog("PHONE", $"Action: {action} | Phone: {phoneInfo}"); } public static void LogError(string error, Exception ex = null) { var message = error; if (ex != null) { message += $"\nException: {ex.GetType().Name}: {ex.Message}"; message += $"\nStackTrace: {ex.StackTrace}"; } WriteLog("ERROR", message); } public static void LogDebug(string message) { WriteLog("DEBUG", message); } public static void LogInfo(string message) { WriteLog("INFO", message); } private static void WriteLog(string level, string message) { if (!_isInitialized) Initialize(); var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); var threadId = Thread.CurrentThread.ManagedThreadId; var logEntry = $"[{timestamp}] [{level}] [Thread-{threadId}] {message}\n"; lock (_lockObject) { try { File.AppendAllText(_logFilePath, logEntry); // Дублируем важные сообщения в консоль if (level == "CONNECTION" || level == "PHONE" || level == "ERROR") { Console.WriteLine($"[{level}] {message}"); } } catch (Exception ex) { Console.WriteLine($"Logging failed: {ex.Message}"); } } } private static string GetAsciiRepresentation(byte[] data) { var result = new StringBuilder(); foreach (var b in data) { if (b >= 32 && b <= 126) result.Append((char)b); else result.Append('.'); } return result.ToString(); } public static void LogStatistics() { var stats = new StringBuilder(); stats.AppendLine("=== SESSION STATISTICS ==="); stats.AppendLine($"Session ended: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"); stats.AppendLine($"Log file: {_logFilePath}"); stats.AppendLine($"Total memory: {GC.GetTotalMemory(false)} bytes"); stats.AppendLine("=========================="); WriteLog("STATS", stats.ToString()); } } }