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.

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