/// <summary> /// Processes the specified log message synchronously and passes the log message to the next processing stages, /// if appropriate. This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> public void ProcessMessage(LocalLogMessage message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } lock (Sync) { if (!mInitialized) { throw new InvalidOperationException("The pipeline stage is not initialized. Ensure it is attached to the logging subsystem."); } try { if (OnProcessMessageBase(message)) { // pass log message to the next pipeline stages for (int i = 0; i < mNextStages.Length; i++) { mNextStages[i].ProcessMessage(message); } } } catch (Exception ex) { // swallow exception to avoid crashing the application, if the exception is not handled properly Debug.Fail("The pipeline stage threw an exception processing a message.", ex.ToString()); } } }
/// <summary> /// The callback that is expected to be invoked when a log message is to process. /// </summary> /// <param name="message"></param> /// <returns></returns> public bool ProcessSyncCallback(LocalLogMessage message) { ProcessSyncCallbackWasCalled = true; MessagePassedToProcessSyncCallback = message; MessagePassedToProcessSyncCallback.AddRef(); return(ProcessSyncCallbackReturnValue); }
protected override bool ProcessSync(LocalLogMessage message, out bool queueForAsyncProcessing) { ProcessSyncWasCalled = true; MessagePassedToProcessSync?.Release(); MessagePassedToProcessSync = message; MessagePassedToProcessSync.AddRef(); return(base.ProcessSync(message, out queueForAsyncProcessing)); }
public bool ProcessSyncCallback(LocalLogMessage message, out bool queueForAsyncProcessing) { queueForAsyncProcessing = ProcessSyncCallbackQueueForAsyncProcessing; ProcessSyncCallbackWasCalled = true; MessagePassedToProcessSyncCallback?.Release(); MessagePassedToProcessSyncCallback = message; MessagePassedToProcessSyncCallback.AddRef(); return(ProcessSyncCallbackReturnValue); }
/// <summary> /// Initializes a new instance of the <see cref="LocalLogMessage"/> class copying the specified one. /// </summary> /// <param name="other">Message to copy.</param> public LocalLogMessage(LocalLogMessage other) { Context = new Dictionary <string, object>(other.Context); mTimestamp = other.Timestamp; mHighPrecisionTimestamp = other.HighPrecisionTimestamp; mLogWriter = other.LogWriter; mLogLevel = other.LogLevel; mTags = other.Tags; mApplicationName = other.ApplicationName; mProcessName = other.ProcessName; mProcessId = other.ProcessId; mText = other.Text; }
/// <summary> /// Gets a log message from the pool, creates a new one, if the pool is empty. The returned message is not initialized. /// Call <see cref="LocalLogMessage.InitWith"/> to initialize it. /// </summary> /// <returns>The requested log message.</returns> public LocalLogMessage GetUninitializedMessage() { if (mMessages.TryTake(out var message)) { message.AddRef(); } else { message = new LocalLogMessage(this); } Debug.Assert(message.RefCount == 1); return(message); }
/// <summary> /// Is called on behalf of <see cref="ProcessingPipelineStage.ProcessMessage"/> (for internal use only). /// This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> /// <returns> /// true to pass the message to the following stages; /// false to stop processing the message. /// </returns> internal override bool OnProcessMessageBase(LocalLogMessage message) { try { return(ProcessSync(message)); } catch (Exception ex) { // swallow exception to avoid crashing the application, if the exception is not handled properly Debug.Fail("The pipeline stage threw an exception processing the message.", ex.ToString()); // let the following stages process the message // (hopefully this is the right decision in this case) return(true); } }
/// <summary> /// Is called on behalf of <see cref="ProcessingPipelineStage.ProcessMessage"/> (for internal use only). /// This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> /// <returns> /// true to pass the message to the following stages; /// false to stop processing the message. /// </returns> internal override bool OnProcessMessageBase(LocalLogMessage message) { try { // synchronous processing bool proceed = ProcessSync(message, out bool queueMessageForAsynchronousProcessing); // asynchronous processing if (queueMessageForAsynchronousProcessing) { if (mDiscardMessagesIfQueueFull) { message.AddRef(); bool pushed = mAsyncProcessingMessageStack.TryPush(message); if (pushed) { mTriggerAsyncProcessingEvent.Set(); } else { message.Release(); } } else { message.AddRef(); while (!mAsyncProcessingMessageStack.TryPush(message)) { Thread.Sleep(10); } mTriggerAsyncProcessingEvent.Set(); } } return(proceed); } catch (Exception ex) { // swallow exception to avoid crashing the application, if the exception is not handled properly Debug.Fail("The pipeline stage threw an exception processing the message.", ex.ToString()); // let the following stages process the message // (hopefully this is the right decision in this case) return(true); } }
/// <summary> /// When overridden in a derived class, processes the specified log message synchronously. /// This method is called by the thread writing the message and from within the pipeline stage lock (<see cref="ProcessingPipelineStage.Sync"/>). /// This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> /// <returns> /// true to pass the message to the following pipeline stages; /// otherwise false. /// </returns> /// <remarks> /// Call <see cref="LocalLogMessage.AddRef"/> on a message that should be stored any longer to prevent it from /// returning to the log message pool too early. Call <see cref="LocalLogMessage.Release"/> as soon as you don't /// need the message any more. /// </remarks> protected virtual bool ProcessSync(LocalLogMessage message) { return(true); }
/// <summary> /// When overridden in a derived class, processes the specified log message synchronously. /// This method is called by the thread writing the message and from within the pipeline stage lock. /// This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> /// <param name="queueForAsyncProcessing"> /// Receives a value indicating whether the message should be enqueued for asynchronous processing. /// </param> /// <returns> /// true to pass the message to the following pipeline stages; /// otherwise false. /// </returns> /// <remarks> /// Call <see cref="LocalLogMessage.AddRef"/> on a message that should be stored any longer to prevent it from /// returning to the log message pool too early. Call <see cref="LocalLogMessage.Release"/> as soon as you don't /// need the message any more. /// </remarks> protected virtual bool ProcessSync(LocalLogMessage message, out bool queueForAsyncProcessing) { queueForAsyncProcessing = true; return(true); }
/// <summary> /// Is called on behalf of <see cref="ProcessMessage"/> (for internal use only). /// This method must not throw exceptions. /// </summary> /// <param name="message">Message to process.</param> /// <returns> /// true to pass the message to the following stages; /// false to stop processing the message. /// </returns> internal abstract bool OnProcessMessageBase(LocalLogMessage message);
/// <summary> /// Returns a log message to the pool, so it can be re-used. /// This message is called by the messages, if their reference counter gets 0. /// </summary> /// <param name="message">Message to return to the pool.</param> public void ReturnMessage(LocalLogMessage message) { Debug.Assert(message.RefCount == 0); message.Reset(); mMessages.Add(message); }