From d8a8a101a1be57fdda73b6fb8468cf12f6e1a6f5 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 11 Jan 2019 20:38:42 -0600 Subject: [PATCH] Improved logger printer inheritance --- IPA.Loader/Logging/StandardLogger.cs | 47 +++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/IPA.Loader/Logging/StandardLogger.cs b/IPA.Loader/Logging/StandardLogger.cs index 0b297782..6ae7b2b5 100644 --- a/IPA.Loader/Logging/StandardLogger.cs +++ b/IPA.Loader/Logging/StandardLogger.cs @@ -4,16 +4,24 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; namespace IPA.Logging { /// - /// The default implementation. + /// The default (and standard) implementation. /// + /// + /// uses a multi-threaded approach to logging. All actual I/O is done on another thread, + /// where all messaged are guaranteed to be logged in the order they appeared. It is up to the printers to format them. + /// + /// This logger supports child loggers. Use to safely get a child. + /// The modification of printers on a parent are reflected down the chain. + /// public class StandardLogger : Logger { - private static readonly IReadOnlyList defaultPrinters = new List() + private static readonly List defaultPrinters = new List() { new ColoredConsolePrinter() { @@ -43,6 +51,11 @@ namespace IPA.Logging new GlobalLogFilePrinter() }; + internal static void AddDefaultPrinter(LogPrinter printer) + { + defaultPrinters.Add(printer); + } + private readonly string logName; private static bool showSourceClass; @@ -50,7 +63,8 @@ namespace IPA.Logging /// All levels defined by this filter will be sent to loggers. All others will be ignored. /// public static LogLevel PrintFilter { get; set; } = LogLevel.All; - private readonly List printers = new List(defaultPrinters); + private readonly List printers = new List(); + private readonly StandardLogger parent; private readonly Dictionary children = new Dictionary(); @@ -60,12 +74,13 @@ namespace IPA.Logging PrintFilter = cfg.Debug.ShowDebug ? LogLevel.All : LogLevel.InfoUp; } - private StandardLogger(string mainName, string subName, params LogPrinter[] inherited) + private StandardLogger(StandardLogger parent, string subName) { - logName = $"{mainName}/{subName}"; - printers = new List(inherited) + logName = $"{parent.logName}/{subName}"; + this.parent = parent; + printers = new List() { - new PluginSubLogPrinter(mainName, subName) + new PluginSubLogPrinter(parent.logName, subName) }; if (logThread == null || !logThread.IsAlive) @@ -91,7 +106,7 @@ namespace IPA.Logging { if (!children.TryGetValue(name, out var child)) { - child = new StandardLogger(logName, name, printers.ToArray()); + child = new StandardLogger(this, name); children.Add(name, child); } @@ -157,8 +172,18 @@ namespace IPA.Logging private static void LogThread() { var started = new HashSet(); - while (logQueue.TryTake(out var msg, Timeout.Infinite)) { - foreach (var printer in msg.Logger.printers) + while (logQueue.TryTake(out var msg, Timeout.Infinite)) + { + var logger = msg.Logger; + IEnumerable printers = logger.printers; + do + { + logger = logger.parent; + if (logger != null) + printers = printers.Concat(logger.printers); + } while (logger != null); + + foreach (var printer in printers.Concat(defaultPrinters)) { try { @@ -210,7 +235,7 @@ namespace IPA.Logging public static class LoggerExtensions { /// - /// Gets a child logger, if supported. + /// Gets a child logger, if supported. Currently the only defined and supported logger is , and most plugins will only ever receive this anyway. /// /// the parent /// the name of the child