Main Tutorials

SLF4J Logback Tutorial

logback logo

A simple SLF4J with Logback example.

Tested with

  • SLF4J API 1.7.25
  • Logback 1.2.3
  • Maven 3
  • Java 8
Note
Logback natively implements the SLF4J API.

1. Project Directory

project directory

2. Maven

2.1 Declares logback-classic, it will pull in the logback-core and slf4j-api

pom.xml

	<dependency>
		<groupId>ch.qos.logback</groupId>
		<artifactId>logback-classic</artifactId>
		<version>1.2.3</version>
	</dependency>

com.mkyong:slf4j-logback:jar:1.0
[INFO] +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.25:compile

2.2 Complete pom.xml example.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.mkyong</groupId>
    <artifactId>slf4j-logback</artifactId>
    <version>1.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <logback.version>1.2.3</logback.version>
		<javax.mail.version>1.6.2</javax.mail.version>
    </properties>

    <dependencies>

        <!-- pull in logback-core and slf4j-api -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <!-- SMTPAppender need this to send email 
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>${javax.mail.version}</version>
        </dependency>
		-->
		
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

            <!-- build a single executable JAR -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <!-- Attach the shade into the package phase -->
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.mkyong.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

</project>

3. logback.xml

3.1 Create a logback.xml in the project classpath.

src/resources/logback.xml

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

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <logger name="com.mkyong" level="debug" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

4. Hello Logback

HelloWorld.java

package com.mkyong;

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

public class HelloWorld {

    private static final Logger logger = LoggerFactory.getLogger(HelloWorld.class);

    public static void main(String[] args) {

        logger.debug("Hello from Logback");

        logger.debug("getNumber() : {}", getNumber());

    }

    static int getNumber() {
        return 5;
    }

}

Output


11:28:18.350 [main] DEBUG com.mkyong.HelloWorld - Hello from Logback
11:28:18.352 [main] DEBUG com.mkyong.HelloWorld - getNumber() : 5

5. Logback Configuration

5.1 For development, it’s recommended to enable the debug mode. It will display a lot of useful INFO and also error message if any.

logback.xml

<configuration debug="true">
    
</Configuration>

Read this Logback configuration

6. Logback Appenders

Some of the common Logback appenders.

6.1 ConsoleAppender

logback.xml

<configuration>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <logger name="com.mkyong" level="debug" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

6.2 FileAppender

logback.xml

<configuration>

    <property name="HOME_LOG" value="logs/app.log"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${HOME_LOG}</file>
        <append>true</append>
        <immediateFlush>true</immediateFlush>
        <encoder>
            <pattern>%d %p %c{1.} [%t] %m%n</pattern>
        </encoder>
    </appender>

    <logger name="com.mkyong" level="debug" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </logger>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>
logs/app.log

2019-03-29 11:42:44,827 DEBUG com.mkyong.HelloWorld [main] Hello from Logback
2019-03-29 11:42:44,836 DEBUG com.mkyong.HelloWorld [main] getNumber() : 5

6.3 RollingFileAppender – Rotate log file, by date and size. This is the one you need in production, most likely.

logback.xml

<configuration>

    <property name="HOME_LOG" value="logs/app.log"/>

    <appender name="FILE-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${HOME_LOG}</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- each archived file, size max 10MB -->
            <maxFileSize>10MB</maxFileSize>
            <!-- total size of all archive files, if total size > 20GB, it will delete old archived file -->
            <totalSizeCap>20GB</totalSizeCap>
            <!-- 60 days to keep -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%d %p %c{1.} [%t] %m%n</pattern>
        </encoder>
    </appender>

    <logger name="com.mkyong" level="debug" additivity="false">
        <appender-ref ref="FILE-ROLLING"/>
    </logger>

    <root level="error">
        <appender-ref ref="FILE-ROLLING"/>
    </root>

</configuration>
sample
sample

Add an .gz extension, Logback will compress the archived files.

logback.xml

	<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
		<fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
	</rollingPolicy>
sample

6.4 SMTPAppender – Need javax.mail to send email.

pom.xml

	<dependency>
		<groupId>com.sun.mail</groupId>
		<artifactId>javax.mail</artifactId>
		<version>1.6.2</version>
	</dependency>
logback.xml

<configuration debug="true">

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
        <smtpHost>smtp.mailgun.org</smtpHost>
        <smtpPort>25</smtpPort>
        <username>123</username>
        <password>123</password>
        <to>TO_EMAIL</to>
        <to>RO_ANOTHER_EMAIL</to>
        <from>FROM_EMAIL</from>
        <subject>TESTING: %logger{20} - %m</subject>

        <layout class="ch.qos.logback.classic.html.HTMLLayout"/>

		<!-- for testing , comment in production, default 256 -->
        <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
			<!-- Send just one log entry per email, ready for a lot of emails if you put one. -->
            <bufferSize>1</bufferSize>
        </cyclicBufferTracker>

		<!-- for testing , comment in production, default asynchronousSending = true -->
        <asynchronousSending>false</asynchronousSending>

    </appender>

    <logger name="com.mkyong" level="error" additivity="false">
        <appender-ref ref="EMAIL"/>
    </logger>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

Simulate an error


package com.mkyong;

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

public class HelloWorldError {

    private static final Logger logger = LoggerFactory.getLogger(HelloWorldError.class);

    public static void main(String[] args) {

        try {
            System.out.println(getData());
        } catch (IllegalArgumentException e) {
            logger.error("{}", e);
        }

    }

    static int getData() throws IllegalArgumentException {
        throw new IllegalArgumentException("Sorry IllegalArgumentException!");
    }

}

Here’s the email

sample email

6.5 AsyncAppender – Logs asynchronously, faster, but drop events of level TRACE, DEBUG and INFO if its queue is 80% full, keeping only events of level WARN and ERROR. Read this AsyncAppender

pom.xml

<configuration debug="true">

    <property name="HOME_LOG" value="logs/app.log"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <appender name="FILE-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${HOME_LOG}</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- each archived file, size max 10MB -->
            <maxFileSize>10MB</maxFileSize>
            <!-- total size of all archive files, if total size > 20GB, it will delete old archived file -->
            <totalSizeCap>20GB</totalSizeCap>
            <!-- 60 days to keep -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%d %p %c{1.} [%t] %m%n</pattern>
        </encoder>
    </appender>

    <!-- https://logback.qos.ch/manual/appenders.html#AsyncAppender -->
    <!-- AsyncAppender will drop events of level TRACE, DEBUG and INFO if its queue is 80% full -->
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE-ROLLING" />
        <!-- defaulr 256 -->
        <queueSize>512</queueSize>
    </appender>

    <logger name="com.mkyong" level="debug" additivity="false">
        <appender-ref ref="ASYNC"/>
        <appender-ref ref="CONSOLE"/>
    </logger>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>
Note
Read more Logback appenders

Download Source Code

$ git clone https://github.com/mkyong/java-logging.git
$ cd slf4j-logback
$ mvn clean package
$ java -jar target\slf4j-logback-1.0.jar

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Rahul
2 years ago

Great stuff, however the same tutorial does not work when logback.xml is put outside a built jar which is a typical requirement in an enterprise application. is there any specific setting need to be done?

Omer
4 years ago

Hi, great article.

I have one question related to smtp appender.
Is there any way to send additional meta information inside email.
For example, at the end of the email body, I would like to list some metadata about VM that generated an error.
Some service Id, few links related to this VM etc.
I know there is a way to send some of this via smtp_subject. Or via pattern.
But it would be great to append to the end of body one large set of metadata with more details about the source.

Thanks in advance.