/// <summary> /// Forwards the log event to one of the sub-targets. /// The sub-target is randomly chosen. /// </summary> /// <param name="logEvent">The log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { if (Targets.Count == 0) { logEvent.Continuation(null); return; } int selectedTarget; lock (random) { selectedTarget = random.Next(Targets.Count); } Targets[selectedTarget].WriteAsyncLogEvent(logEvent); }
/// <summary> /// Forwards the write to one of the targets from /// the <see cref="NLog.Targets" /> collection. /// </summary> /// <param name="logEvent">The log event.</param> /// <remarks> /// The writes are routed in a round-robin fashion. /// The first log event goes to the first target, the second /// one goes to the second target and so on looping to the /// first target when there are no more targets available. /// In general request N goes to Targets[N % Targets.Count]. /// </remarks> protected override void Write(AsyncLogEventInfo logEvent) { if (Targets.Count == 0) { logEvent.Continuation(null); return; } int selectedTarget; lock (lockObject) { selectedTarget = currentTarget; currentTarget = (currentTarget + 1)%Targets.Count; } Targets[selectedTarget].WriteAsyncLogEvent(logEvent); }
/// <summary> /// Forwards the log event to the sub-targets until one of them succeeds. /// </summary> /// <param name="logEvent">The log event.</param> /// <remarks> /// The method remembers the last-known-successful target /// and starts the iteration from it. /// If <see cref="ReturnToFirstOnSuccess" /> is set, the method /// resets the target to the first target /// stored in <see cref="NLog.Targets" />. /// </remarks> protected override void Write(AsyncLogEventInfo logEvent) { AsyncContinuation continuation = null; var tryCounter = 0; int targetToInvoke; continuation = ex => { if (ex == null) { // success lock (lockObject) { if (currentTarget != 0) { if (ReturnToFirstOnSuccess) { InternalLogger.Debug("Fallback: target '{0}' succeeded. Returning to the first one.", Targets[currentTarget]); currentTarget = 0; } } } logEvent.Continuation(null); return; } // failure lock (lockObject) { InternalLogger.Warn("Fallback: target '{0}' failed. Proceeding to the next one. Error was: {1}", Targets[currentTarget], ex); // error while writing, go to the next one currentTarget = (currentTarget + 1)%Targets.Count; tryCounter++; targetToInvoke = currentTarget; if (tryCounter >= Targets.Count) { targetToInvoke = -1; } } if (targetToInvoke >= 0) { Targets[targetToInvoke].WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); } else { logEvent.Continuation(ex); } }; lock (lockObject) { targetToInvoke = currentTarget; } Targets[targetToInvoke].WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
/// <summary> /// Sends the /// rendered logging event over the network optionally concatenating it with a newline character. /// </summary> /// <param name="logEvent">The logging event.</param> protected override void Write(AsyncLogEventInfo logEvent) { var address = Address.Render(logEvent.LogEvent); var bytes = GetBytesToWrite(logEvent.LogEvent); if (KeepConnection) { var sender = GetCachedNetworkSender(address); ChunkedSend( sender, bytes, ex => { if (ex != null) { InternalLogger.Error("Error when sending {0}", ex); ReleaseCachedConnection(sender); } logEvent.Continuation(ex); }); } else { var sender = SenderFactory.Create(address); sender.Initialize(); lock (openNetworkSenders) { openNetworkSenders.Add(sender); ChunkedSend( sender, bytes, ex => { lock (openNetworkSenders) { openNetworkSenders.Remove(sender); } if (ex != null) { InternalLogger.Error("Error when sending {0}", ex); } sender.Close(ex2 => { }); logEvent.Continuation(ex); }); } } }
/// <summary> /// Writes the specified log event to the wrapped target, retrying and pausing in case of an error. /// </summary> /// <param name="logEvent">The log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { AsyncContinuation continuation = null; var counter = 0; continuation = ex => { if (ex == null) { logEvent.Continuation(null); return; } var retryNumber = Interlocked.Increment(ref counter); InternalLogger.Warn("Error while writing to '{0}': {1}. Try {2}/{3}", WrappedTarget, ex, retryNumber, RetryCount); // exceeded retry count if (retryNumber >= RetryCount) { InternalLogger.Warn("Too many retries. Aborting."); logEvent.Continuation(ex); return; } // sleep and try again Thread.Sleep(RetryDelayMilliseconds); WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }; WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
/// <summary> /// Writes log event to the log target. Must be overridden in inheriting /// classes. /// </summary> /// <param name="logEvent">Log event to be written out.</param> protected virtual void Write(AsyncLogEventInfo logEvent) { try { Write(logEvent.LogEvent); logEvent.Continuation(null); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } logEvent.Continuation(exception); } }
/// <summary> /// Writes the log to the target. /// </summary> /// <param name="logEvent">Log event to write.</param> public void WriteAsyncLogEvent(AsyncLogEventInfo logEvent) { lock (SyncRoot) { if (!IsInitialized) { logEvent.Continuation(null); return; } if (initializeException != null) { logEvent.Continuation(CreateInitException()); return; } var wrappedContinuation = AsyncHelpers.PreventMultipleCalls(logEvent.Continuation); try { Write(logEvent.LogEvent.WithContinuation(wrappedContinuation)); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } wrappedContinuation(exception); } } }