/// <summary> /// Logs a message. /// </summary> /// <param name="messageType">Type of the message.</param> /// <param name="message">The text.</param> /// <param name="sourceName">Name of the source.</param> /// <param name="extendedData"> /// The extended data. Could be an exception, or a dictionary of properties or anything the user /// specifies. /// </param> /// <param name="callerMemberName">Name of the caller member.</param> /// <param name="callerFilePath">The caller file path.</param> /// <param name="callerLineNumber">The caller line number.</param> private static void LogMessage(LogMessageType messageType, string message, string sourceName, object extendedData, string callerMemberName, string callerFilePath, int callerLineNumber) { lock (SyncLock) { var prefix = GetConsoleColorAndPrefix(messageType, out var color); #region Create and Format the Output var sequence = _loggingSequence; var date = DateTime.UtcNow; _loggingSequence++; var loggerMessage = string.IsNullOrWhiteSpace(message) ? string.Empty : message.RemoveControlCharsExcept('\n'); var outputMessage = CreateOutputMessage(sourceName, loggerMessage, prefix, date); // Log the message asynchronously with the appropriate event args var eventArgs = new LogMessageReceivedEventArgs(sequence, messageType, date, sourceName, loggerMessage, extendedData, callerMemberName, callerFilePath, callerLineNumber); #endregion #region Fire Up External Logging Logic (Asynchronously) if (OnLogMessageReceived != null) { Task.Factory.StartNew(() => { try { OnLogMessageReceived?.Invoke(sourceName, eventArgs); } catch { // Ignore } }); } #endregion #region Display the Message by Writing to the Output Queue // Check if we are skipping these messages to be displayed based on settings if (Settings.DisplayLoggingMessageType.HasFlag(messageType) == false) { return; } Write(messageType, sourceName, eventArgs, outputMessage, color); #endregion } }
private static void Write(LogMessageType messageType, string sourceName, LogMessageReceivedEventArgs eventArgs, string outputMessage, ConsoleColor color) { // Select the writer based on the message type var writer = IsConsolePresent ? messageType.HasFlag(LogMessageType.Error) ? TerminalWriters.StandardError : TerminalWriters.StandardOutput : TerminalWriters.None; // Set the writer to Diagnostics if appropriate (Error and Debugging data go to the Diagnostics debugger // if it is attached at all if (IsDebuggerAttached && (IsConsolePresent == false || messageType.HasFlag(LogMessageType.Debug) || messageType.HasFlag(LogMessageType.Error))) { writer = writer | TerminalWriters.Diagnostics; } // Check if we really need to write this out if (writer == TerminalWriters.None) { return; } // Further format the output in the case there is an exception being logged if (writer.HasFlag(TerminalWriters.StandardError) && eventArgs.Exception != null) { try { outputMessage = $"{outputMessage}{Environment.NewLine}{eventArgs.Exception.Stringify().Indent()}"; } catch { // Ignore } } // Filter output messages via events var displayingEventArgs = new LogMessageDisplayingEventArgs(eventArgs); OnLogMessageDisplaying?.Invoke(sourceName, displayingEventArgs); if (displayingEventArgs.CancelOutput == false) { outputMessage.WriteLine(color, writer); } }
/// <summary> /// Initializes a new instance of the <see cref="LogMessageDisplayingEventArgs" /> class. /// </summary> /// <param name="data">The <see cref="LogMessageReceivedEventArgs" /> instance containing the event data.</param> public LogMessageDisplayingEventArgs(LogMessageReceivedEventArgs data) : base(data.Sequence, data.MessageType, data.UtcDate, data.Source, data.Message, data.ExtendedData, data.CallerMemberName, data.CallerFilePath, data.CallerLineNumber) { CancelOutput = false; }