February 14, 2010

Sending Log Errors with Log4j and SMTPAppender

Log4j comes with several Appenders and if you like to send mail notification if severe errors occur the you will be pleased to see, that Log4j comes with a SMTPAppender, but there are some pitfalls when using the SMTP appender:
  • The SMTP apppender does not out of the box support a different SMTP port.
  • Using secure connection, such as SSL or TLS.
  • The derived standardized method setThreshold is ignored, and replaced with TriggeringEventEvaluator class.
Configure SMTP appender to use a different port, than the default 25
If your mailserver is configured to answer on a different port than the default 25 for SMTP, you need to configure the underlying javax.mail.Session property "mail.smtp.port". But when looking at the API for SMTPAppender you see no set method for that. What to do? Writing you own extended log4j class? No, that is not neccessary. If you look at the source code of SMTPAppender, you see the following in the createSession():

These means that SMTPAppender is reading system properties, which means you can add the following argument when starting you application.

This is a not gracefefully way, and sometimes also not applicable, because you are not in charge of the deployment environment. And what happens when you have two different application hosted on the same server, that wants to use different ports?
There is also the oppurtunity to do it programmatically:

This has also drawbacks. For examaple if your application is a J2EE application or a web application your code is not the main start class. You can of course always write a boot strap class, but what happens when you have several bootstrap classes, then things starts to get more hard to overlook for a more junior programmer.

Another way if you have problems settings the System Property is to create a class that implements the interface org.apache.log4j.spi.TriggeringEventEvaluator and there set the system properties and then in your log4j properties or xml file override the default EvaluatorClass for SMTPAppender. This is a little hacky, but it will get the work done and it keeps your code clean from log4j configuration code that should in the first place be placed in the log4j configration file.

Also what is lacking is, if you are deploying to a container you might want to define your java.mail.Session properties in the container and then bind them to JNDI, then it should be nice if Log4j could read these property from JNDI, but that is not possible.

Using Secure Connection
The next problem comes when your mailserver uses secure connection as TLS or SSL, then you need to add the following javax.mail.Session properties:

Bellow follows the source code for the example.


Thomas101 said...

Thank you. Excellent guide! Works like a dream :)

Anonymous said...

Jag upptäckte ett litet fel i ditt exempel...

Paketet du refererar till i raderna (i log4j.properties):

log4j.logger.se.msc.examples.log4j.Log4jNoSecureConnectionTest=ERROR, SMTP_NO_SECURE_CONNECTION


log4j.logger.se.msc.examples.log4j.Log4jTLSTest=ERROR, SMTP_TLS

stämmer inte överens med enhetstesterna, som ligger i paketet se.msc.example.log4j

Med det fixat så funkar det dock kanon.