Testing the log4j SyslogAppender with socat

Log4j includes a SyslogAppender which can be used to forward log messages directly to a Linux/Unix syslog daemon. This requires syslog to be configured for remote logging, by adding the -r switch to SYSLOGD_OPTIONS in /etc/sysconfig/syslog. Once configured this way, Syslog listens on UDP port 514 for log messages.

When you are developing on Windows, a local syslog daemon is not available. To provide an endpoint that simply prints messages sent from the log4j SyslogAppender to stdout, you can use socat. Start socat in UDP receive mode on port 514 like this:

$ socat stdio udp-recv:514
$    # or
$ socat - udp-recv:514

To send UDP datagrams to this emulator for testing purposes, socat can be used as well:

$ socat stdio udp:127.0.0.1:514
$    # or
$ socat - udp:127.0.0.1:514

This waits for messages on stdin. Under cygwin, sends the message, or sends the message with a terminating CRLF.

One of the differences between real syslog and this socat syslog simulator is, the real syslog interprets the number in brackets at the beginning of each message as facility.level.

Syslog facilities are defined in rfc3164 as follows:


Numerical             Facility
          Code

           0             kernel messages
           1             user-level messages
           2             mail system
           3             system daemons
           4             security/authorization messages (note 1)
           5             messages generated internally by syslogd
           6             line printer subsystem
           7             network news subsystem
           8             UUCP subsystem
           9             clock daemon (note 2)
          10             security/authorization messages (note 1)
          11             FTP daemon
          12             NTP subsystem
          13             log audit (note 1)
          14             log alert (note 1)
          15             clock daemon (note 2)
          16             local use 0  (local0)
          17             local use 1  (local1)
          18             local use 2  (local2)
          19             local use 3  (local3)
          20             local use 4  (local4)
          21             local use 5  (local5)
          22             local use 6  (local6)
          23             local use 7  (local7)

           Table 1.  syslog Message Facilities



The syslog levels are: (also in rfc3164, or see man syslog)


Numerical         Severity
          Code

           0       Emergency: system is unusable
           1       Alert: action must be taken immediately
           2       Critical: critical conditions
           3       Error: error conditions
           4       Warning: warning conditions
           5       Notice: normal but significant condition
           6       Informational: informational messages
           7       Debug: debug-level messages

           Table 2. syslog Message Severities



To convert facility.level to the integer required by syslog (quote from rfc3164):


   The Priority value is calculated by first multiplying the Facility
   number by 8 and then adding the numerical value of the Severity. For
   example, a kernel message (Facility=0) with a Severity of Emergency
   (Severity=0) would have a Priority value of 0.  Also, a "local use 4"
   message (Facility=20) with a Severity of Notice (Severity=5) would
   have a Priority value of 165.  In the PRI part of a syslog message,
   these values would be placed between the angle brackets as <0> and
   <165> respectively.




How does log4j translate from Java log level to syslog level?

This is set statically in class org.apache.log4.Level as follows:

final static public Level FATAL = new Level(FATAL_INT, "FATAL", 0);
final static public Level ERROR = new Level(ERROR_INT, "ERROR", 3);
final static public Level WARN  = new Level(WARN_INT, "WARN",  4);
final static public Level INFO  = new Level(INFO_INT, "INFO",  6);
final static public Level DEBUG = new Level(DEBUG_INT, "DEBUG", 7);
public static final Level TRACE = new Level(TRACE_INT, "TRACE", 7);

see http://www.docjar.com/html/api/org/apache/log4j/Level.java.html