diff --git a/VolumeControl.Log/AsyncLogWriter.cs b/VolumeControl.Log/AsyncLogWriter.cs index c84f53f8b..c08560f5a 100644 --- a/VolumeControl.Log/AsyncLogWriter.cs +++ b/VolumeControl.Log/AsyncLogWriter.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Collections.Concurrent; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Text; @@ -132,11 +133,6 @@ public bool IsAsyncEnabled #region (Private) WriteLogMessage private void WriteLogMessage(LogMessage message) { - if (!FilterEventType(message.EventType)) - { // event type is not enabled; don't show it - return; - } - lock (Endpoint) { if (!Endpoint.IsWritingEnabled) return; @@ -202,6 +198,8 @@ private static string InsertLinePrefixes(string s) } private static string? ObjectToString(object lineObject, bool isRecursed = false) { + lineObject.GetType(); + if (lineObject is Exception ex) { // expand exception return ExceptionMessageHelper.MakeExceptionMessage(ex, BlankLineHeader, Environment.NewLine, 2, ExceptionMessageHelper.MessageParts.All); @@ -242,11 +240,7 @@ internal static string Indent(int maxLength, int usedLength) #endregion (Private/Internal) #region FilterEventType - /// - /// Checks if messages with the specified are shown in the log. - /// - /// An to check. - /// when the is shown; otherwise . + /// public bool FilterEventType(EventType eventType) { return eventType == EventType.NONE @@ -281,16 +275,12 @@ public void ResetEndpoint(string firstLine) #endregion ResetEndpoint #region LogMessage - /// - /// Writes the specified to the log. - /// - /// - /// When IsAsyncEnabled is , the message is written asynchronously; - /// otherwise, the message is written synchronously and the caller will be blocked until the message has been written. - /// - /// The message to write to the log. - public void LogMessage(LogMessage logMessage) + /// + public bool LogMessage(LogMessage logMessage) { + if (!FilterEventType(logMessage.EventType)) + return false; + if (IsAsyncEnabled) { Enqueue(() => WriteLogMessage(logMessage)); @@ -299,53 +289,43 @@ public void LogMessage(LogMessage logMessage) { WriteLogMessage(logMessage); } + return true; } #endregion LogMessage #region EventType Writer Methods - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Trace(params object?[] lines) => LogMessage(new(EventType.TRACE, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Debug(params object?[] lines) => LogMessage(new(EventType.DEBUG, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Info(params object?[] lines) => LogMessage(new(EventType.INFO, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Warning(params object?[] lines) => LogMessage(new(EventType.WARN, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Error(params object?[] lines) => LogMessage(new(EventType.ERROR, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Fatal(params object?[] lines) => LogMessage(new(EventType.FATAL, lines)); - /// - /// Queues writing a message with the specified . - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Critical(params object?[] lines) => LogMessage(new(EventType.CRITICAL, lines)); - /// - /// Queues writing a message with the specified . - /// - /// - /// This produces a message with no event type header, but a timestamp is still shown. - /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - public void Blank(params object?[] lines) => LogMessage(new(EventType.NONE, lines)); + /// + public bool Trace(params object?[] lines) => LogMessage(new(EventType.TRACE, lines)); + /// + public bool Trace(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.TRACE)); + /// + public bool Debug(params object?[] lines) => LogMessage(new(EventType.DEBUG, lines)); + /// + public bool Debug(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.DEBUG)); + /// + public bool Info(params object?[] lines) => LogMessage(new(EventType.INFO, lines)); + /// + public bool Info(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.INFO)); + /// + public bool Warning(params object?[] lines) => LogMessage(new(EventType.WARN, lines)); + /// + public bool Warning(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.WARN)); + /// + public bool Error(params object?[] lines) => LogMessage(new(EventType.ERROR, lines)); + /// + public bool Error(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.ERROR)); + /// + public bool Fatal(params object?[] lines) => LogMessage(new(EventType.FATAL, lines)); + /// + public bool Fatal(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.FATAL)); + /// + public bool Critical(params object?[] lines) => LogMessage(new(EventType.CRITICAL, lines)); + /// + public bool Critical(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.CRITICAL)); + /// + public bool Blank(params object?[] lines) => LogMessage(new(EventType.NONE, lines)); + /// + public bool Blank(LogMessage logMessage) => LogMessage(logMessage.SetEventType(EventType.NONE)); #endregion EventType Writer Methods #region DisableAsyncNoFlush diff --git a/VolumeControl.Log/FLog.cs b/VolumeControl.Log/FLog.cs index 9346bc775..a584f5650 100644 --- a/VolumeControl.Log/FLog.cs +++ b/VolumeControl.Log/FLog.cs @@ -119,22 +119,38 @@ public static void ChangeLogPath(string newPath) public static bool FilterEventType(EventType eventType) => Log.FilterEventType(eventType); /// public static void LogMessage(LogMessage logMessage) => Log.LogMessage(logMessage); - /// - public static void Trace(params object?[] lines) => Log.LogMessage(new(EventType.TRACE, lines)); + /// + public static bool Trace(params object?[] lines) => Log.LogMessage(new(EventType.TRACE, lines)); + /// + public static bool Trace(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.TRACE)); /// - public static void Debug(params object?[] lines) => Log.LogMessage(new(EventType.DEBUG, lines)); - /// - public static void Info(params object?[] lines) => Log.LogMessage(new(EventType.INFO, lines)); - /// - public static void Warning(params object?[] lines) => Log.LogMessage(new(EventType.WARN, lines)); + public static bool Debug(params object?[] lines) => Log.LogMessage(new(EventType.DEBUG, lines)); + /// + public static bool Debug(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.DEBUG)); + /// + public static bool Info(params object?[] lines) => Log.LogMessage(new(EventType.INFO, lines)); + /// + public static bool Info(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.INFO)); + /// + public static bool Warning(params object?[] lines) => Log.LogMessage(new(EventType.WARN, lines)); + /// + public static bool Warning(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.WARN)); /// - public static void Error(params object?[] lines) => Log.LogMessage(new(EventType.ERROR, lines)); + public static bool Error(params object?[] lines) => Log.LogMessage(new(EventType.ERROR, lines)); + /// + public static bool Error(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.ERROR)); /// - public static void Fatal(params object?[] lines) => Log.LogMessage(new(EventType.FATAL, lines)); + public static bool Fatal(params object?[] lines) => Log.LogMessage(new(EventType.FATAL, lines)); + /// + public static bool Fatal(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.FATAL)); /// - public static void Critical(params object?[] lines) => Log.LogMessage(new(EventType.CRITICAL, lines)); + public static bool Critical(params object?[] lines) => Log.LogMessage(new(EventType.CRITICAL, lines)); + /// + public static bool Critical(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.CRITICAL)); /// - public static void Blank(params object?[] lines) => Log.LogMessage(new(EventType.NONE, lines)); + public static bool Blank(params object?[] lines) => Log.LogMessage(new(EventType.NONE, lines)); + /// + public static bool Blank(LogMessage logMessage) => Log.LogMessage(logMessage.SetEventType(EventType.NONE)); #endregion AsyncLogWriter Methods #endregion Methods diff --git a/VolumeControl.Log/Interfaces/ILogWriter.cs b/VolumeControl.Log/Interfaces/ILogWriter.cs index e58906e92..8cf529ed2 100644 --- a/VolumeControl.Log/Interfaces/ILogWriter.cs +++ b/VolumeControl.Log/Interfaces/ILogWriter.cs @@ -12,55 +12,95 @@ public interface ILogWriter /// when the is shown; otherwise . bool FilterEventType(EventType eventType); /// - /// Writes the specified to the log. + /// Writes the specified to the log, if its event type is enabled by the filter. /// /// - /// When IsAsyncEnabled is , the message is added to the queue and written asynchronously; otherwise, the message is blocking and the message is written synchronously. + /// When IsAsyncEnabled is , the message is written asynchronously; + /// otherwise, the message is written synchronously and the caller will be blocked until the message has been written. /// - /// - void LogMessage(LogMessage logMessage); + /// The message to write to the log. + /// when the 's event type is enabled; otherwise, . + bool LogMessage(LogMessage logMessage); /// - /// Queues writing a message with the specified . + /// Queues writing an log message. /// - /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Trace(params object?[] lines); + /// A instance to write. + bool Trace(LogMessage logMessage); /// - /// Queues writing a message with the specified . + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Debug(params object?[] lines); + bool Debug(params object?[] lines); + /// + /// Queues writing an log message. + /// + /// A instance to write. + bool Debug(LogMessage logMessage); /// - /// Queues writing a message with the specified . + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Info(params object?[] lines); + bool Info(params object?[] lines); + /// + /// Queues writing an log message. + /// + /// A instance to write. + bool Info(LogMessage logMessage); /// - /// Queues writing a message with the specified . + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Warning(params object?[] lines); + bool Warning(params object?[] lines); /// - /// Queues writing a message with the specified . + /// Queues writing an log message. + /// + /// A instance to write. + bool Warning(LogMessage logMessage); + /// + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Error(params object?[] lines); + bool Error(params object?[] lines); + /// + /// Queues writing an log message. + /// + /// A instance to write. + bool Error(LogMessage logMessage); /// - /// Queues writing a message with the specified . + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Fatal(params object?[] lines); + bool Fatal(params object?[] lines); /// - /// Queues writing a message with the specified . + /// Queues writing an log message. + /// + /// A instance to write. + bool Fatal(LogMessage logMessage); + /// + /// Queues writing an message with the specified . /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Critical(params object?[] lines); + bool Critical(params object?[] lines); /// - /// Queues writing a message with the specified . + /// Queues writing an log message. + /// + /// A instance to write. + bool Critical(LogMessage logMessage); + /// + /// Queues writing an message with the specified . /// /// /// This produces a message with no event type header, but a timestamp is still shown. /// /// Any number of objects. Each object will be written on a new line. objects and blank strings are skipped. - void Blank(params object?[] lines); + bool Blank(params object?[] lines); + /// + /// Queues writing an log message. + /// + /// + /// This produces a message with no event type header, but a timestamp is still shown. + /// + /// A instance to write. + bool Blank(LogMessage logMessage); } } diff --git a/VolumeControl.Log/LogMessage.cs b/VolumeControl.Log/LogMessage.cs index 41a7aced6..63c1da1d3 100644 --- a/VolumeControl.Log/LogMessage.cs +++ b/VolumeControl.Log/LogMessage.cs @@ -12,7 +12,7 @@ public sealed class LogMessage : IEnumerable, IEnumerable /// Creates a new instance with the specified . /// /// The of this message. - /// The lines in this message. + /// The contents of the message, where each element represents one "line". public LogMessage(EventType eventType, params object?[] lines) { EventType = eventType; @@ -27,6 +27,15 @@ public LogMessage(EventType eventType) EventType = eventType; Lines = new(); } + /// + /// Creates a new instance with the specified and an undefined EventType. + /// + /// The contents of the message, where each element represents one "line". + public LogMessage(params object?[] lines) + { + EventType = EventType.NONE; + Lines = lines.ToList(); + } #endregion Constructor #region Properties @@ -35,6 +44,10 @@ public LogMessage(EventType eventType) /// public EventType EventType { get; set; } /// + /// Gets whether this instance has an EventType or not. + /// + public bool HasEventType => EventType != EventType.NONE; + /// /// Gets or sets the lines in this message. /// public List Lines { get; set; } @@ -44,39 +57,55 @@ public LogMessage(EventType eventType) public bool IsEmpty => Lines.Count == 0; #endregion Properties + #region Operators + /// + /// Converts a to a new instance. + /// + /// The string to convert. + public static implicit operator LogMessage(string s) => new(s); + #endregion Operators + #region Methods - #region (Internal) - internal void RemoveNullLines() - { - for (int i = Lines.Count - 1; i >= 0; --i) - { - if (Lines[i] == null) - { - Lines.RemoveAt(i); - } - } - } - #endregion (Internal) + #region ToString + /// + /// Gets the contents of the log message as a single string. + /// + public override string ToString() => string.Join(Environment.NewLine, Lines); + #endregion ToString + #region Add /// /// Appends the specified to the message. /// /// The content of the line. - public void Add(object? line) + /// This instance. + public LogMessage Add(object? line) { Lines.Add(line); + return this; } + #endregion Add - /// - public override string ToString() => string.Join(Environment.NewLine, Lines); + #region SetEventType + /// + /// Pipeline method that sets the event type of this log message. + /// + /// The EventType to use for this log message. + /// This instance. + public LogMessage SetEventType(EventType eventType) + { + EventType = eventType; + return this; + } + #endregion SetEventType #endregion Methods - #region IEnumerable + #region IEnumerable /// public IEnumerator GetEnumerator() => ((IEnumerable)this.Lines).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.Lines).GetEnumerator(); - #endregion + #endregion IEnumerable } }