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.

153 lines
4.7 KiB

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