Skip to content

How to write a custom async target

Rolf Kristensen edited this page Nov 11, 2024 · 24 revisions

Introduced with NLog 4.6

It is really easy:

  • Create a class that inherits from NLog.Targets.AsyncTaskTarget
  • Override the WriteAsyncTask(LogEventInfo logEvent, CancellationToken token) method.
  • In the body of this method invoke this.RenderLogEvent(this.Layout, logEvent) to get the message text, and invoke this.GetAllProperties(logEvent) to get structured properties.

⚠️ Don't forget to register your custom component when loading NLog config!

Example

using NLog;
using NLog.Config;
using NLog.Targets;
 
namespace MyNamespace 
{ 
    [Target("MyFirst")] 
    public sealed class MyFirstTarget : AsyncTaskTarget
    { 
        public MyFirstTarget()
        {
            this.IncludeEventProperties = true; // Include LogEvent Properties by default
        }
 
        [RequiredParameter] 
        public Layout Host { get; set; } = "localhost";
 
        protected override Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
        { 
            string logMessage = this.RenderLogEvent(this.Layout, logEvent); 
            string hostName = this.RenderLogEvent(this.Host, logEvent); 
            IDictionary<string,object> logProperties = this.GetAllProperties(logEvent);
            return SendTheMessageToRemoteHost(hostName, logMessage, logProperties); 
        } 
 
        private async Task SendTheMessageToRemoteHost(string hostName, string message, IDictionary<string, object> properties) 
        { 
            // TODO - write me 
        } 
    } 
}

AsyncTaskTarget Features

AsyncTaskTarget has an internal queue (Initial capacity is 10000), so if the Tasks constantly performs timeout then at one point the queue will be filled. The OverflowAction will then take over (Default = Discard to avoid eating all memory).

Timeout and Retry Logic

There are several options:

  • TaskTimeoutSeconds - How many seconds a Task is allowed to run before it is cancelled (Default 150 secs)
  • RetryDelayMilliseconds - How many milliseconds to wait before next retry (Default 500ms, and will be doubled on each retry).
  • RetryCount - How many attempts to retry the same Task, before it is aborted (Default 0)

If wanting to have more control of when to retry (Checking the Exception), or perform connection recovery on failure, then override this method:

protected override bool RetryFailedAsyncTask(Exception exception,
                                             CancellationToken cancellationToken,
                                             int retryCountRemaining,
                                             out TimeSpan retryDelay)
{
   return base.RetryFailedAsyncTask(exception,
                                    cancellationToken,
                                    retryCountRemaining,
                                    out retryDelay); // Default behavior
}

Batch Logic

Activated when overriding this method:

protected override Task WriteAsyncTask(IList<LogEventInfo> logEvents, CancellationToken cancellationToken)
{
   // TODO - write batch
}

There are several options:

  • BatchSize - Gets or sets the number of log events that should be processed in a batch by the lazy writer thread. (Default 1)
  • TaskDelayMilliseconds - How many milliseconds to delay the actual write operation to optimize for batching (Default 1 ms)
  • QueueLimit - Gets or sets the limit on the number of requests in the lazy writer thread request queue (Default 10000)
  • OverflowAction - Gets or sets the action to be taken when the lazy writer thread request queue count exceeds the set limit (Default Discard).

TargetWithContext Features

AsyncTaskTarget inherits the TargetWithContext features, that allows one to configure additional context properties for extended structured logging capabilities.

<target type="MyFirst" name="first" includeEventProperties="true">
   <contextproperty name="MachineName" layout="${machinename}" />
   <contextproperty name="ThreadId" layout="${threadid}" />
</target>

The structured properties can be retrieved inside WriteAsyncTask-method by calling this.GetAllProperties(logEvent).

Clone this wiki locally