0

我正在尝试使用LogbackwithSMTPAppender作为我的日志记录解决方案。我有一个附加的评估器,appender它会触发每记录 100 个错误发送一封电子邮件。在大多数情况下,这可以正常工作,但我注意到如果我在循环中快速创建错误以触发多封电子邮件,则只会发送最后一封具有正确内容的电子邮件。这似乎是一个竞争条件,第一封电子邮件没有完成创建/发送,第二封邮件在创建时覆盖了第一封邮件。有没有其他人经历过这个或找到解决方案。我的 logback 配置附在下面。

<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>

这是评估者:

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;
        }
    }
}

任何帮助是极大的赞赏。

4

2 回答 2

1

问题是 SMTPAppender 的 asynchronousSending 属性默认为 true。我将其设置为 false 并且它可以正常工作

于 2014-03-13T15:34:09.327 回答
0

您应该使您的 Evaluator 线程安全 - 例如使用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;
        }
    }

}
于 2016-10-28T11:32:55.153 回答