Logback SMTPAppender only sending last email

假如想象 提交于 2019-12-11 19:19:49

问题


I am attempting to use Logback with SMTPAppender as my logging solution. I have an evaluator attached to the appender that triggers an email to be sent every 100 errors logged. For the most part this works correctly, but I've noticed if I create errors rapidly in a loop to trigger multiple emails, only the last email gets sent, with the correct content. It seems to be a race condition where the first email is not finished being created/sent, and the second one overwrites the first on creation. Has anyone else experienced this or found a solution. My logback config is attached below.

<configuration>
    <appender name="emailAppender" class="${logback.emailAppenderClass}">
       <evaluator class="com.wdp.common.logging.logback.evaluators.CountingLoggerEvaulator">
            <limit>100</limit>
        </evaluator>
        <to>${logback.emailNotificationRecipientStr}</to>
        <from>${logback.emailNotificationFromStr}</from>
        <smtpHost>${logback.smtpHost}</smtpHost>
        <subject>Logback logs for facebook-ads-processes</subject>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d [Thread:%t] %p [%c] - %m%n</pattern>
        </layout>  

            <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
            <bufferSize>${logback.cyclicBufferSize}</bufferSize>
        </cyclicBufferTracker>
    </appender>
</configuration>

This is the evaluator:

public class CountingLoggerEvaulator extends EventEvaluatorBase<ILoggingEvent> implements EventEvaluator<ILoggingEvent> {
    //if limit is not set in configuration, this will cause it to send one email for each message received.
    private int limit = 100;
    private int counter = 0;

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public int getLimit() {
        return limit;
    }

    @Override
    public boolean evaluate(ILoggingEvent expr) throws NullPointerException, EvaluationException {
        counter++;
        if (counter == limit) {
            counter = 0;
            return true;
        } else {
            return false;
        }
    }
}

Any help is greatly appreciated.


回答1:


The issue was the asynchronousSending attribute of the SMTPAppender defaults to true. I set it to false and it works properly




回答2:


You should make your Evaluator threadsafe - for example use AtomicInteger:

public class CountingLoggerEvaulator extends EventEvaluatorBase<ILoggingEvent> implements EventEvaluator<ILoggingEvent> {

    //if limit is not set in configuration, this will cause it to send one email for each message received.
    private int limit = 100;
    private AtomicInteger counter = new AtomicInteger();

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public int getLimit() {
        return limit;
    }

    @Override
    public boolean evaluate(ILoggingEvent expr) throws NullPointerException, EvaluationException {
        int curValue = counter.incrementAndGet();
        if (curValue >= limit) {
            return counter.compareAndSet(curValue, 0);
        } else {
            return false;
        }
    }

}


来源:https://stackoverflow.com/questions/22383166/logback-smtpappender-only-sending-last-email

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!