From 58b9064fc5b020b8cc1193d43d4d39714c182e9a Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 30 May 2016 12:36:07 +1000 Subject: [PATCH] Fixes #731 - evented SelfLog --- src/Serilog/Debugging/SelfLog.cs | 63 ++++++++++++++------ test/Serilog.Tests/Debugging/SelfLogTests.cs | 35 +++++++++++ 2 files changed, 80 insertions(+), 18 deletions(-) create mode 100644 test/Serilog.Tests/Debugging/SelfLogTests.cs diff --git a/src/Serilog/Debugging/SelfLog.cs b/src/Serilog/Debugging/SelfLog.cs index 8580b5d16..424ff0916 100644 --- a/src/Serilog/Debugging/SelfLog.cs +++ b/src/Serilog/Debugging/SelfLog.cs @@ -23,7 +23,7 @@ namespace Serilog.Debugging /// public static class SelfLog { - static readonly Action _output; + static Action _output; /// /// The output mechanism for self-log events. @@ -32,28 +32,53 @@ public static class SelfLog /// SelfLog.Out = Console.Error; /// // ReSharper disable once MemberCanBePrivate.Global, UnusedAutoPropertyAccessor.Global - [Obsolete("Use SetOutput() instead")] + [Obsolete("Use SelfLog.Enable(value) and SelfLog.Disable() instead")] public static TextWriter Out { set { - if (value == null) - { - SetOutput(null); - } + if (value != null) + Enable(value); else - { - SetOutput(m => - { - value.WriteLine(DateTime.UtcNow.ToString("o") + " " + m); - value.Flush(); - }); - } + Disable(); } } - public static void SetOutput(Action output) + /// + /// Set the output mechanism for self-log events. + /// + /// A synchronized to which + /// self-log events will be written. + // ReSharper disable once MemberCanBePrivate.Global + public static void Enable(TextWriter output) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + Enable(m => + { + output.WriteLine(m); + output.Flush(); + }); + } + + /// + /// Set the output mechanism for self-log events. + /// + /// An action to invoke with self-log messages. + /// // ReSharper disable once MemberCanBePrivate.Global + public static void Enable(Action output) { + if (output == null) throw new ArgumentNullException(nameof(output)); + _output = output; + } + + /// + /// Clear the output mechanism and disable self-log events. + /// + /// // ReSharper disable once MemberCanBePrivate.Global + public static void Disable() + { + _output = null; } /// @@ -63,13 +88,15 @@ public static void SetOutput(Action output) /// First argument, if supplied. /// Second argument, if supplied. /// Third argument, if supplied. + /// + /// The name is historical; because this is used from third-party sink packages, removing the "Line" + /// suffix as would seem sensible isn't worth the breakage. + /// public static void WriteLine(string format, object arg0 = null, object arg1 = null, object arg2 = null) { var o = _output; - if (o != null) - { - o(string.Format(format, arg0, arg1, arg2)); - } + + o?.Invoke(string.Format(DateTime.UtcNow.ToString("o") + " " + format, arg0, arg1, arg2)); } } } diff --git a/test/Serilog.Tests/Debugging/SelfLogTests.cs b/test/Serilog.Tests/Debugging/SelfLogTests.cs new file mode 100644 index 000000000..08722065b --- /dev/null +++ b/test/Serilog.Tests/Debugging/SelfLogTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Serilog.Debugging; +using Xunit; + +namespace Serilog.Tests.Debugging +{ + public class SelfLogTests + { + [ThreadStatic] + static List Messages; + + [Fact] + public void MessagesAreWrittenWhenOutputIsSet() + { + Messages = new List(); + SelfLog.Enable(m => + { + Messages = Messages ?? new List(); + Messages.Add(m); + }); + + SelfLog.WriteLine("Hello {0} {1} {2}", 0, 1, 2); + Assert.True(Messages.Any(m => m.EndsWith("Hello 0 1 2"))); + + // Better to do this here than in another test, since at this point + // we've confirmed there's actually something to disable. + var count = Messages.Count; + SelfLog.Disable(); + SelfLog.WriteLine("Unwritten"); + Assert.Equal(Messages.Count, count); + } + } +}