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.

150 lines
4.4 KiB

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