Comprehensively sort out the Spring Boot log system

I've recorded a video to share the log problem of Spring Boot with you, but I always feel it's almost interesting. Therefore, SongGe plans to use another article to smooth out the log problem in Java. By the way, we'll make it clear about the log problem in Spring Boot.

1. Java log overview

When it comes to Java logging, many beginners may be confused because there are too many things involved here: Apache common logging, Slf4j, Log4j, Log4j2, Logback, Java Util Logging, etc. What are the functions of these frameworks? What's the difference between them?

1.1 general overview

The following figure shows the logging system in Java:

It can be seen that the logging framework in Java is mainly divided into two categories: log facade and log implementation.

Log facade

The log facade defines a set of log interface specifications, which does not provide the underlying specific implementation logic. Apache Commons Logging and Slf4j fall into this category.

Log implementation

Log implementation is the specific implementation of log, including log level control, log print format and log output form (output to database, output to file, output to console, etc.). Log4j, Log4j2, Logback and Java Util Logging fall into this category.

Separating the log facade from the log implementation is actually a typical facade mode. This way allows specific businesses to switch freely between different log implementation frameworks without changing any code. Developers only need to master the API of the log facade.

The log facade cannot be used alone. It must be combined with a specific log implementation framework.

Can the logging framework be used alone?

Technically, of course, there is no problem, but we generally don't do this because it has poor maintainability and is not easy to expand in the later stage. For example, A has developed A toolkit to print logs using Log4j, and B has referenced this toolkit, but B likes to print logs using Logback. At this time, A business uses two or even more log frameworks, and developers also need to maintain multiple log configuration files. Therefore, we all use the log facade to print the log.

1.2 log level

The advantage of using the log level is that by adjusting the level, many debugging related log outputs can be shielded. Different log implementations define different log levels, but they are also similar.

Java Util Logging

Java Util Logging defines seven logging levels, from severe to normal:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

Because the default level is INFO, logs below INFO level will not be printed.

Log4j

Log4j defines 8 log levels (except OFF and ALL, it can be divided into 6 levels), from serious to normal:

  • OFF: the highest level, which is used to turn OFF all logging.
  • FATAL: major error. This level can directly stop the program.
  • ERROR: print ERROR and exception information. If you don't want to output too many logs, you can use this level.
  • WARN: warning prompt.
  • INFO: it is used to output some important information of program operation in the production environment. It cannot be abused.
  • DEBUG: used to print some operation information during development.
  • TRACE
  • ALL is the lowest level, which is used to open ALL logging.

Logback

The Logback log level is relatively simple, from serious to normal:

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

1.3 comprehensive comparison

The Java Util Logging system reads the configuration file and completes initialization when the JVM starts. Once the application starts running, the configuration cannot be modified. In addition, this kind of log implementation configuration is not very convenient. Parameters can only be passed when the JVM is started, as follows:

-Djava.util.logging.config.file=<config-file-name>. 
copy

Due to these limitations, Java Util Logging is not widely used.

Although the configuration of Log4j is cumbersome, once the configuration is completed, it is very convenient to use. You only need to put the relevant configuration files under the classpath. In many cases, the configuration file of Log4j can be used repeatedly in different projects.

Log4j can be used with Apache Commons Logging. Apache Commons Logging will automatically search and use log4j. If log4j is not found, use Java Util Logging.

More popular than the Log4j + Apache Commons Logging combination is the Slf4j + Logback combination.

Logback is the native implementation framework of Slf4j. It is also written by the author of Log4j (Ceki G ü lc ü). However, compared with Log4j, it has more advantages, features and stronger performance.

1.4 best practices

  • If you do not want to add any dependencies, use Java Util Logging or the logging interface already provided by the framework container.
  • If you care about performance, it is recommended: Slf4j + Logback.
  • If Log4j has been used in the project and no performance problems are found, the recommended combination is: Slf4j + Log4j2.

2. Spring Boot log implementation

Spring Boot uses Apache common logging as the internal logging framework facade. It is just a logging interface. In practical application, you need to specify the corresponding logging implementation for this interface.

The default log implementation of Spring Boot is Logback. This is easy to see: start a Spring Boot project and find a line of log from the console, such as the following:

Considering that the last prod is a changeable character, we searched globally in the project: The following profiles are active, and the results are as follows:

debug in the line of log output. Then start the project again, as shown in the following figure:

At this point, we can see that the real log implementation is Logback.

Other frameworks such as Java Util Logging and Log4j are also well supported by Spring Boot.

In the Spring Boot project, as long as the following web dependencies are added, the log dependencies are automatically added:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
copy

2.1 Spring Boot log configuration

The log system of Spring Boot will automatically select the appropriate log configuration according to the content under the classpath. Logback is preferred in this process.

If the developer needs to modify the log level, it only needs to be in application Properties file through logging It can be configured in the form of level prefix + package name, for example:

logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
copy

If you want to output the log to a file, you can specify the log file name through the following configuration:

logging.file.name=javaboy.log
copy

logging.file.name can specify only the log file name or the full path of the log file, for example:

logging.file.name=/Users/sang/Documents/javaboy/javaboy.log
copy

If you just want to redefine the path of the output log file, you can also use logging file. Path attribute, as follows:

logging.file.path=/Users/sang/Documents/javaboy
copy

If you want to finely manage the logs output to the file, you can configure the following properties:

  • logging. logback. rollingpolicy. File name pattern: the file name of the log archive. After the log file reaches a certain size, it will be automatically compressed and archived.
  • logging. logback. rollingpolicy. Clean history on start: whether archive management is performed when the application starts.
  • logging. logback. rollingpolicy. Max file size: the upper limit of log file size. When the upper limit is reached, it will be compressed automatically.
  • logging. logback. rollingpolicy. Total size cap: the maximum size that a log file can hold before it is deleted.
  • logging. logback. rollingpolicy. Max history: the number of days the log file is saved.

For log file archiving, if you are interested, you can try it yourself. You can first turn down the max file size attribute to see the effect:

logging.logback.rollingpolicy.max-file-size=1MB
copy

Then add the following interfaces:

@RestController
public class HelloController {
    private static final Logger logger = getLogger(HelloController.class);
    @GetMapping("/hello")
    public void hello() {
        for (int i = 0; i < 100000; i++) {
            logger.info("hello javaboy");
        }
    }
}
copy

Accessing this interface, you can see that the finally generated log file is automatically compressed:

application. Log grouping can also be configured in properties.

Log grouping can put related logger s into a group for unified management.

For example, we can define a tomcat group:

logging.group.tomcat=org.apache.catalina,org.apache.coyote, org.apache.tomcat
copy

Then manage all logger s in the tomcat group:

logging.level.tomcat=TRACE
copy

Spring Boot also predefines two log groups, web and sql, as follows:

But in application Properties can only implement some very simple log configuration. If you want to implement more fine-grained log configuration, you need to use the native configuration of log implementation, such as classpath: Logback XML, classpath of Log4j: Log4j XML, etc. If these log configuration files exist in classpath, Spring Boot will automatically load these configuration files by default.

2.2 Logback configuration

2.2.1 basic configuration

There are two default Logback configuration file names:

  • logback.xml: this configuration file will be loaded directly by the log framework.
  • logback-spring.xml: this configuration file will not be loaded directly by the log framework, but Spring Boot will parse the log configuration. You can use the advanced Profile function of Spring Boot.

Spring Boot provides four default configuration files for Logback, which are located at org/springframework/boot/logging/logback /

  • defaults.xml: provides common log configuration, log output rules, etc.
  • console-appender.xml: using console_ LOG_ Add a ConsoleAppender to pattern.
  • file-appender.xml: add a RollingFileAppender.
  • base.xml: provided for compatibility with previous versions of Spring Boot.

If you need to customize logback XML file. You can use these default configuration files when customizing or not. A typical logback The XML file is as follows (resources/logback.xml):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>
copy

You can import the configuration files already provided by Spring Boot through include or customize them.

2.2.2 output to file

If you want to disable the log output of the console and instead output the log content to a file, we can customize a logback spring XML file and introduce the previously mentioned file appender XML file.

Like the following (resources/logback-spring.xml):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>
copy

2.3 Log4j configuration

If there is a dependency on Log4j2 under the classpath, Spring Boot will configure it automatically.

By default, there is no dependency on Log4j2 under classpath. If you want to use Log4j2, you can exclude the existing Logback and then introduce Log4j2, as follows:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
copy

The configuration of Log4j2 is relatively easy. Create a new Log4j2 in the resources directory XML file, as follows:

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="warn">
    <properties>
        <Property name="app_name">logging</Property>
        <Property name="log_path">logs/${app_name}</Property>
    </properties>
    <appenders>
        <console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d][%t][%p][%l] %m%n" />
        </console>
        <RollingFile name="RollingFileInfo" fileName="${log_path}/info.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" />
                <ThresholdFilter level="WARN" onMatch="DENY"
                                 onMismatch="NEUTRAL" />
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${log_path}/warn.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="WARN" />
                <ThresholdFilter level="ERROR" onMatch="DENY"
                                 onMismatch="NEUTRAL" />
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>

        <RollingFile name="RollingFileError" fileName="${log_path}/error.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="ERROR" />
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>
    </appenders>
    <loggers>
        <root level="info">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
            <appender-ref ref="RollingFileWarn" />
            <appender-ref ref="RollingFileError" />
        </root>
    </loggers>
</configuration>
copy

First, specify the application name and log file location in the properties node.

Then, different levels of logs are processed through several different rollingfiles. Logs at different levels will be output to different files and compressed according to their respective naming methods.

This configuration is more stylized, and the partners can save it and make it into IntelliJ IDEA template for daily use.

3. Summary

Well, this is the Spring Boot log shared by brother song and his friends. On the whole, it's not difficult. My friends can taste it carefully.

SongGe is currently recording the video of TienChin project ~ Spring Boot+Vue3 technology stack will be used, which will involve all kinds of fun technologies. My friends come to work with SongGe on a project with a completion rate of more than 90%. Here -- > TienChin project supporting video is coming.

Posted by dimitar on Fri, 13 May 2022 01:56:17 +0300