Logback

Logback Syslog Example

Logging is an essential part of a program. We can trace the flow of the program, we can find out the root cause of a bug in the program. Logs are like our guide book when we need to explore what is happening and what was happened in the code.

In this post, we shall show you how to transmit logs to the Syslog server using Logback framework. After a brief introduction to Logback framework and Syslog protocol, we will look at the implementation details of our example.

1. What is Logback?

Logback is basically a logging framework. Log4j, Java logging API, Apache Commons Logging are some other alternatives. But Logback is the most recent, modern one with extra useful features. It was designed by Ceki Gülcü. He is also the founder of the popular Log4j framework. So we can consider Logback as a successor to the Log4j.

1.1 Logback Architecture

Logback is divided into three modules, logback-core, logback-classic and logback-access. The core module provides the groundwork for the other two modules. The classic module corresponds to a significantly improved version of Log4j.

SLF4J API serves as a simple abstraction for various logging frameworks. Logging codes written with SLF4J in the embedded components and libraries are compatible with the preferred logging framework. At runtime, SLF4J codes are bound to the logging framework in the classpath. Logback-classic module natively implements the SLF4J API. So this flexible architecture allows the end user to switch back and forth between other logging systems and Logback.

The logback-access module integrates with Servlet containers, such as Tomcat and Jetty, to provide rich and powerful HTTP-access log functionality. The logback-access setup is done at Servlet container level. So the web applications deployed in the Servlet container are unaware of it. But this module is out of scope in our example.

1.2 Logback Configuration

Logback can be configured either programmatically or with a configuration file expressed in XML or Groovy format. Logback follows these steps to try to configure itself:

1) Logback tries to find a file called logback.groovy in the classpath.
2) If no such file is found, logback tries to find a file called logback-test.xml in the classpath.
3) If no such file is found, it checks for the file logback.xml in the classpath.
4) If neither file is found, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.

Also I would like to mention about appenders and layouts. Each log event for a given logger is forwarded to the relevant appender. Appender determines the log destination system such as console, file, e-mail, syslog… Log layout determines the log message pattern with some fields such as length, thread name, log level…

2. What is Syslog?

Syslog is a message logging protocol originally written by Eric Allman. This protocol provides a transport to allow a client to send event messages across IP networks to event message receiver, commonly called syslogd, syslog daemon or syslog server.

Implementations of syslog exist for many operating systems. In most of the UNIX/Linux distributions, an internal daemon, called Syslogd, handles the syslog process. This daemon is an integral part of the operating system and does not need to be installed. And also some other open source or commercial products that implement the protocol exist.

Syslog messages may be transmitted via the User Datagram Protocol (UDP) or the Transmission Control Protocol (TCP). Syslog uses the port number 514.

Each syslog message is labeled with a facility code and assigned a severity label.

2.1 Syslog Facility and Severity

Facility label indicates the source system category that generate the syslog message. These sources can be the operating system, the process, or an application. Different facilities may be handled differently by the Syslog server. These facilities are represented by an integer number. Facilities are 0 (kern), 1 (user), 2 (mail), 3 (daemon), 4 (auth), 5 (syslog), 6 (lpr), 7 (news), 8 (uucp), 9 (clock daemon), 10 (authpriv), 11 (ftp), 12(ntp system), 13 (log audit), 14 (log alert), 15 (cron), 16 (local0), 17 (local1), 18 (local2), 19 (local3), 20 (local4), 21 (local5), 22 (local6), 23 (local7)

Syslog protocol defines eight severity levels presented by single-digit integer: 0 (emergency), 1 (alert), 2 (critical), 3 (error), 4 (warning), 5 (notice), 6 (informational), 7 (debug)

2.2 Logback Syslog Configuration

In the Logback, syslog messages are configured by the SyslogAppender. Here are the properties you can pass to a SyslogAppender:

syslogHost: The host name of the syslog server.

port: The port number on the syslog server to connect to. Default value is 514.

facility: The source of the message.

suffixPattern: It specifies the format of the message sent to the syslog server. By default, its value is [%thread] %logger %msg.

stackTracePattern: This property allows the customization of the string appearing just before each stack trace line. The default value for this property is “\t”, i.e. the tab character.

throwableExcluded: This is a boolean field. Setting it to true will cause stack trace data associated with a Throwable to be omitted. By default, it is set to false so that stack trace data is sent to the syslog server.

The syslog severity of a logging event is converted from the level of the logging event.

3. Overview

We create a Maven project in the Eclipse IDE and add logback dependencies to our pom.xml file. Please note that Maven Integration Plugin should be already installed in the Eclipse IDE, if you would like to delegate the classpath setting process to the Eclipse. We are using logback.xml file to configure Logback Syslog Appender. As we mentioned before, There are a lot of Syslog implementations. We prefer to use Kiwi Free Edition to test the log transportation in the Windows operating system. In order to see the log messages in the Linux operating system, we use Rsyslog package in the Ubuntu operating system.

In the Ubuntu Server, syslog messages are appended to the syslog file in the “/var/log” directory. But in advance, you must uncomment the lines below in the “/etc/rsyslog.conf” file and next, restart the rsyslog service to provide UDP syslog reception:

$ModLoad imudp
$UDPServerRun 514

When we execute the code, We expect to see messages in the both of the Syslog servers.

Tip
You may skip project creation and jump directly to the beginning of the example below.

4. Create a new Maven project

Go to File -> Project ->Maven -> Maven Project.

Eclipse new Project Wizard
Eclipse new Project Wizard

In the next screen, accept the default options and click on Next

Eclipse Maven Project
Eclipse Maven Project

In the next screen, select the maven-archetype-quickstart option and click Next

Eclipse Maven Project
Eclipse Maven Project

In the next screen, type the Group Id, Artifact Id and Package, as in the following screen and click on Finish

Eclipse Maven Project
Eclipse Maven Project

As you see, the project is created in your workspace.

Eclipse Project
Eclipse Project

4.1 Adding Maven dependencies

Before we execute some code, we need to add logback dependencies in the Maven’s pom.xml file. By the power of the Maven Dependency Management, It is enough to add only logback-classic artifact. logback-core and slf4j-api packages are transitive dependencies of the logback-classic artifact. So they are automatically added to the classpath. It is inessential, but we also add junit artifact to able to write unit test code.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.javacodegeeks.examples</groupId>
	<artifactId>logbacksyslogexample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>logbacksyslogexample</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.1.3</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
	</dependencies>
</project>
 

5. Implementation

We are running the code in a Windows operating system which Kiwi Syslog Server installed on it. On the other hand, an Ubuntu Server is listening its 514 port for syslog transmissions in the same network. We need to add two SyslogAppenders in order to send messages simultaneously to both of them. One of the appenders is for the Kiwi and the other one is for the Rsyslog in the Ubuntu Server.

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<appender name="KIWI" class="ch.qos.logback.classic.net.SyslogAppender">
		<syslogHost>localhost</syslogHost>
		<facility>LOCAL0</facility>
		<suffixPattern>%thread: %-5level %logger{36} - %msg%n</suffixPattern>
	</appender>
	
	<appender name="RSYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
	    <!-- Ubuntu Server host name -->
		<syslogHost>cengaver</syslogHost>
		<facility>LOCAL1</facility>
		<suffixPattern>%thread: %-5level %logger{36} - %msg%n</suffixPattern>
	</appender>

	<logger name="com.javacodegeeks.examples.logbacksyslogexample.message.kiwi" level="INFO">
		<appender-ref ref="KIWI" />
	</logger>

	<logger name="com.javacodegeeks.examples.logbacksyslogexample.message.rsyslog" level="INFO">
		<appender-ref ref="RSYSLOG" />
	</logger>

</configuration>

The UML class diagram below demonstrates the overview of the application. We place the logger instances to appenders that associated to the different syslog servers, into two classes: KiwiMessageTransmitterImpl and RsyslogMessageTransmitterImpl. We generate these classes from an interface to provide an identical method signature and abstraction.

Example Class Diagram
Example Class Diagram

IMessageTransmitter.java

package com.javacodegeeks.examples.logbacksyslogexample.message;

public interface IMessageTransmitter {

	void send( final String message );
}

KiwiMessageTransmitterImpl.java

package com.javacodegeeks.examples.logbacksyslogexample.message.kiwi;

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

import com.javacodegeeks.examples.logbacksyslogexample.message.IMessageTransmitter;

public class KiwiMessageTransmitterImpl implements IMessageTransmitter {

	private static final Logger	LOGGER	= LoggerFactory.getLogger( KiwiMessageTransmitterImpl.class );

	@Override
	public void send( final String message ) {
		LOGGER.info( "Hello! My message is : {}", message );
	}
}

RsyslogMessageTransmitterImpl.java

package com.javacodegeeks.examples.logbacksyslogexample.message.rsyslog;

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

import com.javacodegeeks.examples.logbacksyslogexample.message.IMessageTransmitter;

public class RsyslogMessageTransmitterImpl implements IMessageTransmitter {

	private static final Logger	LOGGER	= LoggerFactory.getLogger( RsyslogMessageTransmitterImpl.class );

	@Override
	public void send( final String message ) {
		LOGGER.info( "Hello! My message is : {}", message );
	}
}

ApplicationStarter.java

package com.javacodegeeks.examples.logbacksyslogexample;

import com.javacodegeeks.examples.logbacksyslogexample.message.IMessageTransmitter;
import com.javacodegeeks.examples.logbacksyslogexample.message.kiwi.KiwiMessageTransmitterImpl;
import com.javacodegeeks.examples.logbacksyslogexample.message.rsyslog.RsyslogMessageTransmitterImpl;

public class ApplicationStarter {

	/**
	 * Main method
	 */
	public static void main( final String[] args ) {

		final IMessageTransmitter kiwiMessageTransmitter = new KiwiMessageTransmitterImpl();
		kiwiMessageTransmitter.send( "I am learning to send message to Syslog server" );

		final IMessageTransmitter rsyslogMessageTransmitter = new RsyslogMessageTransmitterImpl();
		rsyslogMessageTransmitter.send( "Logback can easily send message to Syslog server" );
	}
}

In the main method, we create instances of the message implementation classes. After we invoke their service method ( send ) to cause logger statements in it to perform, the log messages are collected by the Syslog servers ( Kiwi and Rsyslog ) individually.

Let’s look at the consequences in the Servers. In the Kiwi console:

Kiwi Screen Shot
Kiwi Screen Shot

When we examine the "/var/log/syslog" file in the Ubuntu Linux Server, we can see the messages come from our application:

Ubuntu Server Console
Ubuntu Server Console

6. Download the Eclipse Project

This project illustrates how to send messages to the Syslog servers using Logback.

Download
You can download the full source code of this example here : logbacksyslogexample

Ilker Konar

I am a senior software developer with experience mostly in java-related technologies with appliance in the telecommunication industry. I have been programming for more than fifteen years. I am passionate about programming. I like learning new frameworks, languages and design patterns.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Mahesh
Mahesh
6 years ago

Hi,
I need to send CEF format data to syslog server.Can you please explain.

Chandan
Chandan
4 years ago
Reply to  Mahesh

Hi,
Did you found any explanation on how to send CEF format data?

Evgeniy
Evgeniy
5 years ago

Thank you, man. Very good explanation.

Dean
Dean
4 years ago

On Ubuntu 19.10 this code will only write a message to localhost syslog once no matter how many times I run the code. If I change the message by one character it will write the new message, but only once.

What causes this?

nav
nav
3 years ago

Hi, the /var/log/syslog you show above doesn’t have the facility level “local1” as the appender you have. Is there anyway to show local1 (or it’s code) in the syslog message?

Back to top button