#pragma warning disable CA2211 using System.Runtime.CompilerServices; namespace DaggerFramework.Utils { public class Logger { public static Action? OnLog; public static string LogPath { get; set; } = "Logs/"; /// /// Maximum amount of log files in a log folder. If it reaches the limit, all logs will be written to dagger-latest.log instead of creating a new one. /// public static int MaxLogFiles { get; set; } = 5; /// /// Specifies the logging level. In release builds, the log level is Error. In debug, the log level is Echo. /// public static LogLevel LogLevel = LogLevel.Error; /// /// Specifies if the logger should write to file. /// public static bool WriteToFile = true; public Logger(string className) { _className = className; if (WriteToFile && !_logCreated) { var dirInfo = Directory.CreateDirectory(LogPath); var files = dirInfo.GetFiles(); string logName = $"dagger-{DateFormat}-{TimeFormat}.log".Replace(':', '.'); if (files.Length >= MaxLogFiles) { logName = "dagger-latest.log"; } var path = Path.Combine(LogPath, logName); if (File.Exists(path)) { File.Delete(path); } _fileStream = File.Create(path); _fileWriter = new StreamWriter(_fileStream); _logCreated = true; } #if DEBUG LogLevel = LogLevel.Echo; #endif } public void Echo(string what) { string message = string.Format(EchoFormat, TimeFormat, what); LogFile(message); LogConsole(what, LogLevel.Echo); OnLog?.Invoke(what, LogLevel.Echo); } public void Info(string what, [CallerMemberName] string method = "") { LogLevel logType = LogLevel.Info; string message = string.Format(LogFormat, TimeFormat, logType.ToString(), _className, method, what); LogFile(message); LogConsole(message, logType); OnLog?.Invoke(message, logType); } public void Warn(string what, [CallerMemberName] string method = "") { LogLevel logType = LogLevel.Warn; string message = string.Format(LogFormat, TimeFormat, logType.ToString(), _className, method, what); LogFile(message); LogConsole(message, logType); OnLog?.Invoke(message, logType); } public void Error(string what, [CallerMemberName] string method = "") { LogLevel logType = LogLevel.Error; string message = string.Format(LogFormat, TimeFormat, logType.ToString(), _className, method, what); LogFile(message); LogConsole(message, logType); OnLog?.Invoke(message, logType); } private static string TimeFormat => $"{DateTime.Now:HH:mm:ffff}"; private static string DateFormat => $"{DateTime.Now:d:M:yyyy:}"; private static string LogFormat => "({0}) [{1}/{2}/{3}] {4}"; private static string EchoFormat => "({0}) {1}"; private static void LogConsole(string what, LogLevel logType) { if (LogLevel < logType) return; Console.ForegroundColor = ConsoleColorForLog(logType); Console.WriteLine(what); Console.ForegroundColor = ConsoleColor.White; } private static ConsoleColor ConsoleColorForLog(LogLevel logType) { ConsoleColor color = ConsoleColor.White; switch (logType) { case LogLevel.Info: color = ConsoleColor.Cyan; break; case LogLevel.Warn: color = ConsoleColor.Yellow; break; case LogLevel.Error: color = ConsoleColor.Red; break; } return color; } private void LogFile(string message) { if (!WriteToFile || _fileWriter is null) return; _fileWriter.WriteLine(message); _fileWriter.Flush(); } private readonly string _className; private static bool _logCreated; private static FileStream? _fileStream; private static StreamWriter? _fileWriter; } public enum LogLevel { Error, Warn, Info, Echo, } }