Log4Net is a great logging extension for the .NET EcoSystem, that also supports .NET Standard / .NET Core (which you should be using if you arent).
Unless you want to really read up on the framework extensively it can be easy to fall into some performance traps. I’ve found that in many cases these performance issues are caused by less-than-desirable appender configuration. For example lets say you have a
<appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="log-file.txt" /> <appendToFile value="true" /> <layout type="log4net.Layout.SimpleLayout" /> </appender>
When you log (assuming no other appenders are configured) your application will call into log4net, which will attempt to get a file handle, and once successful will write this to your log file, followed by releasing the lock. The point is your application is going to block on this thread whilst completing all those steps.
One solution that can be implemented easily is to just use the
You simply add this appender (which is a forwarding appender)
<appender name="BufferingForwardingAppender" type="log4net.Appender.BufferingForwardingAppender" > <bufferSize value="100"/> <appender-ref ref="FileAppender" /> <evaluator type="log4net.Core.LevelEvaluator"> <threshold value="WARN"/> </evaluator> </appender> <appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="log-file.txt" /> <appendToFile value="true" /> <layout type="log4net.Layout.SimpleLayout" /> </appender>
Now instead of writing directly to the
FileAppender you will write to the
BufferingForwardingAppender. Essentially this thread will drop your message in a queue. When that queue fills up (bufferSize) or if you log an event that will trigger the evaluator (warn) all messages will be written to the downstream appenders. In this case the FileAppender. This action will block the calling thread that triggered it, but writing 100 entries to the logfile in one action is much faster than writing 100 individual messages.