-
Notifications
You must be signed in to change notification settings - Fork 1.4k
AsyncWrapper target
Enables asynchronous logging, so the application-thread will only have the overhead of NLog automatically capturing thread-context (Ex. ${threadid}
) and pushing to a concurrent-queue. Background timer-event using Dotnet-ThreadPool for writing pending LogEvents from the concurrent-queue to the wrapped target. It also activates batch-writing of LogEvents for even better performance.
Platforms Supported: All
<targets>
<target xsi:type="AsyncWrapper"
name="String"
queueLimit="Integer"
timeToSleepBetweenBatches="Integer"
batchSize="Integer"
overflowAction="Enum">
<target xsi:type="wrappedTargetType" ...target properties... />
</target>
</targets>
- name - Name of the target.
-
queueLimit - Limit on the number of requests the background-writer thread can have in the queue. Integer Default:
10000
-
timeToSleepBetweenBatches - Time in milliseconds to sleep between batches. Integer Default:
1
(NLog 4.6 changed default from50
to1
). When set to '0' or '1', then it will only trigger timer when something is logged (Less timer activity when idle, Faster logging and improved garbage collection behavior). -
batchSize - Number of log events that should be processed in a batch by the background-writer thread. Integer Default: 100 (NLog 4.4.2 and newer has Default: 200)
-
fullBatchSizeWriteLimit - Max number of consecutive full batchSize writes to perform within the same timer event. Integer Default: 5. Introduced in NLog 4.4.2
-
overflowAction - Action to be taken when in-memory-queue becomes full (Reached queueLimit). This means the background-writer is falling behind, and cannot keep up with the application-threads logging. Default: Discard
Possible values:- Discard - The application-thread will discard logevent to avoid becoming blocked or causing out-of-memory issues. If memory and large-object-heap usage is not an issue, then one can consider increasing queueLimit to 100.000. (Default)
- Block - The application-thread will block until the background-writer-thread has taken the next batch. Avoids loosing important logevents, but can block all application-threads. Consider to throttle active thread count, by limiting number of concurrent inbound requests.
- Grow - The application-thread will ignore the
queueLimit
, and will just allocate more memory. Can cause the entire application to experience out-of-memory-issues.
-
ForceLockingQueue - Force thread synchronization with monitor-lock, instead of using .NET ConcurrentQueue. Legacy NetFramework application will by default use monitor-lock (Default=true). .NET Standard 2.0 will by default use of the .NET lock-free ConcurrentQueue for improved concurrency (Default=false).
Introduced in NLog 4.6
Remember to Flush before application exit, is very important when enabling use of the Asynchronous target wrapper.
Asynchronous target wrapper allows the logger code to execute more quickly, by queuing messages for processing by background writer-thread. You should wrap targets that spend a non-trivial amount of time in their Write()
method with asynchronous target to speed up logging. Because asynchronous logging is quite a common scenario, NLog supports a shorthand notation for wrapping all targets with AsyncWrapper. Just add async="true"
to the <targets/>
element in the configuration file.
Example:
<targets async="true">
... your targets go here ...
</targets>
The async attribute is a shorthand for:
xsi:type="AsyncWrapper overflowAction="Discard" queueLimit="10000" batchSize="200" timeToSleepBetweenBatches="1"
So if you write a lot of messages (more then 10000) in a short time, it's possible that messages will be lost. This is intended behavior as keeping all the messages or waiting for all the messages to be written, could have impact on the performance of your program.
If you need all the log messages, then you can change from <targets async="true">
to using <default-wrapper>
:
<targets>
<default-wrapper xsi:type="AsyncWrapper" overflowAction="Block" />
... your targets go here ...
</targets>
When using the AsyncWrapper
, do write to the wrapper in your <rules>
section! In the following example: do write to
"target2". If the <logger>
is writing to "target1", the messages are not written asynchronously!
<targets>
<target name="target2" xsi:type="AsyncWrapper">
<target name ="target1" xsi:type="File"
fileName="c:/temp/test.log" layout="${message}"
keepFileOpen="true" />
</target>
<rules>
<logger name="*" minlevel="Info" writeTo="target2"/>
</rules>
</targets>
When messages are written asynchronously, then writing is performed by the background-writer-thread. There can be custom NLog targets that requires writing to happen on the application-thread for proper context capture. When used together with AsyncWrapper then asynchronous writing is used and context information can be lost.
By default all standard NLog targets supports use of AsyncWrapper. Custom NLog targets that inherits from TargetWithContext
should also by default work correctly with AsyncWrapper.
The BufferingWrapper can also be asynchronously when having configured FlushTimeout
. AsyncWrapper is intended for improving performance, where BufferingWrapper is intended for throttling or even discarding LogEvents. AsyncWrapper has an internal buffer optimized to handle many concurrent threads.
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
- Articles about NLog
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json