Log4j 自定义电子邮件附加器制作无限循环链

问题描述 投票:0回答:1

问题:如何防止错误日志调用相同的追加方法来停止无限循环,从而导致应用程序停止工作。

分析:由于AppenderClass中的append方法不是线程安全的,所以创建了单独的线程来发送电子邮件。但如果电子邮件由于异常而失败,请尝试打印 log.error 消息,该消息创建记录器事件并再次调用追加方法,该方法再次创建新线程。结果,循环无限循环开始并使用所有系统资源。

已经尝试过

  1. 尝试使用Executor Service,但由于错误日志循环,它继续使用所有线程并进入无限循环。

  2. 如果我将错误更改为警告或其他级别,则没有问题。但想打印错误日志。 (有效,但未满足要求。)

  3. 如果不创建新线程,那么它在多线程环境中再次工作,它再次失败。 (有效,但未满足要求。)

@Plugin(name = EmailErrorsAppender.PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
public class EmailErrorsAppender extends AbstractPropertiesAwareAppender
{
......

@Override
public void append(LogEvent event)
{
    try
    {
           this.sendEmailInThread(recipients, filter.getRecipientType(), subject, filter.createEmailContentFromEvent(event));
     }catch(Throwable t){
        logger.error("Failed to send error email.", t);
     }
}

protected void sendEmailInThread(final List<String> destinationAddresses, final Message.RecipientType recipientType,final String subject, final String body)
   {
      final String mailHost = this.getMailHost();
      final String fromAddress = this.getFromAddress();
      final EmailMessageConverter messageConverter = this.messageConverter;

    if(messageConverter == null || StringUtils.isBlank(mailHost) || StringUtils.isBlank(fromAddress))
        throw new IllegalStateException("The message converter, mail host and from address are required to send " +
                                        "an email. Please consult the documentation for more information.");

    Thread emailThread = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            Message message =null;
            try
            {
                Properties properties = new Properties();
                properties.put("mail.smtp.host", mailHost);

                Session session = Session.getDefaultInstance(properties, null);
                properties = session.getProperties();
                properties.put("mail.smtp.host", mailHost);

                message = new MimeMessage(session);
                message.setFrom(new InternetAddress(fromAddress));

                for(String address : destinationAddresses)
                    message.addRecipient(recipientType, new InternetAddress(address));

                message.setSubject(subject);
                message.setSentDate(new Date());

                messageConverter.addBodyToMessagePart(body, message);

                try
                {
                    Transport.send(message);
                }
                catch(MessagingException e1)
                {
                    logger.error("Failed to send email on first try. Waiting 10 seconds and trying once more."+ e1);
                    Thread.sleep(10000);
                }
            }
            catch(MessagingException | InterruptedException e)
            {
                try
                {

                    Transport.send(message);
                }
                catch(MessagingException e3)
                {
                    logger.error("Failed to send email on second try. Will not try again.", e3);
                }
            }
        }

    });
    emailThread.start();
}

......

}

是否可以停止再次调用append方法的错误日志,append将再创建一个线程并以1000s线程创建和系统消失而结束。

java multithreading log4j2 appender infinite-recursion
1个回答
0
投票

我还没测试过。

使用异步和缓冲区附加器

<Configuration status="WARN">
    <Appenders>
        <!-- Define SMTP Appender -->
        <SMTP name="EmailAppender" subject="Log Alert"
              to="[email protected]"
              from="[email protected]"
              smtpHost="smtp.example.com"
              smtpPort="25">
            <PatternLayout>
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
        </SMTP>

        <!-- Define Buffer Appender -->
        <BufferingForwardingAppender name="BufferedEmailAppender" bufferSize="10">
            <AppenderRef ref="EmailAppender"/>
        </BufferingForwardingAppender>

        <!-- Define Async Appender -->
        <Async name="AsyncBufferedEmailAppender">
            <AppenderRef ref="BufferedEmailAppender"/>
        </Async>
    </Appenders>

    <Loggers>
        <Root level="error">
            <AppenderRef ref="AsyncBufferedEmailAppender"/>
        </Root>
    </Loggers>
</Configuration>

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.