You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
5.6 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Concurrent;
  4. using System.IO;
  5. using System.Runtime.Remoting.Messaging;
  6. using System.Threading;
  7. using IllusionPlugin;
  8. namespace IllusionPlugin {
  9. public class Logger {
  10. private static BlockingCollection<logMessage> _logQueue;
  11. private static Thread _watcherThread;
  12. private static bool _threadRunning;
  13. private readonly FileInfo _logFile;
  14. private string ModName;
  15. struct logMessage {
  16. public static readonly string logFormat = "[{3} @ {2:HH:mm:ss} | {1}] {0}";
  17. public WarningLevel WarningLevel;
  18. public DateTime Time;
  19. public Logger Log;
  20. public string Message;
  21. public logMessage(string msg, Logger log, DateTime time, WarningLevel wl) {
  22. Message = msg;
  23. WarningLevel = wl;
  24. Log = log;
  25. Time = time;
  26. }
  27. }
  28. enum WarningLevel {
  29. Log, Error, Exception, Warning
  30. }
  31. static void SetupStatic()
  32. {
  33. if (_logQueue == null)
  34. _logQueue = new BlockingCollection<logMessage>();
  35. if (_watcherThread == null || !_watcherThread.IsAlive)
  36. {
  37. _watcherThread = new Thread(QueueWatcher); // { IsBackground = true };
  38. _threadRunning = true;
  39. _watcherThread.Start();
  40. }
  41. }
  42. public Logger(string modName = "Default") {
  43. SetupStatic();
  44. _logFile = GetPath(modName);
  45. _logFile.Create().Close();
  46. }
  47. public Logger(IBeatSaberPlugin plugin)
  48. {
  49. SetupStatic();
  50. _logFile = GetPath(plugin);
  51. _logFile.Create().Close();
  52. }
  53. public void Log(string msg) {
  54. if(!_watcherThread.IsAlive) throw new Exception("Logger is Closed!");
  55. //_logQueue.Add(new logMessage($"[LOG @ {DateTime.Now:HH:mm:ss} | {ModName}] {msg}", WarningLevel.Log));
  56. _logQueue.Add(new logMessage(msg, this, DateTime.Now, WarningLevel.Log));
  57. }
  58. public void Error(string msg) {
  59. if(!_watcherThread.IsAlive) throw new Exception("Logger is Closed!");
  60. //_logQueue.Add(new logMessage($"[ERROR @ {DateTime.Now:HH:mm:ss} | {ModName}] {msg}", WarningLevel.Error));
  61. _logQueue.Add(new logMessage(msg, this, DateTime.Now, WarningLevel.Error));
  62. }
  63. public void Exception(string msg) {
  64. if(!_watcherThread.IsAlive) throw new Exception("Logger is Closed!");
  65. //_logQueue.Add(new logMessage($"[EXCEPTION @ {DateTime.Now:HH:mm:ss} | {ModName}] {msg}", WarningLevel.Exception));
  66. _logQueue.Add(new logMessage(msg, this, DateTime.Now, WarningLevel.Exception));
  67. }
  68. public void Warning(string msg) {
  69. if(!_watcherThread.IsAlive) throw new Exception("Logger is Closed!");
  70. //_logQueue.Add(new logMessage($"[WARNING @ {DateTime.Now:HH:mm:ss} | {ModName}] {msg}", WarningLevel.Warning));
  71. _logQueue.Add(new logMessage(msg, this, DateTime.Now, WarningLevel.Warning));
  72. }
  73. static void QueueWatcher() {
  74. //StreamWriter wstream = null;
  75. Dictionary<string, StreamWriter> wstreams = new Dictionary<string, StreamWriter>();
  76. while (_threadRunning && _logQueue.TryTake(out logMessage message, Timeout.Infinite))
  77. {
  78. string msg = string.Format(logMessage.logFormat, message.Message, message.Log.ModName, message.Time, message.WarningLevel);
  79. wstreams[message.Log.ModName] = message.Log._logFile.AppendText();
  80. wstreams[message.Log.ModName].WriteLine(msg);
  81. Console.ForegroundColor = GetConsoleColour(message.WarningLevel);
  82. Console.WriteLine(message.Message);
  83. Console.ResetColor();
  84. if (_logQueue.Count == 0)
  85. { // no more messages
  86. foreach (var kvp in wstreams)
  87. {
  88. if (kvp.Value == null) continue;
  89. kvp.Value.Dispose();
  90. wstreams[kvp.Key] = null;
  91. }
  92. }
  93. }
  94. foreach (var kvp in wstreams)
  95. {
  96. if (kvp.Value == null) continue;
  97. kvp.Value.Dispose();
  98. }
  99. }
  100. public static void Stop() {
  101. _threadRunning = false;
  102. _watcherThread.Join();
  103. }
  104. static ConsoleColor GetConsoleColour(WarningLevel level) {
  105. switch (level) {
  106. case WarningLevel.Log:
  107. return ConsoleColor.Green;
  108. case WarningLevel.Error:
  109. return ConsoleColor.Yellow;
  110. case WarningLevel.Exception:
  111. return ConsoleColor.Red;
  112. case WarningLevel.Warning:
  113. return ConsoleColor.Blue;
  114. default:
  115. return ConsoleColor.Gray;
  116. }
  117. }
  118. FileInfo GetPath(IBeatSaberPlugin plugin) => GetPath(plugin.Name);
  119. FileInfo GetPath(string modName) {
  120. ModName = modName;
  121. var logsDir = new DirectoryInfo($"./Logs/{modName}/{DateTime.Now:dd-MM-yy}");
  122. logsDir.Create();
  123. return new FileInfo($"{logsDir.FullName}/{logsDir.GetFiles().Length}.txt");
  124. }
  125. }
  126. public static class LoggerExtensions {
  127. public static Logger GetLogger(this IBeatSaberPlugin plugin) {
  128. return new Logger(plugin);
  129. }
  130. }
  131. }