Reporting Application Errors by Email
Pages: 1, 2
Configuring log4j's SMTPAppender
You can configure log4j with a property file (typically, log4j.properties)
or with an XML file (typically, log4j.xml). Since log4j XML
configuration files allow for more flexibility than log4j property files, we'll
focus our attention on XML.
The log4j.xml file has a top-level element, <log4j:configuration>. Inside of the
configuration element, you will typically declare <appender> elements and
a <root> element. The following example declares three appenders and attaches the appenders to the
root logger:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{ISO8601}] %-5p %c %m %n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="DEBUG"/>
<param name="LevelMax" value="INFO"/>
</filter>
</appender>
<appender name="STDERR" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.err" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{ISO8601}] %-5p %c %m %n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="WARN"/>
<param name="LevelMax" value="FATAL"/>
</filter>
</appender>
<!-- -->
<!-- Declare the SMTPAppender -->
<!-- -->
<appender name="EMAIL" class="org.apache.log4j.net.SMTPAppender">
<param name="BufferSize" value="512" />
<param name="SMTPHost" value="smtp.foobar.com" />
<param name="From" value="log4j@server5" />
<param name="To" value="neo@foobar.com" />
<param name="Subject" value="[SMTPAppender] Application message" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{ISO8601}]%n%n%-5p%n%n%c%n%n%m%n%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="ERROR"/>
<param name="LevelMax" value="FATAL"/>
</filter>
</appender>
<!-- -->
<!-- setup log4j's root logger -->
<!-- -->
<root>
<level value="all" />
<appender-ref ref="STDOUT"/>
<appender-ref ref="STDERR"/>
<appender-ref ref="EMAIL" />
</root>
</log4j:configuration>
Each appender has a logical name. In this example, the
appender names are STDOUT, STDERR, and EMAIL. We associate the appenders to
log4j's root logger by adding three <appender-ref> declarations inside of
the <root> element. The ref attribute in the <appender-ref>
must match one of the name attributes in the <appender>
declarations.
Using nested <param> elements, you can tailor the
SMTPAppender for your environment. The SMTPAppender supports the following
parameters: From, To, Subject, SMTPHost, and BufferSize. Also, the <layout> element gives you control over the format of the body of the email message. The previous example uses org.apache.log4j.PatternLayout
to display a date, the logging level, the logger name, and the log message.
For more information about log4j configuration, consult the Apache log4j web site.
SMTPHandler for java.util.logging
Unlike log4j, java.util.logging does not include any code for sending
messages via SMTP. Fortunately, java.util.logging allows you to install custom
handler classes. The SMTPHandler project
provides a handler class named smtphandler.SMTPHandler. By installing this
class, you can achieve functionality that is similar to log4j's SMTPAppender.
The SMTPHandler class is responsible for creating the email message and sending
it to the SMTP server. Figure 3 shows its control flow.

Figure 3. java.util.logging.Logger and the SMTPHandler
Like the SMTPAppender, the SMTPHandler uses the JavaMail API to communicate with the
SMTP server. The SMTP server holds the message until it is time to deliver the
message to a mail client. Figure 4 shows an example email message
that was generated by the SMTPHandler class.

Figure 4. An email message from the SMTPHandler
Next, we'll discuss how to configure java.util.logging and how to enable the
SMTPHandler.
Configuring SMTPHandler for java.util.logging
By default, java.util.logging reads the lib/logging.properties
file in the JRE directory. You can adjust logging levels and add new handlers
by editing this property file. It is important to know that java.util.logging
requires all handler classes to be on the JVM system classpath. In order to use
the SMTPHandler class, you will need to place three JAR files on your system
classpath: the SMTPHandler JAR, the JavaMail JAR, and the JavaBeans Activation
Framework JAR.
The logging.properties file contains a handlers
property. The handlers property specifies a comma-separated list of
handler classes. The following example declares two handlers, a ConsoleHandler
and a SMTPHandler:
handlers=java.util.logging.ConsoleHandler,smtphandler.SMTPHandler
.level= FINEST
java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
smtphandler.SMTPHandler.level=WARNING
smtphandler.SMTPHandler.smtpHost=smtp.foobar.com
smtphandler.SMTPHandler.to=neo@foobar.com
smtphandler.SMTPHandler.from=appserver@server3
smtphandler.SMTPHandler.subject=[SMTPHandler] Application message
smtphandler.SMTPHandler.bufferSize=512
smtphandler.SMTPHandler.formatter=java.util.logging.SimpleFormatter
The SMTPHandler has seven customizable parameters: level, smtpHost, to, from, subject, bufferSize, and formatter. You should tailor their values as needed for your application environment.
For more information about java.util.logging configuration,
consult Sun's J2SE platform documentation.
Common Pitfalls
To get the most out of the SMTPAppender and the SMTPHandler, your application
code needs to correctly and consistently invoke the logging framework's API.
Let's suppose that your web application unexpectedly throws a runtime
exception. In a perfect world, the exception will be caught, logged using the
logging framework's API, and reported via email to all interested parties.
However, you may encounter a situation where some of the application exceptions do not trigger an email message. This usually occurs when the application fails to invoke the logging API appropriately.
Let's examine three exception-handling examples:
| Example | Code | Discussion |
| A | |
This code prints the exception message to This type of code should be avoided because the logging framework is unaware that the application encountered an error. In this scenario, the logging framework never has an opportunity to generate an email message. |
| B | |
This code prints the exception stack trace to The logging framework never receives notification about the error. The logging framework never has the opportunity to report the error. |
| C | |
This code logs an error message using the logging framework API. Example C is preferable to examples A and B. |
Your development team will need to be disciplined whenever they are writing exception-handling code. With proper exception-handling code in place, the email notification system can notify you about application errors.
Wrap-Up
We have learned about log4j's SMTPAppender and the SMTPHandler for java.util.logging.
We discussed how to configure these features in their respective logging
frameworks. With only a small amount of configuration work, your logging
framework can notify you when there is a problem in your application.
Resources
- Apache
log4jproject - Sun's java.util.logging API
- The SMTPHandler project
- Logging entry in the Javapedia
- JavaMail
- RFC 2821: The Simple Mail Transfer Protocol
- Brian Gilstrap's article, "An Introduction to the Java Logging API"
- Vikram Goyal's article, "Building Flexible Logs with
log4j" - Ruth Zamorano and Rafael Luque's article, "Instant Logging: Harness the power of
log4jwith Jabber"
Sean C. Sullivan has been developing Internet applications with Java since 1996. His recent work includes B2B web applications, various open source projects, and the development of an Internet e-commerce payment system at Intel.
Return to ONJava.com.