During project development, you can use debug to find problems. In the online environment, we can only find problems by printing logs. Therefore, logging is a very important issue for a project. Therefore, choosing an appropriate logging framework is also very important.

In Java development, common logging frameworks are JDKLog, Log4J, LogBack, SLF4J, SLF4J. Each of these logging frameworks has its own characteristics and application scenarios. Understanding the characteristics and application scenarios of these frameworks is helpful for us to make correct judgments when selecting technologies.

JDKLog: Log knife

JDKLog is an official JDK logging method that can be used directly in the JDK.

import java.util.logging.Logger; /**** ** JDKLog Demo **/ public class JDKLog { public static void main( String[] args ) { Logger logger = Logger.getLogger("JDKLog"); logger.info("Hello World."); }}Copy the code

The nice thing about JDKLog is that it’s very simple to use and can be used directly in the JDK. However, the JDKLog function is too simple, does not support placeholder display, poor scalability, so few people use it now.

Log4J: log cannon

Log4J is an open source logging framework for Apache. It has multiple log levels (DEBUG/INFO/WARN/ERROR), which can be used to record logs at different log levels.

Log4J is available in 1.x and 2.x versions, which are now officially recommended, with some architectural upgrades and configuration file changes. But the good news is that the official configuration documentation is very clear and most of the problems can be solved by consulting the documentation.

To use the Log4J framework, you first need to import dependent packages:

<! -- Log4J --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> < version > 2.6.2 < / version > < / dependency > < the dependency > < groupId > org. Apache. Logging. Log4j < / groupId > < artifactId > log4j - core < / artifactId > < version > 2.6.2 < / version > < / dependency >Copy the code

Add configuration file log4j2. XML to resource directory:

<? The XML version = "1.0" encoding = "utf-8"? > <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>Copy the code

The level attribute of the <Root> node indicates the lowest level of output.

Finally, write a test class:

import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /**** ** Log4J Demo **/ public class Log4jLog { public static void main(String args[]) { Logger logger = LogManager.getLogger(Log4jLog.class); logger.debug("Debug Level"); logger.info("Info Level"); logger.warn("Warn Level"); logger.error("Error Level"); }}Copy the code

Output from running the test class:

10:16:08.279 [main] infocom.chanshuyi. Log4jlog-info Level 10:16:08.280 [main] WARN com.chanshuyi. Log4jlog-warn Level 10:16:08.280 [main] ERROR com.chanshuyi.Log4jLog - ERROR LevelCopy the code

If the log4j2.xml configuration file is not configured, LOG4J will automatically enable a configuration file similar to the following:

<? The XML version = "1.0" encoding = "utf-8"? > <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>Copy the code

Output using the default configuration file:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: Logging only Errors to the console.11:40:07.377 [main] ERROR com.chanshuyi.Log4jLog - ERROR LevelCopy the code

As you can see from the steps above, Log4J is a little more complicated to use, but it is still very clear. And because Log4J has multiple hierarchical (DEBUG/INFO/WARN/ERROR) recording levels, different business problems can be well documented. Because of these advantages, almost everyone was using Log4J as a logging framework a few years ago, and the base was very deep.

However, Log4J also has some disadvantages, such as no support for placeholders and bad code reading. But compared to JDKLog, Log4J is a very good logging framework.

LogBack: Log rocket

LogBack is an evolutionary version of Log4J, as both are open source logging components designed by the same person (Ceki Gulcu). In addition to having all the advantages of Log4j, LogBack solves the problem that Log4j cannot use placeholders.

To use LogBack, you need to first introduce dependencies:

<! -- LogBack --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> The < version > 1.1.7 < / version > < / dependency >Copy the code

To configure the logback.xml configuration file:

<? The XML version = "1.0" encoding = "utf-8"? > <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <logger name="com.chanshuyi" level="TRACE"/> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration>Copy the code

LogBack’s log level division can be broken down into classes or packages, making logging more flexible. Then introduce the Logger class into the class file and log:

import org.slf4j.Logger; import org.slf4j.LoggerFactory; /**** ** LogBack Demo **/ public class LogBack { static final Logger logger = LoggerFactory.getLogger(LogBack.class); public static void main(String[] args) { logger.trace("Trace Level."); logger.debug("Debug Level."); logger.info("Info Level."); logger.warn("Warn Level."); logger.error("Error Level."); }}Copy the code

Output result:

14:34:45.747 [main] TRACE com.chanshuyi.LogBack - TRACE level.14:34:45.749 [main] DEBUG com.chanshuyi.LogBack - DEBUG Level.14:34:45.749 [main] INFO com.chanshuyi.LogBack - INFO level.14:34:45.749 [main] WARN com.chanshuyi.LogBack - Warn level.14:34:45.749 [main] ERROR com.chanshuyi.LogBack - ERROR LevelCopy the code

LogBack addresses Log4J’s inability to use placeholders, which makes it easy to read the logging code. In addition, LogBack has a faster runtime and better internal implementation than Log4J. And the LogBack internal integration with SLF4J enables some logging implementations to be more native.

SLF4J: adapter

JDKLog, Log4J, and LogBack all have their own advantages and disadvantages, and can be used in different scenarios. Simple projects may use JDKLog directly, while more complex projects may need Log4J.

Most of the time we are working on a project from simple to complex, that is, we are likely to start with JDKLog, and then need to use Log4J. In this case, how can we use the new logging framework to output the original log?

One of the most rigid approaches is to change the logging code from JDKLog to Log4J’s logging interface line by line. But this approach is not only inefficient, but also doing repetitive work, which can not be tolerated.

Because of the need to switch from one logging framework to another in real project applications, it is often necessary to make significant changes to the code. To avoid changing the code when switching Logging components, something called SLF4J (Simple Logging Facade for Java) emerged.

SLF4J (Simple Logging Facade for Java) is a Logging interface specification that provides users with a unified Logging interface and shields the differences between different Logging components. In this way, we only need to look at the SLF4J interface documentation when writing code, and do not need to pay attention to the differences between different frameworks. When we need to replace the logging component, we only need to replace a specific logging component Jar package.

Integrating SLF4J with the logging framework is also a simple matter.

SLF4J+JDKLog

SLF4J + JDKLog import the following dependency packages in Maven:

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.21</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-jdk14</artifactId>
  <version>1.7.21</version>
</dependency>Copy the code

Writing test classes:

import org.slf4j.Logger; import org.slf4j.LoggerFactory; /**** ** SLF4J + JDKLog **/ public class Slf4jJDKLog { final static Logger logger = LoggerFactory.getLogger(Slf4jJDKLog.class); public static void main(String[] args) { logger.trace("Trace Level."); logger.info("Info Level."); logger.warn("Warn Level."); logger.error("Error Level."); }}Copy the code

Output result:

July 15, 2016 3:30:02 afternoon com. Chanshuyi. Slf4j. Slf4jJDKLog main information: the Info Level. July 15, 2016 3:30:02 afternoon com. Chanshuyi. Slf4j. Slf4jJDKLog main warning: Warn Level. July 15, 2016 3:30:02 afternoon com. Chanshuyi. Slf4j. Slf4jJDKLog main serious: the Error Level.Copy the code

SLF4J+LOG4J

Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven Maven

<! -- 2.SLF4J + Log4J --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>log4j</ artifactId> The < version > 1.2.17 < / version > < / dependency >Copy the code

To configure the log4j.xml file:

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' > <appender name="myConsole" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" /> </layout> <! Set output levels - filter - > < filter class = ". Org. Apache log4j. Varia. LevelRangeFilter "> < param name =" levelMin "value =" debug "/ > < param name="levelMax" value="error" /> <param name="AcceptOnMatch" value="true" /> </filter> </appender> <! -- Root Logger setup --> <root> <priority value ="debug"/> <appender-ref ref="myConsole"/> </root> </log4j: Configuration >Copy the code

We use the same code as above, with no changes, and the result is:

[15 16:04:06.371 INFO] [main] slf4j.slf4jlog-info Level. [15 16:04:06.371 INFO] [main] slf4jlog-info Level. [15 16:04:06.371 WARN] [main] slf4jlog-warn Level. [15 16:04:06.371 ERROR] [main] slf4jlog-error Level.Copy the code

SLF4J+LogBack

Import dependencies:

<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> < the dependency > < groupId > ch. Qos. Logback < / groupId > < artifactId > logback - classic < / artifactId > < version > 1.1.7 < / version > </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> The < version > 1.1.7 < / version > < / dependency >Copy the code

To configure the logback. XML file:

<? The XML version = "1.0" encoding = "utf-8"? > <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <logger name="com.chanshuyi" level="TRACE"/> <root level="warn"> <appender-ref ref="STDOUT" /> </root> </configuration>Copy the code

We use the same code as above, with no changes, and the result is:

16:08:01. [the main] TRACE com 040. Chanshuyi. Slf4j. SLF4JLog - TRACE Level. 16:08:01. The 042 [main] the DEBUG Com. Chanshuyi. Slf4j. SLF4JLog - the Debug Level. 16:08:01. 043 [main] INFO com. Chanshuyi. Slf4j. SLF4JLog - INFO Level. 16:08:01. [the main] WARN 043 com. Chanshuyi. Slf4j. SLF4JLog - the WARN Level. 16:08:01. [the main] ERROR 043 com.chanshuyi.slf4j.SLF4JLog - Error Level.Copy the code

After the above introduction, I believe you have a certain understanding of the Java logging framework commonly used.

In The Java Logging Framework Stuff, PART 2, I’ll show you one of the most common logging scenarios in Java usage, and how you can switch between different logging frameworks without changing your code.