Extremely slow operation and log4net


I’m currently profiling a web application, and I noticed that for some combination of input, a specific search into the database is really really slow. After verifying that the query is not responsible for this problem I fire a profiler, load the page, issue the search and then verify with ant profiler the method that need more time to be executed. The result was that the method that needs more time to be executed is one called Send Alert, that simply logs with log4net to a specific logger called Alert.

I noticed a lot of SocketException, so I verify the configuration, and find that the Alert logger has a reference to a SmtpAppender that points to a wrong smtp server. The page was slow because it is waiting to send an alert with a wrong mailserver, then it waits for timeout before proceeding on.

Ok, this is a configuration problem, but I do not want my email alert to be sent synchronously, because there is no point in slowing the application if I need to send an alert. Remember that sending an E-Mail is a slow operation even if the smtp is ok. In this situation Log4Net has a specific appender called AsyncAppender that can be used to solve this problem. The AsyncAppender is a specific appender that is used to wrap any other appender, and make the log asyncronous. The only part I need to change is to add this to configuration

   1: <appender name="AsyncSmtpAppender"

   2: type="SampleAppendersApp.Appender.AsyncAppender,SampleAppendersApp">

   3:   <appender-ref ref="SmtpAppender" />

   4: </appender>

and use the AsyncSmtpAppender in logger definition.

   1: <logger name="Alerter" additivity="false">

   2:     <level value="WARN" />

   3:     <appender-ref ref="AsyncSmtpAppender" />

   4: </logger>

Then I reload the page again, and now, even with a wrong smtp server, the page loads almost instantaneously.


Difference in log4net between threshold and evaluator

In log4net configuration you can filter out event by level in almost any appender, since it is supported by the AppenderSkeleton, the base class for every appender.

<appender name="GeneralLog" type="log4net.Appender.RollingFileAppender">
    <file value="Logs/exception.txt" />
    <appendToFile value="true" />
    <maximumFileSize value="10000KB" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="5" />
    <threshold value="ERROR"/>

Sometimes I see different configuration that uses an evaluator.

<evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="ERROR"/>

If you think that this is the same as before you are wrong. This setting is supported by all appenders that inherit from BufferingAppenderSkeleton, basically the above configuration tells the buffered appender to flush the buffer if an error of level “ERROR” is logged, this is expecially useful to have an immediate log of errors of the application.