protected void LogReceived(AsyncLogEventInfo log) { LogEventViewModel vm = new LogEventViewModel(log.LogEvent); Dispatcher.BeginInvoke(new Action(() => { if (MaxRowCount > 0 && LogEntries.Count >= MaxRowCount) { LogEntries.RemoveAt(0); } LogEntries.Add(vm); if (AutoScrollToLast) { ScrollToLast(); } ItemAdded(this, (NLogEvent)log.LogEvent); })); }
protected override void Write(AsyncLogEventInfo logEvent) { WriteCount++; ThreadPool.QueueUserWorkItem( s => { if (ThrowExceptions) { logEvent.Continuation(new InvalidOperationException("Some problem!")); logEvent.Continuation(new InvalidOperationException("Some problem!")); } else { logEvent.Continuation(null); logEvent.Continuation(null); } }); }
protected override void Write(AsyncLogEventInfo logEvent) { if ((DateTime.Now - _lastLogEvent).TotalMinutes >= MinLogInterval) { _lastLogEvent = DateTime.Now; WrappedTarget.WriteAsyncLogEvent(logEvent); } else { logEvent.Continuation(null); // EXPERIMENTAL: check if the level of the log event is higher than "WARN" (3) and // log a debug message about keeping back the email message: if (logEvent.LogEvent.Level.Ordinal > 3) { Log.Debug("RateLimitWrapper: not sending email, frequency too high!"); } } }
/// <summary> /// Forwards the write to one of the targets from /// the <see cref="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 write to one of the targets from /// the <see cref="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 (this.Targets.Count == 0) { logEvent.Continuation(null); return; } int selectedTarget; lock (this.lockObject) { selectedTarget = this.currentTarget; this.currentTarget = (this.currentTarget + 1) % this.Targets.Count; } this.Targets[selectedTarget].WriteAsyncLogEvent(logEvent); }
private NLogEvents TranslateLogEvents(IList <AsyncLogEventInfo> logEvents) { if (logEvents.Count == 0 && !LogManager.ThrowExceptions) { InternalLogger.Error("LogReceiverServiceTarget(Name={0}): LogEvents array is empty, sending empty event...", Name); return(new NLogEvents()); } string clientID = string.Empty; if (ClientId != null) { clientID = ClientId.Render(logEvents[0].LogEvent); } var networkLogEvents = new NLogEvents { ClientName = clientID, LayoutNames = new StringCollection(), Strings = new StringCollection(), BaseTimeUtc = logEvents[0].LogEvent.TimeStamp.ToUniversalTime().Ticks }; var stringTable = new Dictionary <string, int>(); for (int i = 0; i < Parameters.Count; ++i) { networkLogEvents.LayoutNames.Add(Parameters[i].Name); } if (IncludeEventProperties) { AddEventProperties(logEvents, networkLogEvents); } networkLogEvents.Events = new NLogEvent[logEvents.Count]; for (int i = 0; i < logEvents.Count; ++i) { AsyncLogEventInfo ev = logEvents[i]; networkLogEvents.Events[i] = TranslateEvent(ev.LogEvent, networkLogEvents, stringTable); } return(networkLogEvents); }
protected override void Write(AsyncLogEventInfo logEvent) { GetConnection(); InternalLogger.Trace("Fluentd (Name={0}): Sending to address: '{1}:{2}'", Name, this.Host, this.Port); var record = new Dictionary <string, string>(); var logMessage = GetFormattedMessage(logEvent.LogEvent); record.Add("message", logMessage); try { this.emitter.Pack(logEvent.LogEvent.TimeStamp, this.Tag, record); } catch (Exception ex) { InternalLogger.Warn("Fluentd Emit - " + ex.ToString()); throw; // Notify NLog of failure } }
/// <summary> /// Writes async log event to the log target. /// </summary> /// <param name="logEvent">Async Log event to be written out.</param> protected virtual void Write(AsyncLogEventInfo logEvent) { try { MergeEventProperties(logEvent.LogEvent); Write(logEvent.LogEvent); logEvent.Continuation(null); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } logEvent.Continuation(exception); } }
private void Enqueue(AsyncLogEventInfo asyncLogEventInfo, int timeout) { void LogEnqueueResult(string message) { if (!InternalLogger.IsDebugEnabled) { return; } InternalLogger.Debug("[Syslog] {0} '{1}'", message, asyncLogEventInfo.ToFormattedMessage()); } if (queue.TryAdd(asyncLogEventInfo, timeout, token)) { LogEnqueueResult("Enqueued"); return; } LogEnqueueResult("Failed enqueuing"); asyncLogEventInfo.Continuation(new InvalidOperationException($"Enqueue failed")); }
protected override void Write(AsyncLogEventInfo logEvent) { Assert.True(this.FlushCount <= this.WriteCount); Interlocked.Increment(ref this.WriteCount); ThreadPool.QueueUserWorkItem( s => { if (this.ThrowExceptions) { logEvent.Continuation(new InvalidOperationException("Some problem!")); logEvent.Continuation(new InvalidOperationException("Some problem!")); } else { logEvent.Continuation(null); logEvent.Continuation(null); } }); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Write" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(IList <AsyncLogEventInfo> logEvents) { InternalLogger.Trace("SplitGroup(Name={0}): Writing {1} events", Name, logEvents.Count); if (logEvents.Count == 1) { Write(logEvents[0]); // Skip array allocation for each destination target } else if (Targets.Count == 0 || logEvents.Count == 0) { for (int i = 0; i < logEvents.Count; ++i) { logEvents[i].Continuation(null); } } else { if (Targets.Count > 1) { for (int i = 0; i < logEvents.Count; ++i) { AsyncLogEventInfo ev = logEvents[i]; logEvents[i] = ev.LogEvent.WithContinuation(CreateCountedContinuation(ev.Continuation, Targets.Count)); } } for (int i = 0; i < Targets.Count; ++i) { InternalLogger.Trace("SplitGroup(Name={0}): Sending {1} events to {2}", Name, logEvents.Count, Targets[i]); var targetLogEvents = logEvents; if (i < Targets.Count - 1) { // OptimizeBufferReuse = true, will change the input-array (so we make clones here) AsyncLogEventInfo[] cloneLogEvents = new AsyncLogEventInfo[logEvents.Count]; logEvents.CopyTo(cloneLogEvents, 0); targetLogEvents = cloneLogEvents; } Targets[i].WriteAsyncLogEvents(targetLogEvents); } } }
private void Send(AsyncLogEventInfo info) { var message = RenderLogEvent(Layout, info.LogEvent); var baseurl = RenderLogEvent(BaseUrl, info.LogEvent); var botToken = RenderLogEvent(BotToken, info.LogEvent); var chatId = RenderLogEvent(ChatId, info.LogEvent); var uriBuilder = new UriBuilder(baseurl + botToken); uriBuilder.Path += "/sendMessage"; var url = uriBuilder.Uri.ToString(); var builder = TelegramMessageBuilder .Build(url, message) .ToChat(chatId) .OnError(e => info.Continuation(e)) ; builder.Send(); }
/// <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; int counter = 0; continuation = ex => { if (ex == null) { logEvent.Continuation(null); return; } int 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 (Check every 100 ms if target have been closed) for (int i = 0; i < RetryDelayMilliseconds;) { int retryDelay = Math.Min(100, RetryDelayMilliseconds - i); Thread.Sleep(retryDelay); i += retryDelay; if (!IsInitialized) { InternalLogger.Warn("Target closed. Aborting."); logEvent.Continuation(ex); return; } } WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }; WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
/// <summary> /// Writes async log event to the log target. /// </summary> /// /// <param name="logEvent">Logging event to be written out.</param> protected override void Write(AsyncLogEventInfo logEvent) { LogEntry logEntry = null; try { logEntry = BuildLogEntry(logEvent.LogEvent); } catch (Exception ex) { InternalLogger.Error(ex, "GoogleStackdriver(Name={0}): Failed to create LogEntry, marked as failed", Name); logEvent.Continuation(ex); } if (logEntry != null) { WriteLogEntries(new[] { logEntry }, logEvent.Continuation); } }
/// <summary> /// Writes log event to the wrapped target if the current <see cref="MessagesWrittenCount"/> is lower than <see cref="MessageLimit"/>. /// If the <see cref="MessageLimit"/> is already reached, no log event will be written to the wrapped target. /// <see cref="MessagesWrittenCount"/> resets when the current <see cref="Interval"/> is expired. /// </summary> /// <param name="logEvent">Log event to be written out.</param> protected override void Write(AsyncLogEventInfo logEvent) { if (IsIntervalExpired()) { ResetInterval(); InternalLogger.Debug("LimitingWrapper(Name={0}): New interval of '{1}' started.", Name, Interval); } if (MessagesWrittenCount < MessageLimit) { WrappedTarget.WriteAsyncLogEvent(logEvent); MessagesWrittenCount++; } else { logEvent.Continuation(null); InternalLogger.Trace("LimitingWrapper(Name={0}): Discarded event, because MessageLimit of '{1}' was reached.", Name, MessageLimit); } }
/// <summary> /// Forwards the specified log event to all sub-targets. /// </summary> /// <param name="logEvent">The log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { if (Targets.Count == 0) { logEvent.Continuation(null); } else { if (Targets.Count > 1) { logEvent = logEvent.LogEvent.WithContinuation(CreateCountedContinuation(logEvent.Continuation, Targets.Count)); } for (int i = 0; i < Targets.Count; ++i) { Targets[i].WriteAsyncLogEvent(logEvent); } } }
protected override void Write(AsyncLogEventInfo logEvent) { var continuation = logEvent.Continuation; var basicProperties = GetBasicProperties(logEvent); var uncompressedMessage = GetMessage(logEvent); var message = CompressMessage(uncompressedMessage); var routingKey = GetTopic(logEvent.LogEvent); if (_Model == null || !_Model.IsOpen) { StartConnection(); } if (_Model == null || !_Model.IsOpen) { AddUnsent(routingKey, basicProperties, message); return; } try { CheckUnsent(); Publish(message, basicProperties, routingKey); return; } catch (IOException e) { AddUnsent(routingKey, basicProperties, message); continuation(e); //InternalLogger.Error("Could not send to RabbitMQ instance! {0}", e.ToString()); } catch (ObjectDisposedException e) { AddUnsent(routingKey, basicProperties, message); continuation(e); //InternalLogger.Error("Could not write data to the network stream! {0}", e.ToString()); } ShutdownAmqp(_Connection, new ShutdownEventArgs(ShutdownInitiator.Application, Constants.ChannelError, "Could not talk to RabbitMQ instance", null)); // using this version of constructor, because RabbitMQ.Client from 3.5.x don't have ctor without cause parameter }
protected override void Write(AsyncLogEventInfo info) { try { var uri = new Uri(Url.Render(info.LogEvent)); var json = BuildJsonEvent(info.LogEvent); #if DEBUG Debug.WriteLine("Sending: " + json); #endif _poster.Post(uri, json); info.Continuation(null); } catch (Exception ex) { info.Continuation(ex); } }
/// <summary> /// Invokes the web service method. /// </summary> /// <param name="parameters">Parameters to be passed.</param> /// <param name="logEvent">The logging event.</param> protected override void DoInvoke(object[] parameters, AsyncLogEventInfo logEvent) { var request = (HttpWebRequest)WebRequest.Create(BuildWebServiceUrl(parameters)); if (this.Headers != null && this.Headers.Count > 0) { for (int i = 0; i < this.Headers.Count; i++) { string headerValue = base.RenderLogEvent(this.Headers[i].Layout, logEvent.LogEvent); if (headerValue == null) { continue; } request.Headers[this.Headers[i].Name] = headerValue; } } DoInvoke(parameters, request, logEvent.Continuation); }
private async Task WriteAsync(AsyncLogEventInfo info) { try { InternalLogger.Debug("Async post event: {0}.", info.LogEvent.SequenceID); var result = await Client.PostAsync(Url, new JsonContent(GetContent(info.LogEvent))); InternalLogger.Debug("Response of event {0} from '{1}': {2}", info.LogEvent.SequenceID, Url, result); result.EnsureSuccessStatusCode(); info.Continuation(null); } catch (Exception ex) { InternalLogger.Error(ex, "Async write error of event: {0}.", info.LogEvent.SequenceID); info.Continuation(ex); } }
protected override void Write(AsyncLogEventInfo info) { if (!_client.Configuration.IsValid) { return; } var builder = _client.CreateFromLogEvent(info.LogEvent); foreach (var field in Fields) { var renderedField = field.Layout.Render(info.LogEvent); if (!String.IsNullOrWhiteSpace(renderedField)) { builder.AddObject(renderedField, field.Name); } } builder.Submit(); }
/// <summary> /// Writes the log to the target. /// </summary> /// <param name="logEvent">Log event to write.</param> public void WriteAsyncLogEvent(AsyncLogEventInfo logEvent) { lock (this.SyncRoot) { if (!this.IsInitialized) { logEvent.Continuation(null); return; } if (this.initializeException != null) { logEvent.Continuation(this.CreateInitException()); return; } AsyncContinuation wrappedContinuation = AsyncHelpers.PreventMultipleCalls(this.LoggingConfiguration, logEvent.Continuation);; // Create async continuation to put log item back into the pool if (this.LoggingConfiguration.PoolingEnabled()) { var pool = this.LoggingConfiguration.PoolFactory.Get <CombinedAsyncContinuationPool, CombinedAsyncContinuation>(); wrappedContinuation = pool.Get(wrappedContinuation, logEvent.LogEvent.PutBackDelegate).Delegate; } try { this.Write(logEvent.LogEvent.WithContinuation(wrappedContinuation)); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } wrappedContinuation(exception); } } }
/// <summary> /// Adds the specified log event to the buffer. /// </summary> /// <param name="eventInfo">Log event.</param> /// <returns>The number of items in the buffer.</returns> public int Append(AsyncLogEventInfo eventInfo) { lock (_lockObject) { // make room for additional item if (_count >= _buffer.Length) { if (_growAsNeeded && _buffer.Length < _growLimit) { // create a new buffer, copy data from current int newLength = _buffer.Length * 2; if (newLength >= _growLimit) { newLength = _growLimit; } InternalLogger.Trace("Enlarging LogEventInfoBuffer from {0} to {1}", _buffer.Length, newLength); var newBuffer = new AsyncLogEventInfo[newLength]; Array.Copy(_buffer, 0, newBuffer, 0, _buffer.Length); _buffer = newBuffer; } else { // lose the oldest item _getPointer = _getPointer + 1; } } // put the item _putPointer = _putPointer % _buffer.Length; _buffer[_putPointer] = eventInfo; _putPointer = _putPointer + 1; _count++; if (_count >= _buffer.Length) { _count = _buffer.Length; } return _count; } }
/// <summary> /// Enqueues another item. If the queue is overflown the appropriate /// action is taken as specified by <see cref="AsyncRequestQueueBase.OnOverflow"/>. /// </summary> /// <param name="logEventInfo">The log event info.</param> /// <returns>Queue was empty before enqueue</returns> public override bool Enqueue(AsyncLogEventInfo logEventInfo) { long currentCount = Interlocked.Increment(ref _count); if (currentCount > RequestLimit) { InternalLogger.Debug("Async queue is full"); switch (OnOverflow) { case AsyncTargetWrapperOverflowAction.Discard: { do { if (_logEventInfoQueue.TryDequeue(out var lostItem)) { InternalLogger.Debug("Discarding one element from queue"); currentCount = Interlocked.Decrement(ref _count); OnLogEventDropped(lostItem.LogEvent); break; } currentCount = Interlocked.Read(ref _count); } while (currentCount > RequestLimit); } break; case AsyncTargetWrapperOverflowAction.Block: { currentCount = WaitForBelowRequestLimit(); } break; case AsyncTargetWrapperOverflowAction.Grow: { OnLogEventQueueGrows(currentCount); } break; } } _logEventInfoQueue.Enqueue(logEventInfo); return(currentCount == 1); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Write" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(ArraySegment <AsyncLogEventInfo> logEvents) { // if web service call is being processed, buffer new events and return // lock is being held here if (this.inCall) { for (int x = 0; x < logEvents.Count; x++) { var ev = logEvents.Array[x]; this.buffer.Append(ev); } return; } var networkLogEvents = this.TranslateLogEvents(logEvents); var arr = new AsyncLogEventInfo[logEvents.Count]; Array.Copy(logEvents.Array, logEvents.Offset, arr, 0, logEvents.Count); this.Send(networkLogEvents, arr); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Append" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(IList<AsyncLogEventInfo> logEvents) { // if web service call is being processed, buffer new events and return // lock is being held here if (inCall) { for (int i = 0; i < logEvents.Count; ++i) { PrecalculateVolatileLayouts(logEvents[i].LogEvent); buffer.Append(logEvents[i]); } return; } // OptimizeBufferReuse = true, will reuse the input-array on method-exit (so we make clone here) AsyncLogEventInfo[] logEventsArray = new AsyncLogEventInfo[logEvents.Count]; logEvents.CopyTo(logEventsArray, 0); var networkLogEvents = TranslateLogEvents(logEventsArray); Send(networkLogEvents, logEventsArray, null); }
protected override void Write(AsyncLogEventInfo logEvent) { try { // The check for the request is a dirty way to check if we're trying to log from App_Start if (HttpContext.Current != null && HttpContext.Current.Request != null) { EnqueueLogEvent(logEvent); return; } } catch (HttpException) { // We're in App_Start, so we'll just write the log directly } using (MiniProfiler.Current.Ignore()) { Cohort.Database.Insert(ProjectLog(logEvent.LogEvent)); } base.Write(logEvent); }
/// <summary> /// Writes the array of log events. /// </summary> /// <param name="logEvents">The log events.</param> public void WriteAsyncLogEvents(params AsyncLogEventInfo[] logEvents) { if (logEvents == null || logEvents.Length == 0) { return; } if (!this.IsInitialized) { lock (this.SyncRoot) { foreach (var ev in logEvents) { ev.Continuation(null); } } return; } if (this.initializeException != null) { lock (this.SyncRoot) { foreach (var ev in logEvents) { ev.Continuation(this.CreateInitException()); } } return; } var wrappedEvents = new AsyncLogEventInfo[logEvents.Length]; for (int i = 0; i < logEvents.Length; ++i) { wrappedEvents[i] = logEvents[i].LogEvent.WithContinuation(AsyncHelpers.PreventMultipleCalls(logEvents[i].Continuation)); } this.WriteAsyncThreadSafe(wrappedEvents); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Append" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(IList <AsyncLogEventInfo> logEvents) { // if web service call is being processed, buffer new events and return // lock is being held here if (inCall) { for (int i = 0; i < logEvents.Count; ++i) { PrecalculateVolatileLayouts(logEvents[i].LogEvent); buffer.Append(logEvents[i]); } return; } // Make clone as the input IList will be reused on next call AsyncLogEventInfo[] logEventsArray = new AsyncLogEventInfo[logEvents.Count]; logEvents.CopyTo(logEventsArray, 0); var networkLogEvents = TranslateLogEvents(logEvents); Send(networkLogEvents, logEvents, null); }
/// <summary> /// Forwards the call to the <see cref="WrapperTargetBase.WrappedTarget"/>.Write() /// and calls <see cref="Target.Flush(AsyncContinuation)"/> on it if LogEvent satisfies /// the flush condition or condition is null. /// </summary> /// <param name="logEvent">Logging event to be written out.</param> protected override void Write(AsyncLogEventInfo logEvent) { if (this.Condition == null || this.Condition.Evaluate(logEvent.LogEvent).Equals(true)) { AsyncContinuation currentContinuation = logEvent.Continuation; AsyncContinuation wrappedContinuation = (ex) => { if (ex == null) { this.WrappedTarget.Flush((e) => { }); } this.pendingManualFlushList.CompleteOperation(ex); currentContinuation(ex); }; this.pendingManualFlushList.BeginOperation(); this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(wrappedContinuation)); } else { this.WrappedTarget.WriteAsyncLogEvent(logEvent); } }
/// <summary> /// Checks the condition against the passed log event. /// If the condition is met, the log event is forwarded to /// the wrapped target. /// </summary> /// <param name="logEvent">Log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { object v = this.Condition.Evaluate(logEvent.LogEvent); if (boxedBooleanTrue.Equals(v)) { this.WrappedTarget.WriteAsyncLogEvent(logEvent); } else { logEvent.Continuation(null); } }
/// <summary> /// Forwards the call to the <see cref="WrapperTargetBase.WrappedTarget"/>.Write() /// and calls <see cref="Target.Flush(AsyncContinuation)"/> on it. /// </summary> /// <param name="logEvent">Logging event to be written out.</param> protected override void Write(AsyncLogEventInfo logEvent) { this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(AsyncHelpers.PrecededBy(logEvent.Continuation, this.WrappedTarget.Flush))); }
/// <summary> /// Write to queue without locking <see cref="Target.SyncRoot"/> /// </summary> /// <param name="logEvent"></param> protected override void WriteAsyncThreadSafe(AsyncLogEventInfo logEvent) { try { this.Write(logEvent); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } logEvent.Continuation(exception); } }
/// <summary> /// Writes the specified array of logging events to a file specified in the FileName /// parameter. /// </summary> /// <param name="logEvents">An array of <see cref="LogEventInfo "/> objects.</param> /// <remarks> /// This function makes use of the fact that the events are batched by sorting /// the requests by filename. This optimizes the number of open/close calls /// and can help improve performance. /// </remarks> protected override void Write(AsyncLogEventInfo[] logEvents) { var buckets = logEvents.BucketSort(c => this.FileName.Render(c.LogEvent)); using (var ms = new MemoryStream()) { var pendingContinuations = new List<AsyncContinuation>(); foreach (var bucket in buckets) { string fileName = bucket.Key; ms.SetLength(0); ms.Position = 0; LogEventInfo firstLogEvent = null; foreach (AsyncLogEventInfo ev in bucket.Value) { if (firstLogEvent == null) { firstLogEvent = ev.LogEvent; } byte[] bytes = this.GetBytesToWrite(ev.LogEvent); ms.Write(bytes, 0, bytes.Length); pendingContinuations.Add(ev.Continuation); } this.FlushCurrentFileWrites(fileName, firstLogEvent, ms, pendingContinuations); } } }
/// <summary> /// Renders the logging event message and adds it to the internal ArrayList of log messages. /// </summary> /// <param name="logEvent">The logging event.</param> protected override void Write(AsyncLogEventInfo logEvent) { this.Write(new[] { logEvent }); }
/// <summary> /// Evaluates all filtering rules to find the first one that matches. /// The matching rule determines the filtering condition to be applied /// to all items in a buffer. If no condition matches, default filter /// is applied to the array of log events. /// </summary> /// <param name="logEvents">Array of log events to be post-filtered.</param> protected override void Write(AsyncLogEventInfo[] logEvents) { ConditionExpression resultFilter = null; InternalLogger.Trace("Running {0} on {1} events", this, logEvents.Length); // evaluate all the rules to get the filtering condition for (int i = 0; i < logEvents.Length; ++i) { foreach (FilteringRule rule in this.Rules) { object v = rule.Exists.Evaluate(logEvents[i].LogEvent); if (boxedTrue.Equals(v)) { InternalLogger.Trace("Rule matched: {0}", rule.Exists); resultFilter = rule.Filter; break; } } if (resultFilter != null) { break; } } if (resultFilter == null) { resultFilter = this.DefaultFilter; } if (resultFilter == null) { this.WrappedTarget.WriteAsyncLogEvents(logEvents); } else { InternalLogger.Trace("Filter to apply: {0}", resultFilter); // apply the condition to the buffer var resultBuffer = new List<AsyncLogEventInfo>(); for (int i = 0; i < logEvents.Length; ++i) { object v = resultFilter.Evaluate(logEvents[i].LogEvent); if (boxedTrue.Equals(v)) { resultBuffer.Add(logEvents[i]); } else { // anything not passed down will be notified about successful completion logEvents[i].Continuation(null); } } InternalLogger.Trace("After filtering: {0} events.", resultBuffer.Count); if (resultBuffer.Count > 0) { InternalLogger.Trace("Sending to {0}", this.WrappedTarget); this.WrappedTarget.WriteAsyncLogEvents(resultBuffer.ToArray()); } } }
/// <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 (this.Targets.Count == 0) { logEvent.Continuation(null); return; } int selectedTarget; lock (this.lockObject) { selectedTarget = this.currentTarget; this.currentTarget = (this.currentTarget + 1) % this.Targets.Count; } this.Targets[selectedTarget].WriteAsyncLogEvent(logEvent); }
/// <summary> /// Renders an array logging events. /// </summary> /// <param name="logEvents">Array of logging events.</param> protected override void Write(AsyncLogEventInfo[] logEvents) { foreach (var bucket in logEvents.BucketSort(c => this.GetSmtpSettingsKey(c.LogEvent))) { var eventInfos = bucket.Value; this.ProcessSingleMailMessage(eventInfos); } }
/// <summary> /// Forwards the specified log event to all sub-targets. /// </summary> /// <param name="logEvent">The log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { AsyncHelpers.ForEachItemSequentially(this.Targets, logEvent.Continuation, (t, cont) => t.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(cont))); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Write" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(AsyncLogEventInfo[] logEvents) { var buckets = SortHelpers.BucketSort(logEvents, c => this.BuildConnectionString(c.LogEvent)); try { foreach (var kvp in buckets) { foreach (AsyncLogEventInfo ev in kvp.Value) { try { this.WriteEventToDatabase(ev.LogEvent); ev.Continuation(null); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } // in case of exception, close the connection and report it InternalLogger.Error("Error when writing to database {0}", exception); this.CloseConnection(); ev.Continuation(exception); } } } } finally { if (!this.KeepConnection) { this.CloseConnection(); } } }
protected override void Write(AsyncLogEventInfo[] logEvents) { if (logEvents.Length == 0) { return; } var sb = new StringBuilder(); var lastLogEvent = logEvents[logEvents.Length - 1]; foreach (var ev in logEvents) { sb.Append(this.Layout.Render(ev.LogEvent)); sb.Append("\n"); } MessageBoxHelper.Show(sb.ToString(), this.Caption.Render(lastLogEvent.LogEvent)); for (int i = 0; i < logEvents.Length; ++i) { logEvents[i].Continuation(null); } }
/// <summary> /// Adds the log event to asynchronous queue to be processed by /// the lazy writer thread. /// </summary> /// <param name="logEvent">The log event.</param> /// <remarks> /// The <see cref="Target.PrecalculateVolatileLayouts"/> is called /// to ensure that the log event can be processed in another thread. /// </remarks> protected override void Write(AsyncLogEventInfo logEvent) { this.MergeEventProperties(logEvent.LogEvent); this.PrecalculateVolatileLayouts(logEvent.LogEvent); bool queueWasEmpty = this.RequestQueue.Enqueue(logEvent); if (queueWasEmpty && TimeToSleepBetweenBatches <= 0) StartInstantWriterTimer(); }
/// <summary> /// Adds the log event to asynchronous queue to be processed by /// the lazy writer thread. /// </summary> /// <param name="logEvent">The log event.</param> /// <remarks> /// The <see cref="Target.PrecalculateVolatileLayouts"/> is called /// to ensure that the log event can be processed in another thread. /// </remarks> protected override void Write(AsyncLogEventInfo logEvent) { this.MergeEventProperties(logEvent.LogEvent); this.PrecalculateVolatileLayouts(logEvent.LogEvent); this.RequestQueue.Enqueue(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; int tryCounter = 0; int targetToInvoke; continuation = ex => { if (ex == null) { // success lock (this.lockObject) { if (this.currentTarget != 0) { if (this.ReturnToFirstOnSuccess) { InternalLogger.Debug("Fallback: target '{0}' succeeded. Returning to the first one.", this.Targets[this.currentTarget]); this.currentTarget = 0; } } } logEvent.Continuation(null); return; } // failure lock (this.lockObject) { InternalLogger.Warn("Fallback: target '{0}' failed. Proceeding to the next one. Error was: {1}", this.Targets[this.currentTarget], ex); // error while writing, go to the next one this.currentTarget = (this.currentTarget + 1) % this.Targets.Count; tryCounter++; targetToInvoke = this.currentTarget; if (tryCounter >= this.Targets.Count) { targetToInvoke = -1; } } if (targetToInvoke >= 0) { this.Targets[targetToInvoke].WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); } else { logEvent.Continuation(ex); } }; lock (this.lockObject) { targetToInvoke = this.currentTarget; } this.Targets[targetToInvoke].WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
/// <summary> /// Writes an array of logging events to the log target. By default it iterates on all /// events and passes them to "Write" method. Inheriting classes can use this method to /// optimize batch writes. /// </summary> /// <param name="logEvents">Logging events to be written out.</param> protected override void Write(AsyncLogEventInfo[] logEvents) { InternalLogger.Trace("Writing {0} events", logEvents.Length); for (int i = 0; i < logEvents.Length; ++i) { logEvents[i].Continuation = CountedWrap(logEvents[i].Continuation, this.Targets.Count); } foreach (var t in this.Targets) { InternalLogger.Trace("Sending {0} events to {1}", logEvents.Length, t); t.WriteAsyncLogEvents(logEvents); } }