protected override void Write(AsyncLogEventInfo logEvent) { Assert.True(FlushCount <= WriteCount); pendingWriteCounter.BeginOperation(); ThreadPool.QueueUserWorkItem( s => { try { Interlocked.Increment(ref WriteCount); if (ThrowExceptions) { logEvent.Continuation(new InvalidOperationException("Some problem!")); logEvent.Continuation(new InvalidOperationException("Some problem!")); } else { logEvent.Continuation(null); logEvent.Continuation(null); } } finally { pendingWriteCounter.CompleteOperation(null); } }); }
/// <summary> /// Writes the log to the target. /// </summary> /// <param name="logEvent">Log event to write.</param> public void WriteAsyncLogEvent(AsyncLogEventInfo logEvent) { if (!IsInitialized) { lock (SyncRoot) { logEvent.Continuation(null); } return; } if (_initializeException != null) { lock (SyncRoot) { logEvent.Continuation(CreateInitException()); } return; } var wrappedContinuation = AsyncHelpers.PreventMultipleCalls(logEvent.Continuation); var wrappedLogEvent = logEvent.LogEvent.WithContinuation(wrappedContinuation); WriteAsyncThreadSafe(wrappedLogEvent); }
/// <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; } var wrappedContinuation = AsyncHelpers.PreventMultipleCalls(logEvent.Continuation); try { this.Write(logEvent.LogEvent.WithContinuation(wrappedContinuation)); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } wrappedContinuation(exception); } } }
/// <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}", this.WrappedTarget, ex, retryNumber, this.RetryCount); // exceeded retry count if (retryNumber >= this.RetryCount) { InternalLogger.Warn("Too many retries. Aborting."); logEvent.Continuation(ex); return; } // sleep and try again Thread.Sleep(this.RetryDelayMilliseconds); this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }; this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
/// <summary> /// Writes a log event to the log target, in a thread safe manner. /// </summary> /// <param name="logEvent">Log event to be written out.</param> protected virtual void WriteAsyncThreadSafe(AsyncLogEventInfo logEvent) { lock (SyncRoot) { if (!IsInitialized) { // In case target was Closed logEvent.Continuation(null); return; } try { Write(logEvent); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } logEvent.Continuation(exception); } } }
/// <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="Targets"/>. /// </remarks> protected override void Write(AsyncLogEventInfo logEvent) { AsyncContinuation continuation = null; int tryCounter = 0; int targetToInvoke = 0; 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[targetToInvoke]); _currentTarget = 0; } } } logEvent.Continuation(null); return; } // failure lock (_lockObject) { InternalLogger.Warn(ex, "Fallback: target '{0}' failed. Proceeding to the next one.", Targets[targetToInvoke]); // error while writing, go to the next one _currentTarget = (targetToInvoke + 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)); }
protected override void Write(AsyncLogEventInfo logEvent) { try { //make sure the buffer isn't overflowing //if it is skip since we can't do anything with the message if (StackifyLib.Logger.PrefixEnabled() || _logClient.CanQueue()) { var logMsg = Translate(logEvent.LogEvent); if (logMsg != null) { _logClient.QueueMessage(logMsg); } logEvent.Continuation(null); // Signal success to NLog } else { InternalLogger.Warn("StackifyTarget: Cannot send because queue is full"); logEvent.Continuation(new OperationCanceledException("StackifyTarget: Cannot send because queue is full")); // Signal failure to NLog StackifyAPILogger.Log("Unable to send log because the queue is full"); } } catch (Exception ex) { InternalLogger.Error("StackifyTarget: Failed to send"); logEvent.Continuation(ex); // Signal failure to NLog StackifyAPILogger.Log(ex.ToString()); } }
protected override void Write(AsyncLogEventInfo logEvent) { if (this.ThrowExceptions-- > 0) { logEvent.Continuation(new InvalidOperationException("Some exception has occurred.")); return; } this.Events.Add(logEvent.LogEvent); logEvent.Continuation(null); }
protected override void Write(AsyncLogEventInfo logEvent) { if (ThrowExceptions-- > 0) { logEvent.Continuation(new ApplicationException("Some exception has occurred.")); return; } Events.Add(logEvent.LogEvent); logEvent.Continuation(null); }
protected override void Write(AsyncLogEventInfo info) { try { var url = new Uri(this.Url.Render(info.LogEvent)); var layout = this.Layout.Render(info.LogEvent); var json = JObject.Parse(layout).ToString(); // make sure the json is valid var client = new WebClient(); client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); UploadStringCompletedEventHandler cb = null; cb = (s, e) => { if (cb != null) { client.UploadStringCompleted -= cb; } if (e.Error != null) { if (e.Error is WebException) { var we = e.Error as WebException; try { var result = JObject.Load(new JsonTextReader(new StreamReader(we.Response.GetResponseStream()))); var error = result.GetValue("error"); if (error != null) { info.Continuation(new Exception(result.ToString(), e.Error)); return; } } catch (Exception) { info.Continuation(new Exception("Failed to send log event to ElasticSearch", e.Error)); } } info.Continuation(e.Error); return; } info.Continuation(null); }; client.UploadStringCompleted += cb; client.UploadStringAsync(url, "PUT", json); } catch (Exception ex) { info.Continuation(ex); } }
/// <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) { string address = this.Address.Render(logEvent.LogEvent); byte[] bytes = this.GetBytesToWrite(logEvent.LogEvent); if (this.KeepConnection) { NetworkSender sender = this.GetCachedNetworkSender(address); this.ChunkedSend( sender, bytes, ex => { if (ex != null) { InternalLogger.Error("Error when sending {0}", ex); this.ReleaseCachedConnection(sender); } logEvent.Continuation(ex); }); } else { var sender = this.SenderFactory.Create(address); sender.Initialize(); lock (this.openNetworkSenders) { this.openNetworkSenders.Add(sender); this.ChunkedSend( sender, bytes, ex => { lock (this.openNetworkSenders) { this.openNetworkSenders.Remove(sender); } if (ex != null) { InternalLogger.Error("Error when sending {0}", ex); } sender.Close(ex2 => { }); logEvent.Continuation(ex); }); } } }
protected override void Write(AsyncLogEventInfo info) { try { this.SendToSlack(info); info.Continuation(null); } catch (Exception e) { info.Continuation(e); } }
protected override async void Write(AsyncLogEventInfo logEvent) { try { await MyLogMethodAsync(logEvent.LogEvent).ConfigureAwait(false); logEvent.Continuation(null); } catch (Exception ex) { logEvent.Continuation(ex); } }
private bool TaskCreation(AsyncLogEventInfo logEvent) { try { if (_cancelTokenSource.IsCancellationRequested) { logEvent.Continuation(null); return(false); } if (logEvent.LogEvent == null) { InternalLogger.Debug("{0} Flush Completed", this.Name); logEvent.Continuation(null); return(false); } var newTask = WriteAsyncTask(logEvent.LogEvent, _cancelTokenSource.Token); if (newTask == null) { InternalLogger.Debug("{0} WriteAsync returned null", this.Name); } else { lock (this.SyncRoot) { _previousTask = newTask; _previousTask.ContinueWith(_taskCompletion, logEvent.Continuation, _cancelTokenSource.Token); if (_previousTask.Status == TaskStatus.Created) { _previousTask.Start(TaskScheduler.Default); } } return(true); } } catch (Exception ex) { try { InternalLogger.Error(ex, "{0} WriteAsync failed on creation", this.Name); logEvent.Continuation(ex); } catch { // Don't wanna die } } return(false); }
private Task SendAsync(CancellationToken token, TaskCompletionSource <object> tcs) { if (token.IsCancellationRequested) { tcs.SetCanceled(); return(tcs.Task); } var allSent = currentMessage == logEntries.Length; if (allSent) { asyncLogEventInfo.Continuation(null); tcs.SetResult(null); return(tcs.Task); } try { PrepareMessage(); messageTransmitter .SendMessageAsync(buffer, token) .ContinueWith(t => { var exception = t.Exception; if (token.IsCancellationRequested || t.IsCanceled) { tcs.SetCanceled(); return; } if (exception != null) { asyncLogEventInfo.Continuation(exception.GetBaseException()); tcs.SetException(exception); return; } SendAsync(token, tcs); }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); return(tcs.Task); } catch (Exception exception) { tcs.SetException(exception); return(tcs.Task); } }
protected override void Write(AsyncLogEventInfo logEvent) { var output = Layout.Render(logEvent.LogEvent); writer.WriteLineAsync(output) .ContinueWith(task => logEvent.Continuation(task.Exception)); }
/// <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) { var buckets = logEvents.BucketSort(c => BuildConnectionString(c.LogEvent)); try { foreach (var kvp in buckets) { for (int i = 0; i < kvp.Value.Count; i++) { AsyncLogEventInfo ev = kvp.Value[i]; try { WriteEventToDatabase(ev.LogEvent); ev.Continuation(null); } catch (Exception exception) { // in case of exception, close the connection and report it InternalLogger.Error(exception, "Error when writing to database."); if (exception.MustBeRethrownImmediately()) { throw; } InternalLogger.Trace("DatabaseTarget: close connection because of exception"); CloseConnection(); ev.Continuation(exception); if (exception.MustBeRethrown()) { throw; } } } } } finally { if (!KeepConnection) { InternalLogger.Trace("DatabaseTarget: close connection because of KeepConnection=false"); CloseConnection(); } } }
/// <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 WriteAsyncThreadSafe(AsyncLogEventInfo logEvent) { lock (this.RetrySyncObject) { 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}", this.WrappedTarget, ex, retryNumber, this.RetryCount); // exceeded retry count if (retryNumber >= this.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 < this.RetryDelayMilliseconds;) { int retryDelay = Math.Min(100, this.RetryDelayMilliseconds - i); Thread.Sleep(retryDelay); i += retryDelay; if (!IsInitialized) { InternalLogger.Warn("Target closed. Aborting."); logEvent.Continuation(ex); return; } } this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }; this.WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); } }
/// <summary> /// Calls the specified Method. /// </summary> /// <param name="parameters">Method parameters.</param> /// <param name="logEvent">The logging event.</param> protected override void DoInvoke(object[] parameters, AsyncLogEventInfo logEvent) { try { ExecuteLogMethod(parameters, logEvent.LogEvent); logEvent.Continuation(null); } catch (Exception ex) { if (ex.MustBeRethrown(this)) { throw; } logEvent.Continuation(ex); } }
/// <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 { this.Write(logEvent.LogEvent); logEvent.Continuation(null); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } logEvent.Continuation(exception); } }
private void SendToSlack(AsyncLogEventInfo info) { var message = RenderLogEvent(Layout, info.LogEvent); var webHookUrl = GetWebHookUrl(info.LogEvent); var slack = SlackMessageBuilder .Build(webHookUrl) .OnError(e => info.Continuation(e)) .WithMessage(message); if (this.ShouldIncludeProperties(info.LogEvent) || this.ContextProperties.Count > 0) { var color = this.GetSlackColorFromLogLevel(info.LogEvent.Level); Attachment attachment = new Attachment(info.LogEvent.Message) { Color = color }; var allProperties = this.GetAllProperties(info.LogEvent); foreach (var property in allProperties) { if (string.IsNullOrEmpty(property.Key)) { continue; } var propertyValue = property.Value?.ToString(); if (string.IsNullOrEmpty(propertyValue)) { continue; } attachment.Fields.Add(new Field(property.Key) { Value = propertyValue, Short = true }); } if (attachment.Fields.Count > 0) { slack.AddAttachment(attachment); } } var exception = info.LogEvent.Exception; if (!this.Compact && exception != null) { var color = this.GetSlackColorFromLogLevel(info.LogEvent.Level); var exceptionAttachment = new Attachment(null) { Color = color, Text = $"*Exception*\n```{exception}```" }; slack.AddAttachment(exceptionAttachment); } slack.Send(); }
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); } }); }
private void SignalFlushCompletionWhenIsMarker(AsyncLogEventInfo asyncLogEventInfo) { bool IsFlushCompletionMarker(AsyncLogEventInfo x) => x.LogEvent == notLoggedLogEventInfo; void SignalFlushCompletion() => asyncLogEventInfo.Continuation(null); if (IsFlushCompletionMarker(asyncLogEventInfo)) { SignalFlushCompletion(); } }
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); } }); }
private void SendToElasticSearch(AsyncLogEventInfo info) { var json = Layout.Render(info.LogEvent); var uri = GetUriFromLayout(info); var jsonClient = new SimpleElasticSearchWebClient(); jsonClient.Error += exception => info.Continuation(exception); jsonClient.PostAsync(uri, json); }
/// <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(ex, "RetryingWrapper(Name={0}): Error while writing to '{1}'. Try {2}/{3}", Name, WrappedTarget, 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); AsyncHelpers.WaitForDelay(TimeSpan.FromMilliseconds(retryDelay)); i += retryDelay; if (!IsInitialized) { InternalLogger.Warn("RetryingWrapper(Name={0}): Target closed. Aborting.", Name); logEvent.Continuation(ex); return; } } WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }; WrappedTarget.WriteAsyncLogEvent(logEvent.LogEvent.WithContinuation(continuation)); }
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); } }
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) { try { SendToElasticSearch(info); } catch (Exception ex) { info.Continuation(ex); } }
protected override void Write(AsyncLogEventInfo info) { try { Send(info); } catch (Exception e) { info.Continuation(e); } }
/// <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> /// 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> /// 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> /// 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)); }