Showing posts with label rsyslog. Show all posts
Showing posts with label rsyslog. Show all posts

Monday, December 12, 2011

Using logback to log to a syslog server

In my previous posts, we've configured a rsyslogd server to accept remote connections via TCP/UDP as well as a rsyslogd instance to write to a remote rsyslogd server.  We'll now take this further by logging to the rsyslogd server we've configured earlier using the logback library (http://logback.qos.ch/). 

Besides the logback JAR files, you'll need to grab the latest SLF4J libraries as well from http://slf4j.org/.  Below are the JAR files required to get logback working:
  • logback-core-1.0.0.jar
  • logback-classic-1.0.0.jar
  • slf4j-api-1.6.4.jar
Pay attention to the version of SLF4J you're using.  If you get the following exception when running your program, you're most likely using an older SLF4J library:
SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.
Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.arrayFormat(Ljava/lang/String;[Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
    at ch.qos.logback.classic.spi.LoggingEvent.(LoggingEvent.java:114)
    at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:468)
    at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:424)
    at ch.qos.logback.classic.Logger.info(Logger.java:628)
    at com.test.RemoteTest.main(RemoteTest.java:11)
On to the logback.xml configuration file.  It's a very basic configuration.  Just two appenders: STDOUT and SYSLOG.  SYSLOG appender is the one we're interested in.
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
            by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>myhost</syslogHost>
        <facility>USER</facility>
        <suffixPattern>[%thread] %logger %msg</suffixPattern>
    </appender>

    <root level="debug">
        <appender-ref ref="SYSLOG"/>
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
  • syslogHost - syslog server host to log to
  • facility - identify the source of the message
  • suffixPattern - format of the log message
More info can be obtained in logback's manual on appenders: http://logback.qos.ch/manual/appenders.html#SyslogAppender.

The Java class to test the appenders:
package com.test;

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

public class RemoteTest {
    static final Logger logger = LoggerFactory.getLogger(RemoteTest.class);
   
    public static void main(String[] args) {
       
        logger.info("hello world");
    }
}
The rsyslogd host should have the following entry once you run the RemoteTest class:
Dec 12 16:16:37 my-noteb [main] com.test.RemoteTest hello world

rsyslog: Logging to remote server

Now that we've setup the rsyslogd server to accept incoming connections (NOTE: UDP somehow didn't work.  I had to configure rsyslogd to listen to TCP instead); we can now configure the "client" rsyslogd instance to log to a remote server.

In the "client" server, we'll need to edit the same configuration file /etc/rsyslog.conf.  I've added the highlighted lines below:
[...]
###############
#### RULES ####
###############

# Log all messages to this rsyslogd host
*.* @@myhost:514

#
# First some standard log files.  Log by facility.
#
auth,authpriv.*                 /var/log/auth.log
*.*;auth,authpriv.none          -/var/log/syslog
#cron.*                         /var/log/cron.log
[...]
The rest of the config file remains unchanged.  Reload/restart the service once we're done:
myclient:~# /etc/init.d/rsyslog reload
Reloading enhanced syslogd: rsyslogd.
We can now use the logger command to send log messages to the syslog.  Here's what I used:
# logger -t CLIENT_TEST "This is a test to test the test"
The following entry should be logged in myhost /var/log/syslog file:
Dec 12 15:17:52 myhost CLIENT_TEST: This is a test to test the test

rsyslog: Enabling remote logging service in Ubuntu

Newer versions of Ubuntu (since 9.10 according to rsyslog wiki: http://wiki.rsyslog.com/index.php/Ubuntu) comes with rsyslog instead of sysklogd.  Was trying to enable it via the sysklogd way by adding the "-r" option in the startup script.  That obviously didn't work :)

What you'll need to do is just uncomment 2 lines in the /etc/rsyslog.conf file:
# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
That's if you want to provide UDP syslog service.  Uncomment the following 2 lines if you want to provide TCP syslog service:
# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
Once you've made the changes, either reload or restart the rsyslogd service:
myhost:/etc# /etc/init.d/rsyslog reload
Reloading enhanced syslogd: rsyslogd.
I've chose to enable UDP for my server.  We'll use netstat to check if rsyslogd is listening to the specified port:
myhost:/etc# netstat -tlnup | grep 514
udp        0      0 0.0.0.0:514             0.0.0.0:*                           13282/rsyslogd
udp6       0      0 :::514                  :::*                                13282/rsyslogd
rsyslogd is indeed listening to the proper port and protocol. 

Next stop, actual logging and probably more configuration :)