Search code examples
javalog4jrsyslog

SyslogAppender: Using a pattern not starting with square brackets overwrites the host name


I am using log4j and the SyslogAppender class to send messages to rsyslog running on the local Linux machine (called orion). I currently have the following pattern:

log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=[%p] %m%n

Which produces this output:

Jun  5 16:16:09 orion [ERROR]: <My message here>

This doesn't show the source of the message and so I wanted to add that but unfortunately when I add anything before the square brackets, the host name disappears. eg.

log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=TEST [%p] %m%n

Jun  5 16:22:41 TEST [ERROR]: <My message here>

It is not just literal text that causes this problem. For example, if I use the sample pattern from the documentation, "%-5p [%t]: %m%n", the hostname is also not there:

log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=%-5p [%t]: %m%n

Jun  5 16:25:34 ERROR [main]: <My message here>

Here is the simplest example I can come up with to demonstrate the problem using the patterns aaa and [aaa]:

log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=aaa
Jun  5 17:47:29 aaa

log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=[aaa]
Jun  5 17:48:24 orion [aaa]:

The documentation doesn't show that square brackets have any special meaning so I don't understand why this is happening. I'm also unclear on whether this problem is caused by the SyslogAppender class or rsyslog.

How do I keep the host name in the syslog message without wrapping the first item in square brackets?


Solution

  • I decided to look at this with fresh eyes by looking at the source of the SyslogAppender class.

    This subclass has an extra field called header:

      105       /**
      106        * If true, the appender will generate the HEADER (timestamp and host name)
      107        * part of the syslog packet.
      108        * @since 1.2.15
      109        */
      110     private boolean header = false;
    

    Setting this value to true allows the hostname to show up.

    log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=TEST [%p] %m%n
    
    May  9 16:50:14 orion TEST [ERROR] <my message here>
    

    The documentation for setHeader() (confusingly mixed up with the documentation for getHeader()) has some extra information about the default value.

      460     /**
      461      * If true, the appender will generate the HEADER part (that is, timestamp and host name)
      462      * of the syslog packet.  Default value is false for compatibility with existing behavior,
      463      * however should be true unless there is a specific justification.
      464      * @since 1.2.15
      465     */
      466     public final boolean getHeader() {
      467         return header;
      468     }
      469   
      470       /**
      471        * Returns whether the appender produces the HEADER part (that is, timestamp and host name)
      472        * of the syslog packet.
      473        * @since 1.2.15
      474       */
      475     public final void setHeader(final boolean val) {
      476         header = val;
      477     }
    

    The header value can either be set in Java code by calling setHeader(true) or by adding the following line to log4j.properties:

    log4j.appender.SYSLOG_LOCAL1.header=true
    

    Replace SYSLOG_LOCAL1 with whatever you named this appender in your properties file.