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.

157 lines
4.6 KiB

  1. using IllusionInjector.Logging.Printers;
  2. using IllusionPlugin;
  3. using IllusionPlugin.Logging;
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using LoggerBase = IllusionPlugin.Logging.Logger;
  12. namespace IllusionInjector.Logging
  13. {
  14. internal static class Logger
  15. {
  16. private static LoggerBase _log;
  17. internal static LoggerBase log
  18. {
  19. get
  20. {
  21. if (_log == null)
  22. _log = new StandardLogger("IPA");
  23. return _log;
  24. }
  25. }
  26. }
  27. public class StandardLogger : LoggerBase
  28. {
  29. private static readonly IReadOnlyList<LogPrinter> defaultPrinters = new List<LogPrinter>()
  30. {
  31. new ColoredConsolePrinter()
  32. {
  33. Filter = LogLevel.DebugOnly,
  34. Color = ConsoleColor.Green,
  35. },
  36. new ColoredConsolePrinter()
  37. {
  38. Filter = LogLevel.InfoOnly,
  39. Color = ConsoleColor.White,
  40. },
  41. new ColoredConsolePrinter()
  42. {
  43. Filter = LogLevel.WarningOnly,
  44. Color = ConsoleColor.Yellow,
  45. },
  46. new ColoredConsolePrinter()
  47. {
  48. Filter = LogLevel.ErrorOnly,
  49. Color = ConsoleColor.Red,
  50. },
  51. new ColoredConsolePrinter()
  52. {
  53. Filter = LogLevel.CriticalOnly,
  54. Color = ConsoleColor.Magenta,
  55. },
  56. new GlobalLogFilePrinter()
  57. };
  58. private string logName;
  59. private static LogLevel showFilter = LogLevel.InfoUp;
  60. public static LogLevel PrintFilter { get => showFilter; set => showFilter = value; }
  61. private List<LogPrinter> printers = new List<LogPrinter>(defaultPrinters);
  62. static StandardLogger()
  63. {
  64. if (ModPrefs.GetBool("IPA", "PrintDebug", false, true))
  65. showFilter = LogLevel.All;
  66. }
  67. internal StandardLogger(string name)
  68. {
  69. logName = name;
  70. printers.Add(new PluginLogFilePrinter(name));
  71. if (_logThread == null || !_logThread.IsAlive)
  72. {
  73. _logThread = new Thread(LogThread);
  74. _logThread.Start();
  75. }
  76. }
  77. public override void Log(Level level, string message)
  78. {
  79. _logQueue.Add(new LogMessage
  80. {
  81. level = level,
  82. message = message,
  83. logger = this,
  84. time = DateTime.Now
  85. });
  86. }
  87. internal struct LogMessage
  88. {
  89. public Level level;
  90. public StandardLogger logger;
  91. public string message;
  92. public DateTime time;
  93. }
  94. private static BlockingCollection<LogMessage> _logQueue = new BlockingCollection<LogMessage>();
  95. private static Thread _logThread;
  96. private static void LogThread()
  97. {
  98. HashSet<LogPrinter> started = new HashSet<LogPrinter>();
  99. while (_logQueue.TryTake(out LogMessage msg, Timeout.Infinite)) {
  100. foreach (var printer in msg.logger.printers)
  101. {
  102. try
  103. {
  104. if (((byte)msg.level & (byte)printer.Filter) != 0)
  105. {
  106. if (!started.Contains(printer))
  107. {
  108. printer.StartPrint();
  109. started.Add(printer);
  110. }
  111. printer.Print(msg.level, msg.time, msg.logger.logName, msg.message);
  112. }
  113. }
  114. catch (Exception e)
  115. {
  116. Console.WriteLine($"printer errored {e}");
  117. }
  118. }
  119. if (_logQueue.Count == 0)
  120. {
  121. foreach (var printer in started)
  122. {
  123. try
  124. {
  125. printer.EndPrint();
  126. }
  127. catch (Exception e)
  128. {
  129. Console.WriteLine($"printer errored {e}");
  130. }
  131. }
  132. started.Clear();
  133. }
  134. }
  135. }
  136. public static void StopLogThread()
  137. {
  138. _logQueue.CompleteAdding();
  139. _logThread.Join();
  140. }
  141. }
  142. }