• 0.11

Using syslogd at Amazon Elastic Beanstalk

The best way to monitor your running Elastic Beanstalk environments is through the runtime logs produced by EC2 instances and your running Java applications. We recommend to use SLF4J (in combination with com.jcabi:jcabi-log) as a logging facade and Apache log4j as logging facility. Add these three dependencies to your pom.xml:

<dependencies>
  <dependency>
    <groupId>com.jcabi</groupId>
    <artifactId>jcabi-log</artifactId>
    <version>${jcabi.version}</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.2</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
    <scope>runtime</scope>
  </dependency>
</dependencies>

That's all you need to start logging events in your Java classes (read more about com.jcabi.log.Logger):

public class Foo {
  public void bar() {
    Logger.info(this, "something just happened...");
  }
}

The logging event produced by that info() call to com.jcabi.log.Logger will be forwarded to log4j through SLF4J. Now you should inform LOG4J runtime engine about the syslog, as a logging destination. Create a log4j.properties file in src/main/resources directory of your project:

log4j.rootLogger=INFO, SYSLOG
log4j.appender.SYSLOG=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG.facility=user
log4j.appender.SYSLOG.facilityPrinting=true
log4j.appender.SYSLOG.header=true
log4j.appender.SYSLOG.syslogHost=localhost
log4j.appender.SYSLOG.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG.layout.ConversionPattern=[%p] %t %c: %m%n

Now log4j knows that all logging events received from SLF4J should be forwarded to the locally running syslog service (via UDP port 514).

Now the most important step is to instruct Elastic Beanstalk engine how to configure locally running syslogd daemon at every EC2 instance, on reboot. The only and the best way to do it is through one of ebextensions (read more about them here). Create a syslog.config file in src/main/ebextensions:

commands:
  01-set-correct-hostname:
    command: hostname www.example.com
  02-forward-rsyslog-to-papertrail:
    command: |
      grep -v papertrailapp.com /etc/rsyslog.conf \
        | echo "*.* @logs.papertrailapp.com:55555" > /etc/rsyslog.conf
  03-enable-remote-logging:
    command: |
      echo -e "\$ModLoad imudp\n\$UDPServerRun 514\n\$ModLoad imtcp\n\$InputTCPServerRun 514" \
        >> /etc/rsyslog.conf
  04-enable-FQDN:
    command: |
      echo -e "\$EscapeControlCharactersOnReceive off\n\$PreserveFQDN on" \
        | cat - /etc/rsyslog.conf \
        > /tmp/rsyslog.conf \
        && mv /tmp/rsyslog.conf /etc/rsyslog.conf
  05-restart-syslog:
    command: service rsyslog restart

Replace 55555 with the UDP port number provided by papertrailapp.com.

Package this ebs-volume.config file as suggested here.

As you see in the syslog.config file above, we are using papertrailapp.com as a collector of log events. We recommend to use this platform as one of the best in the market.

Update: You can also specify host name and port right inside you log4j.properties, which is a more elegant and preferred way:

log4j.appender.SYSLOG.syslogHost=localhost:55555