diff --git a/src/Serilog/Debugging/SelfLog.cs b/src/Serilog/Debugging/SelfLog.cs index 86b7d775e..c9423519a 100644 --- a/src/Serilog/Debugging/SelfLog.cs +++ b/src/Serilog/Debugging/SelfLog.cs @@ -23,14 +23,63 @@ namespace Serilog.Debugging /// public static class SelfLog { + static Action _output; + /// - /// The output mechanism for self-log events. + /// The output mechanism for self-log messages. /// /// /// SelfLog.Out = Console.Error; /// // ReSharper disable once MemberCanBePrivate.Global, UnusedAutoPropertyAccessor.Global - public static TextWriter Out { get; set; } + [Obsolete("Use SelfLog.Enable(value) and SelfLog.Disable() instead")] + public static TextWriter Out + { + set + { + if (value != null) + Enable(value); + else + Disable(); + } + } + + /// + /// Set the output mechanism for self-log messages. + /// + /// A synchronized to which + /// self-log messages 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 messages. + /// + /// 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; + } /// /// Write a message to the self-log. @@ -39,14 +88,15 @@ public static class SelfLog /// 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 = Out; - if (o != null) - { - o.WriteLine(DateTime.Now.ToString("s") + " " + format, arg0, arg1, arg2); - o.Flush(); - } + var o = _output; + + 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); + } + } +}