Saturday, March 7, 2009

Sending SMS alerts with Log4j using ipipi.com

In the post “Sending Email alerts with Log4j” and in the post “Sending Email alerts with Log4j – Controlled Alerts” I wrote about a simple way of sending email alerts using the ready log4j appender SMTPAppender. But, there are times in which an organization wants to send system alerts directly to a cell phone, in order to be notified about a problem as soon as possible.

ipipi.com is SMS service allowing sending SMS messages to almost every cell phone in the world. There is a support for sending SMS messages over SMTP protocol. Extending log4j SMTP appender to send SMS alert messages is easy task.

There is only one thing important to notice: Sending error message as SMS has to be much shorter than sending email. SMS messages can have very few characters. For this reason log4j SMTP appender has to be altered in order to send only the error string written to the log and the first line from the exception stack trace. This is done in the following class: FilteredShortSMTPAppender. Note that this class extends BaseFilteredSMTPAppender from the post “Sending Email alerts with Log4j – Controlled Alerts”:

import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.helpers.LogLog;
import java.util.Date;
import javax.mail.Multipart;
import javax.mail.Transport;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeBodyPart;

public class FilteredShortSMTPAppender extends BaseFilteredSMTPAppender {
  @Override
  public void activateOptions()
  {
    super.activateOptions();
    setBufferSize(1);
  }

  @Override
  protected void sendBuffer() {
    cleanTimedoutExceptions();
    if (isSendMailAllowed()) {
      try {
        MimeBodyPart part = new MimeBodyPart();
        StringBuffer sbuf = new StringBuffer();
        String t = layout.getHeader();
        if (t != null) {
          sbuf.append(t);
        }
        LoggingEvent event = cb.get();
        sbuf.append(layout.format(event));
        if (layout.ignoresThrowable()) {
          String[] s = event.getThrowableStrRep();
          if (s != null && s.length > 0) {
            sbuf.append(s[0]);
        }
        t = layout.getFooter();
          }
        if (t != null) {
          sbuf.append(t);
        }
        part.setContent(sbuf.toString(), layout.getContentType());
        Multipart mp = new MimeMultipart();
        mp.addBodyPart(part);
        msg.setContent(mp);
        msg.setSentDate(new Date());
        Transport.send(msg);
        addException();
      }
      catch (Exception e) {
        LogLog.error("Error occured while sending e-mail notification.", e);
      }
    }
  }
}

The class FilteredShortSMTPAppender allows to send email alerts in a short version. It can be used exactly the same as FilteredSMTPAppender, besides the parameter: BufferSize is no longer needed, since we do not send log history with the mail message.

After we have the class FilteredShortSMTPAppender we can easily extend it to send SMS email alerts over SMTP using the ipipi.com service:

import org.apache.log4j.helpers.LogLog;
import java.io.IOException;
import java.util.Properties;

public final class IPIPISmsOverSmtpAppender extends FilteredShortSMTPAppender {
  private static final String KEY_HOST = "host";
  private static final String TO_SERVER = "to.server";
  private String toServer;

  @Override
  public void activateOptions() {
    Properties properties = new Properties();
    try {
      properties.load(IPIPISmsOverSmtpAppender.class.getResourceAsStream("ipipi.properties"));
      setSMTPHost(properties.getProperty(KEY_HOST));
      setFrom(getSMTPUsername() + "@" + getSMTPHost());
      toServer = properties.getProperty(TO_SERVER);
      setTo(parseAddress(getTo()));  
    }
    catch (IOException ioe) {
      LogLog.error("Failed loading IPIPI service properties", ioe);
    }
    super.activateOptions();
  }

  private String parseAddress(String addressStr) {
    String[] addresses = addressStr.split(",");
    StringBuffer sb = new StringBuffer();
    for (String address : addresses) {
      sb.append(address).append("@").append(toServer).append(",");
    }
    return sb.substring(0, sb.length() - 1);
  }
}
Note that the information regarding the ipipi.com service is on external file named ipipi.properties. This file should be located on the same package as the IPIPISmsOverSmtpAppender class:
host=ipipi.com
to.server=sms.ipipi.com
This class extends the capabilities of the class FilteredShortSMTPAppender to allow adding cell phone numbers instead of email addresses. In your appender configuration file you can simply insert cell phone numbers and this code will know to convert the cell phone numbers to email addresses used for ipipi.com convention. The service allows sending SMS message to almost any cell phone on the planet by using the cell phone owner as the email address prefix. for example, you can simply send SMS message to a cell phone by emailing to: 972541234567@ipipi.com. Of course, that the service costs money, and in order to send SMS messages you must first register to the service and buy a package of SMS messages. Your registered username and password is used as login details for ipipi.com SMTP server.

This is an example of the IPIPISmsOverSmtpAppender log4j configuration:

log4j.rootLogger=INFO, a, sms
log4j.appender.a=org.apache.log4j.ConsoleAppender
log4j.appender.a.layout=org.apache.log4j.PatternLayout
log4j.appender.a.layout.ConversionPattern=%d{HH:mm:ss} %-5p [%c{1}]: %m%n
log4j.appender.sms=com.bashan.log4j.IPIPISmsOverSmtpAppender
log4j.appender.sms.SMTPUsername=bashan
log4j.appender.sms.SMTPPassword=bashan
log4j.appender.sms.TimeFrame=10
log4j.appender.sms.MaxEMails=30
log4j.appender.sms.To=972541234567,972542345678
log4j.appender.sms.layout=org.apache.log4j.PatternLayout
log4j.appender.sms.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n
Note for few things:
  • Phone numbers must contain country prefix.
  • TimeFrame and MaxEMails parameters from the class: FilteredSMTPAppender exist on this appender as well.
  • BufferSize parameter is no longer used.

No comments:

Post a Comment