Syslog: Sending Java SLF4J/Logback to Syslog

logback-logoSLF4J, the Simple Logging Facade for Java, is a popular front for various logging backends, one of the being Logback.  With the advent of containerization, using syslog to send data to remote logging infrastructure has become a popular transport method.

Enable Syslog Input

The first step is to enable the receipt of syslog messages.  This could be any server listening for syslog messages. You can follow my previous article on configuring an Ubuntu server to receive RFC5424 compatible messages or you can configure a syslog input in Logstash.

Java Test Program

Now we need a sample Java sample program to send log messages as well as exception stack traces to logback.  As designed, the SLF4J interfaces are all that we import and interact with, while the backend implementation will be Logback.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestLogback {
    
    static final Logger logger = LoggerFactory.getLogger(TestLogback.class);
    
    public static void main(String[] args) throws Exception
      {
         logger.debug("debug message slf4j");
         logger.info("info message slf4j");
         logger.warn("warn message slf4j");
         logger.error("error message slf4j");
         try {
             int i = 1/0;
         }catch(Exception exc) {
             logger.error("error message with stack trace slf4j",
                     new Exception("I forced this exception",exc));
         }
      }    

}

You will need to have slf4j-api-<version>.jar, logback-core-<version>.jar, and logback-classic-<version>.jar on the classpath in order to compile and run the program above.

In addition to the jars, you will need the following resource file named “logback.xml” in the classpath.

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
    </layout>
  </appender>
  
    <appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>myhost</syslogHost>
        <facility>LOCAL0</facility>
        <port>514</port>
        <!-- include %exception in message instead of allowing default multiline stack trace -->
        <throwableExcluded>true</throwableExcluded>
        <suffixPattern>testlogback %m thread:%t priority:%p category:%c exception:%exception</suffixPattern> 
    </appender>  
  
  <root level="debug">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="SYSLOG" />
  </root>
</configuration>

The raw data sent will look something like below:

<135>Oct 17 06:37:55 myhost testlog4j debug message slf4j thread:main priority:DEBUG category:TestLogback exception:

<134>Oct 17 06:37:55 myhost testlog4j info message slf4j thread:main priority:INFO category:TestLogback exception:

<132>Oct 17 06:37:55 myhost testlog4j warn message slf4j thread:main priority:WARN category:TestLogback exception:

<131>Oct 17 06:37:55 myhost testlog4j error message slf4j thread:main priority:ERROR category:TestLogback exception:

<131>Oct 17 06:37:55 myhost testlog4j error message with stack trace slf4j thread:main priority:ERROR category:TestLogback exception:java.lang.Exception: I forced this exception at TestLogback.main(TestLogback.java:20) Caused by: java.lang.ArithmeticException: / by zero at TestLogback.main(TestLogback.java:17)

With this ability to send your Java debug logs through syslog, you can now feed centralized logging solutions such as Logstash.

 

REFERENCES

http://logback.qos.ch/manual/appenders.html

https://www.loggly.com/docs/java-logback-syslog/

https://examples.javacodegeeks.com/enterprise-java/logback/logback-syslog-example/