当出现异常时,我将对象发送到服务器(大约 90 个),例如端点关闭,Logback 触发自定义 STMP 附加程序,它只发送 1 封电子邮件,最大。10 个日志,然后有一个延迟,其他日志被发送。是否有可能,这start()
被调用得太频繁了?
问题:
scheduler.scheduleAtFixedRate(this::sendEmail, 1, 1L, TimeUnit.HOURS);
执行一次后不延迟,直接执行另一次,使得许多邮件在一个小时内发送出去。
我必须改变调度程序的延迟工作吗?
调试后,我注意到
Attaching appender named [EMAIL] to Logger[ROOT]
发生了两次可能是问题所在,如果是,我该如何解决?
Logback.xml 配置:
<configuration debug="true">
<!-- Logging per console and per email -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
<!-- sets the format of the output -->
%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
</Pattern>
</layout>
</appender>
<appender name="EMAIL" class="com.konverto.phonebillasaj.appenders.ScheduledSMTPAppender">
<subject>TESTING: %logger{20} - %m</subject>
<layout class="ch.qos.logback.classic.html.HTMLLayout" />
<smtpHost>smtp.xxx.net</smtpHost>
<smtpPort>587</smtpPort>
<STARTTLS>true</STARTTLS>
<username>xxx@domain.net</username>
<password>myPass</password>
<to>yyy@domain.net</to>
<from>xxx@domain.net</from>
<maxMessages>10</maxMessages>
<!-- for testing , comment in production, default 256 -->
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<!-- Send just one log entry per email, ready for a lot of emails if you put one. -->
<bufferSize>1</bufferSize>
</cyclicBufferTracker>
<!-- for testing , comment in production, default asynchronousSending = true -->
<asynchronousSending>false</asynchronousSending>
</appender>
<logger name="com.konverto.phonebillasaj" level="error" additivity="false">
<appender-ref ref="EMAIL"/>
<appender-ref ref="CONSOLE" />
</logger>
<root level="error">
<appender-ref ref="EMAIL" />
<appender-ref ref="CONSOLE" />
</root>
附加程序代码:
public class ScheduledSMTPAppender extends SMTPAppender {
private final ThreadFactory tf = r -> {
Thread t = new Thread(r, "ScheduledSMTPAppender Thread");
t.setDaemon(true); //make daemon or it will prevent your program to exit
return t;
};
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, tf);
private final List<ILoggingEvent> events = new ArrayList<>();
private int maxMessages = 10;
public ScheduledSMTPAppender() {
super();
}
public ScheduledSMTPAppender(EventEvaluator<ILoggingEvent> eventEvaluator) {
super(eventEvaluator);
}
@Override public void start() {
super.start();
scheduler.scheduleAtFixedRate(this::sendEmail, 1, 1L, TimeUnit.HOURS);
}
@Override protected void sendBuffer(CyclicBuffer<ILoggingEvent> cb, ILoggingEvent lastEventObject) {
events.add(lastEventObject);
if (events.size() > maxMessages)
{
sendEmail();
}
}
//needs to be synchronized for thread safety
private synchronized void sendEmail() {
try {
if (events.isEmpty()){
return;
}
ILoggingEvent lastEvent = events.get(events.size() - 1);
events.remove(events.size() - 1);
CyclicBuffer<ILoggingEvent> cb;
if (events.isEmpty()) {
cb = new CyclicBuffer<>(1);
} else {
cb = new CyclicBuffer<>(events.size());
for (ILoggingEvent e : events){
cb.add(e);
}
}
super.sendBuffer(cb, lastEvent);
events.clear();
} catch (Exception e) {
//Important to have a catch all here or the scheduled task will die
addError("Error occurred while sending e-mail notification.", e);
}
}
//this allows to make "maxMessages" a parameter of your appender
public int getMaxMessages() {
return maxMessages;
}
public String getContentType() {
return layout.getContentType();
}
public void setMaxMessages(int maxMessages) {
this.maxMessages = maxMessages;
}