13

I'm trying to use log4j to send emailable reports that contain the logging statements from a background process. I want one email sent for each process run, not one email for each logging statement. I've looked at the SMTPAppender, but don't see a way to manually send the report when the process completes. I believe the TriggeringEventEvaluator may be the key, but one issue I'm running into is how to get a handle to the TriggeringEventEvaluator instance. I'm stuck using log4j 1.2.14 and the SMTPAppender.getEvaluator() method was introduced in 1.2.15. Any thoughts? Am I even on the right track? Does the SMTPAppender.close() method come into play here?

I want to be able to do this:

log.info(message1);
log.info(message2);
log.info(message3);
log.sendMail();

After thinking about this some more, I think I need to clarify what I'm hoping to accomplish. I'm trying to capture the logging from running a quartz job and send the resulting log as an email. The quartz job makes a bunch of service method calls into various services. I want the to include any logging those service methods perform as well as the logging of the quartz jobs itself. I was thinking I could do something like the following for capturing all the logging, but it isn't working.

// at the beginning of quartz job
Logger logger = Logger.getRootLogger();
StringWriter sw = new StringWriter();
WriterAppender wa = new WriterAppender(new SimpleLayout(), sw);
logger.addAppender(wa);

// at the end of the quartz job 
String report = sw.toString();
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
fmpdmb
  • 1,370
  • 3
  • 21
  • 34

3 Answers3

20

You shouldn't use any of log4j's methods, you should configure it properly instead.

First of all, define in your log4j.properties file your appender properly:

#CONFIGURE SMTP
log4j.appender.email=org.apache.log4j.net.SMTPAppender
log4j.appender.email.SMTPHost=mail.mydomain.com
log4j.appender.email.SMTPUsername=myuser@mydomain.com
log4j.appender.email.SMTPPassword=mypw
log4j.appender.email.From=myuser@mydomain.com
log4j.appender.email.To=myuser@mydomain.com
log4j.appender.email.Subject=Log of messages
log4j.appender.email.BufferSize=1
log4j.appender.email.EvaluatorClass=TriggerLogEvent
log4j.appender.email.layout=org.apache.log4j.PatternLayout
log4j.appender.email.layout.ConversionPattern=%m

Note: code taken from this post. More information can be obtained in SMTPAppender API.

Next, make a special class that will be used just for sending email. Example:

package com.foo.mailer;
import org.apache.log4j.Logger;

public class Mailer {
   private static final Logger logger = Logger.getLogger(Mailer.class);

   public void logMail(String mailString) {
      logger.info(mailString);
   }
}

Next, put in log4j.properties configuration for this class:

# INFO level will be logged
log4j.logger.com.foo.mailer = INFO, email
# turn off additivity
log4j.additivity.com.foo.mailer = false

Now, whenever you want to send an email using log4j, put this in your code:

new Mailer().logMail("This mail should be sent");

Disclaimer: I haven't tested any of this code.

Community
  • 1
  • 1
darioo
  • 46,442
  • 10
  • 75
  • 103
  • in above log4j properties, we can send email for only INFO statements only right. it means if I have some debug stmts, it won't include those statements in the email right ? – mahesh Feb 05 '14 at 16:44
  • 1
    I am not sure the use of a `Mailer` class with a `logMail()` method is the way... This does not leave the choice of delivery to the user running the software, nor the software have a guarantee that these log messages will be delivered by email if log4j is not configured accordingly. I see more log4j methods (.debug(), .info(), ...) as an delivery-agnostic system, then you use the log4j configuration to perform a filtering and pick you delivery method (file, email, ...) that suits you. – Julien Sep 08 '15 at 07:00
5

If you are using an XML configuration file, the following should be helpful.

<appender name="ErrorEmailAppender" class="org.apache.log4j.net.SMTPAppender">
    <param name="SMTPHost" value="mail.mydomain.com" />
    <param name="SMTPUsername" value="myuser@mydomain.com" />
    <param name="SMTPPassword" value="password" />
    <param name="From" value="myuser@mydomain.com" />
    <param name="To" value="myuser@mydomain.com" />
    <param name="Subject" value="Log of messages" />
    <param name="BufferSize" value="1" />
    <param name="EvaluatorClass" value="TriggerLogEvent" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%t %m%n"/>
    </layout>
</appender>

<logger name="com.foo.mailer">
    <level value="INFO" />
    <appender-ref ref="ErrorEmailAppender"/>
</logger>
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
1

Log4j 2.x onwards, the following configuration for log4j.xml can be used. It's pretty straightforward and can be used to send emails.

You need to edit it and enter your smtp host, username, password, port and subject.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>

        <SMTP>
            <name>Mail1</name>
            <subject>SUBJECT</subject>
            <to>TO_EMAIL</to>
            <from>FROM_EMAIL</from>
            <smtpHost>smtp.gmail.com</smtpHost>
            <smtpPort>487</smtpPort>
            <ignoreExceptions>false</ignoreExceptions>
            <smtpUsername>username</smtpUsername>
            <smtpPassword>password</smtpPassword>
            <smtpProtocol>smtps</smtpProtocol>
            <HtmlLayout charset="UTF-8" locationInfo="true" />
            <ThresholdFilter level="ERROR"/>
        </SMTP>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Mail1"/>
        </Root>
    </Loggers>
</Configuration>

Reference: Log4j SMTP Appender

PIYUSH CHUGH
  • 304
  • 4
  • 15