From e6320b27fae339c2c49f290c45ca3c90c13982ce Mon Sep 17 00:00:00 2001 From: 3047256 <154562391+3047256@users.noreply.github.com> Date: Sun, 31 Dec 2023 01:06:28 +0000 Subject: [PATCH 1/3] Log the calling class, and values, and value changes --- osu.Framework/Logging/Logger.cs | 101 ++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/osu.Framework/Logging/Logger.cs b/osu.Framework/Logging/Logger.cs index d35f536d2a..388152a0ee 100644 --- a/osu.Framework/Logging/Logger.cs +++ b/osu.Framework/Logging/Logger.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -155,9 +156,11 @@ public static string ApplyFilters(string message) /// The description of the error that should be logged with the exception. /// The logging target (file). /// Whether the inner exceptions of the given exception should be logged recursively. - public static void Error(Exception e, string description, LoggingTarget target = LoggingTarget.Runtime, bool recursive = false) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void Error(Exception e, string description, LoggingTarget target = LoggingTarget.Runtime, bool recursive = false, Dictionary valueChanges = null, Dictionary values = null) { - error(e, description, target, null, recursive); + error(e, description, target, null, recursive, valueChanges: valueChanges, values: values); } /// @@ -167,17 +170,29 @@ public static void Error(Exception e, string description, LoggingTarget target = /// The description of the error that should be logged with the exception. /// The logger name (file). /// Whether the inner exceptions of the given exception should be logged recursively. - public static void Error(Exception e, string description, string name, bool recursive = false) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void Error(Exception e, string description, string name, bool recursive = false, Dictionary valueChanges = null, Dictionary values = null) { - error(e, description, null, name, recursive); + error(e, description, null, name, recursive, valueChanges: valueChanges, values: values); } - private static void error(Exception e, string description, LoggingTarget? target, string name, bool recursive) + /// + /// Logs the given exception with the given description to the logger with the given name. + /// + /// The exception that should be logged. + /// The description of the error that should be logged with the exception. + /// The logging target (file). + /// The logger name (file). + /// Whether the inner exceptions of the given exception should be logged recursively. + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + private static void error(Exception e, string description, LoggingTarget? target, string name, bool recursive, Dictionary valueChanges = null, Dictionary values = null) { - log($@"{description}", target, name, LogLevel.Error, e); + log($@"{description}", target, name, LogLevel.Error, e, valueChanges: valueChanges, values: values); if (recursive && e.InnerException != null) - error(e.InnerException, $"{description} (inner)", target, name, true); + error(e.InnerException, $"{description} (inner)", target, name, true, valueChanges: valueChanges, values: values); } /// @@ -187,9 +202,11 @@ private static void error(Exception e, string description, LoggingTarget? target /// The logging target (file). /// The verbosity level. /// Whether the message should be sent to listeners of and . True by default. - public static void Log(string message, LoggingTarget target = LoggingTarget.Runtime, LogLevel level = LogLevel.Verbose, bool outputToListeners = true) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void Log(string message, LoggingTarget target = LoggingTarget.Runtime, LogLevel level = LogLevel.Verbose, bool outputToListeners = true, Dictionary valueChanges = null, Dictionary values = null) { - log(message, target, null, level, outputToListeners: outputToListeners); + log(message, target, null, level, outputToListeners: outputToListeners, valueChanges: valueChanges, values: values); } /// @@ -199,19 +216,32 @@ public static void Log(string message, LoggingTarget target = LoggingTarget.Runt /// The logger name (file). /// The verbosity level. /// Whether the message should be sent to listeners of and . True by default. - public static void Log(string message, string name, LogLevel level = LogLevel.Verbose, bool outputToListeners = true) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void Log(string message, string name, LogLevel level = LogLevel.Verbose, bool outputToListeners = true, Dictionary valueChanges = null, Dictionary values = null) { - log(message, null, name, level, outputToListeners: outputToListeners); + log(message, null, name, level, outputToListeners: outputToListeners, valueChanges: valueChanges, values: values); } - private static void log(string message, LoggingTarget? target, string loggerName, LogLevel level, Exception exception = null, bool outputToListeners = true) + /// + /// Log an arbitrary string to the specified logging target. + /// + /// The message to log. Can include newline (\n) characters to split into multiple lines. + /// The logging target (file). + /// The logger name (file). + /// The verbosity level. + /// An optional related exception. + /// Whether the message should be sent to listeners of and . True by default. + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + private static void log(string message, LoggingTarget? target, string loggerName, LogLevel level, Exception exception = null, bool outputToListeners = true, Dictionary valueChanges = null, Dictionary values = null) { try { if (target.HasValue) - GetLogger(target.Value).Add(message, level, exception, outputToListeners); + GetLogger(target.Value).Add(message, level, exception, outputToListeners, valueChanges, values); else - GetLogger(loggerName).Add(message, level, exception, outputToListeners); + GetLogger(loggerName).Add(message, level, exception, outputToListeners, valueChanges, values); } catch { @@ -224,12 +254,14 @@ private static void log(string message, LoggingTarget? target, string loggerName /// The message to log. Can include newline (\n) characters to split into multiple lines. /// The logging target (file). /// The verbosity level. - public static void LogPrint(string message, LoggingTarget target = LoggingTarget.Runtime, LogLevel level = LogLevel.Verbose) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void LogPrint(string message, LoggingTarget target = LoggingTarget.Runtime, LogLevel level = LogLevel.Verbose, Dictionary valueChanges = null, Dictionary values = null) { if (Enabled && DebugUtils.IsDebugBuild) System.Diagnostics.Debug.Print(message); - Log(message, target, level); + Log(message, target, level, valueChanges: valueChanges, values: values); } /// @@ -238,12 +270,14 @@ public static void LogPrint(string message, LoggingTarget target = LoggingTarget /// The message to log. Can include newline (\n) characters to split into multiple lines. /// The logger name (file). /// The verbosity level. - public static void LogPrint(string message, string name, LogLevel level = LogLevel.Verbose) + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public static void LogPrint(string message, string name, LogLevel level = LogLevel.Verbose, Dictionary valueChanges = null, Dictionary values = null) { if (Enabled && DebugUtils.IsDebugBuild) System.Diagnostics.Debug.Print(message); - Log(message, name, level); + Log(message, name, level, valueChanges: valueChanges, values: values); } /// @@ -275,12 +309,14 @@ public static Logger GetLogger(string name) /// Logs a new message with the and will only be logged if your project is built in the Debug configuration. Please note that the default setting for is so unless you increase the to messages printed with this method will not appear in the output. /// /// The message that should be logged. - public void Debug(string message = @"") + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public void Debug(string message = @"", Dictionary valueChanges = null, Dictionary values = null) { if (!DebugUtils.IsDebugBuild) return; - Add(message, LogLevel.Debug); + Add(message, LogLevel.Debug, valueChanges: valueChanges, values: values); } /// @@ -290,14 +326,16 @@ public void Debug(string message = @"") /// The verbosity level. /// An optional related exception. /// Whether the message should be sent to listeners of and . True by default. - public void Add(string message = @"", LogLevel level = LogLevel.Verbose, Exception exception = null, bool outputToListeners = true) => - add(message, level, exception, outputToListeners && OutputToListeners); + /// Value changes to be indicated in the logs + /// Value to be shown in the logs + public void Add(string message = @"", LogLevel level = LogLevel.Verbose, Exception exception = null, bool outputToListeners = true, Dictionary valueChanges = null, Dictionary values = null) => + add(message, level, exception, outputToListeners && OutputToListeners, valueChanges, values); private readonly RollingTime debugOutputRollingTime = new RollingTime(50, 10000); private readonly Queue pendingFileOutput = new Queue(); - private void add(string message = @"", LogLevel level = LogLevel.Verbose, Exception exception = null, bool outputToListeners = true) + private void add(string message = @"", LogLevel level = LogLevel.Verbose, Exception exception = null, bool outputToListeners = true, Dictionary valueChanges = null, Dictionary values = null) { if (!Enabled || level < Level) return; @@ -308,6 +346,23 @@ private void add(string message = @"", LogLevel level = LogLevel.Verbose, Except message = ApplyFilters(message); + Type callingClass = new StackTrace().GetFrames().Where(sf => sf.HasMethod()).Select(sf => sf.GetMethod()).FirstOrDefault(m => m != null && m.DeclaringType != typeof(Logger))?.DeclaringType; + + if (callingClass != null) + { + message = $"{callingClass.Name}, {message}"; + } + + if (valueChanges != null) + { + message = $"{message}, {string.Join(" ", valueChanges.Select(kvp => $"from: \"{kvp.Key}\" to: \"{kvp.Value}\""))}"; + } + + if (values != null) + { + message = $"{message}, {string.Join(" ", values.Select(kvp => $"{kvp.Key}:{kvp.Value}"))}"; + } + string logOutput = message; if (exception != null) From a4860227e586dc2ba0d9ce0854f2a941eaece994 Mon Sep 17 00:00:00 2001 From: 3047256 <154562391+3047256@users.noreply.github.com> Date: Sun, 31 Dec 2023 01:07:02 +0000 Subject: [PATCH 2/3] Add tests for the new logs --- osu.Framework.Tests/IO/TestLogging.cs | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/osu.Framework.Tests/IO/TestLogging.cs b/osu.Framework.Tests/IO/TestLogging.cs index 090ffcf9f5..7dfce940dd 100644 --- a/osu.Framework.Tests/IO/TestLogging.cs +++ b/osu.Framework.Tests/IO/TestLogging.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using NUnit.Framework; @@ -79,6 +80,71 @@ void logTest(LogEntry entry) Logger.NewEntry -= logTest; } + [Test] + public void TestClassNameLogging() + { + void logTest(LogEntry entry) + { + Assert.That(entry.Message, Does.StartWith(nameof(TestLogging))); + } + + using (var storage = new TemporaryNativeStorage(nameof(TestExceptionLogging))) + { + Logger.Storage = storage; + Logger.Enabled = true; + + Logger.NewEntry += logTest; + Logger.Error(new TestException(), "message"); + Logger.Error(new TestException(), "message", "test"); + Logger.Log("message"); + Logger.Log("message", "test"); + Logger.LogPrint("message"); + Logger.LogPrint("message", "test"); + Logger.NewEntry -= logTest; + + Logger.Enabled = false; + Logger.Flush(); + } + } + + [Test] + public void TestValueLogging() + { + Dictionary valueChanges = new Dictionary() { [""] = "osu!", ["EnteringMode"] = "TopLevel" }; + Dictionary values = new Dictionary() { ["beatmap"] = 186, ["ruleset"] = 0, }; + + void logTest(LogEntry entry) + { + foreach (var valueChange in valueChanges) + { + Assert.That(entry.Message, Contains.Substring($"from: \"{valueChange.Key}\" to: \"{valueChange.Value}\"")); + } + + foreach (var value in values) + { + Assert.That(entry.Message, Contains.Substring($"{value.Key}:{value.Value}")); + } + } + + using (var storage = new TemporaryNativeStorage(nameof(TestExceptionLogging))) + { + Logger.Storage = storage; + Logger.Enabled = true; + + Logger.NewEntry += logTest; + Logger.Error(new TestException(), "message", valueChanges: valueChanges, values: values); + Logger.Error(new TestException(), "message", "test", valueChanges: valueChanges, values: values); + Logger.Log("message", valueChanges: valueChanges, values: values); + Logger.Log("message", "test", valueChanges: valueChanges, values: values); + Logger.LogPrint("message", valueChanges: valueChanges, values: values); + Logger.LogPrint("message", "test", valueChanges: valueChanges, values: values); + Logger.NewEntry -= logTest; + + Logger.Enabled = false; + Logger.Flush(); + } + } + [Test] public void TestUnhandledIgnoredException() { From 8a2da3b3b5b4281ed09afdd1592fa3ee79c4855d Mon Sep 17 00:00:00 2001 From: 3047256 <154562391+3047256@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:26:55 +0000 Subject: [PATCH 3/3] Include quotes for values --- osu.Framework.Tests/IO/TestLogging.cs | 2 +- osu.Framework/Logging/Logger.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Framework.Tests/IO/TestLogging.cs b/osu.Framework.Tests/IO/TestLogging.cs index 7dfce940dd..316fad7588 100644 --- a/osu.Framework.Tests/IO/TestLogging.cs +++ b/osu.Framework.Tests/IO/TestLogging.cs @@ -122,7 +122,7 @@ void logTest(LogEntry entry) foreach (var value in values) { - Assert.That(entry.Message, Contains.Substring($"{value.Key}:{value.Value}")); + Assert.That(entry.Message, Contains.Substring($"{value.Key}:\"{value.Value}\"")); } } diff --git a/osu.Framework/Logging/Logger.cs b/osu.Framework/Logging/Logger.cs index 388152a0ee..9eb52ed97b 100644 --- a/osu.Framework/Logging/Logger.cs +++ b/osu.Framework/Logging/Logger.cs @@ -360,7 +360,7 @@ private void add(string message = @"", LogLevel level = LogLevel.Verbose, Except if (values != null) { - message = $"{message}, {string.Join(" ", values.Select(kvp => $"{kvp.Key}:{kvp.Value}"))}"; + message = $"{message}, {string.Join(" ", values.Select(kvp => $"{kvp.Key}:\"{kvp.Value}\""))}"; } string logOutput = message;