SLF4J Logback Tutorial
A simple SLF4J with Logback example.
Tested with
- SLF4J API 1.7.25
- Logback 1.2.3
- Maven 3
- Java 8
Logback natively implements the SLF4J API.
1. Project Directory
2. Maven
2.1 Declares logback-classic, it will pull in the logback-core and slf4j-api
<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.
<?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.
<?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
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.
<configuration debug="true"> </Configuration>
Read this Logback configuration
6. Logback Appenders
Some of the common Logback appenders.
6.1 ConsoleAppender
<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
<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>
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.
<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>
Add an .gz extension, Logback will compress the archived files.
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> </rollingPolicy>
6.4 SMTPAppender – Need javax.mail to send email.
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
<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
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
<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>
Read more Logback appenders
From:一号门
Previous:Java How to Iterate a HashMap
COMMENTS