/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } string messageContentToDisplay; try { messageContentToDisplay = _messageFormatter(message); if (messageContentToDisplay == null) { throw new Exception("messageFormatter returned null"); } } catch { if (IndividualLogEntryErrorBehaviour == ErrorBehaviourOptions.ThrowException) { throw; } return; } if (messageContentToDisplay == "") { return; } _outputWriter(messageContentToDisplay.ToString()); }
/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } }
/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } QueueMessage(message); FlushQueueIfNecessary(); }
/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (!AllowedLogLevels.Contains(message.LogLevel)) { return; } _logger.Log(message); }
/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var messagesToLogImmediatelyIfAny = QueueMessageAndReturnAnyMessagesThatShouldBeLoggedImmediately(message); if ((messagesToLogImmediatelyIfAny != null) && (messagesToLogImmediatelyIfAny.Count > 0)) { _logger.Log(messagesToLogImmediatelyIfAny); } }
private void QueueMessage(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } // If the message is to be evaluated when it's actually logged (which may be in the future), as opposed to when it's queued (which is right now) // the push it straight onto the queue. Or, if the content is a string and not a lazily-evaluating Func then we can also queue it immediately. if ((MessageEvaluationBehaviour == MessageEvaluationBehaviourOptions.EvaluateWhenLogged) || (message.ContentGenerator == null)) { _messages.Enqueue(message); return; } // If the message is to be evaluated when queued (ie. right now) then we need to evaulate the ContentGenerator. This will be desirable if there // is any content that is time dependent (eg. "time to complete = {x}ms") or in cases where there are any references that are required by the // message evaluation that might be disposed of between now and when the message is recorded. Note: Just because the message content is being // evaluated immediately doesn't negate the benefit of a content generator delegate, there could be relative-expensive-to-log messages that // should only be written away in debug mode, which case a FilteredLogger might wrap a ThrottlingLogger instance so that the messages are only // evaluated if Debug-level messages are allowed through the filter. string messageContents; try { messageContents = message.ContentGenerator(); // We know that ContentGenerator is non-null (we checked for a null reference above) } catch { if (IndividualLogEntryErrorBehaviour == ErrorBehaviourOptions.ThrowException) { throw; } return; } _messages.Enqueue( new LogEventDetails( message.LogLevel, message.LogDate, message.ManagedThreadId, messageContents, message.OptionalException ) ); }
/// <summary> /// This should throw an exception for a null message set but whether exceptions are thrown due to any other issues (eg. a message whose ContentGenerator /// delegate throws an exception or IO exceptions where file-writing is attempted) will vary depending upon the implementation /// </summary> public void Log(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } foreach (var logger in Loggers) { try { logger.Log(message); } catch { if (IndividualLoggerErrorBehaviour == ErrorBehaviourOptions.ThrowException) { throw; } } } }
private static string FormatMessage(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var detailedContent = new StringBuilder(); detailedContent.AppendFormat("[{0}] [Thread{1}] ", message.LogDate.ToString("yyyy-MM-dd HH:mm:ss.fff"), message.ManagedThreadId); if (message.LogLevel != LogLevel.Info) { // Don't bother displaying the text "Info", it's redundant (Debug, Warning or Error are useful content, though) detailedContent.AppendFormat("[{0}] ", message.LogLevel.ToString()); } var content = message.Content ?? message.ContentGenerator(); if (string.IsNullOrWhiteSpace(content)) { if (message.OptionalException == null) { detailedContent.Append("{Empty Message}"); } } else { detailedContent.Append(content); } if (message.OptionalException != null) { if (!string.IsNullOrWhiteSpace(content)) { detailedContent.Append(" - "); } detailedContent.Append(message.OptionalException.ToString()); } return(detailedContent.ToString()); }
/// <summary> /// This will throw an exception for a null message argument or if the message's ContentGenerator delegate raises an exception /// </summary> public static string Format(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } try { return(FormatMessage(message)); } catch (Exception e) { return(FormatMessage( new LogEventDetails( message.LogLevel, message.LogDate, message.ManagedThreadId, "Message log failure: " + e.Message, e ) )); } }
private List <LogEventDetails> QueueMessageAndReturnAnyMessagesThatShouldBeLoggedImmediately(LogEventDetails message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (message.LogLevel != LogLevel.Error) { _messages.Enqueue(message); while (_messages.Count >= MaximumNumberOfHistoricalMessagesToMaintain) { _messages.Dequeue(); } return(null); } var historicalMessagesToIncludeWithError = HistoryLoggingBehaviour == HistoryLoggingBehaviourOptions.IncludeAllPrecedingMessages ? (IEnumerable <LogEventDetails>)_messages : _messages.Where(m => m.ManagedThreadId == message.ManagedThreadId); var messagesToPassThrough = new List <LogEventDetails>(); if (historicalMessagesToIncludeWithError.Any()) { var historicalMessagesToIncludeWithErrorArray = historicalMessagesToIncludeWithError.ToArray(); if (historicalMessagesToIncludeWithErrorArray.Length > MaximumNumberOfHistoricalMessagesToMaintain) { messagesToPassThrough.AddRange( historicalMessagesToIncludeWithErrorArray.Skip( MaximumNumberOfHistoricalMessagesToIncludeWithAnErrorEntry - historicalMessagesToIncludeWithErrorArray.Length ) ); } else { messagesToPassThrough.AddRange(historicalMessagesToIncludeWithErrorArray); } var historicalMessagesLookup = new HashSet <LogEventDetails>(historicalMessagesToIncludeWithError); var messagesToKeep = _messages.Where(m => !historicalMessagesLookup.Contains(m)).ToArray(); _messages.Clear(); foreach (var messageToKeep in messagesToKeep) { _messages.Enqueue(messageToKeep); } } messagesToPassThrough.Add(message); return(messagesToPassThrough); }