I heard that wechat search “Java fish” will change strong oh!

This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview

preface

Before, I mentioned the two most important methods for troubleshooting problems: checking logs and debugging. Breakpoint debugging was covered in the last installment, and this installment will cover logging. This article will start with Log4j and introduce slf4J, Log4j2, and logging in SpringBoot.

(a) the Log4j

Log4j consists of Loggers(Loggers), Appenders(outputs), and Layout(formatters), where Loggers control the level of log output and whether the log is output. Appenders specifies the log output mode (to the console or file); Layout Controls the output format of log information.

1.1 Importing Dependencies

First, we introduce the Log4j dependencies:

<! --log4j-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
Copy the code

1.2 the use of

Under the condition of without the custom configuration file, can through BasicConfigurator. Configure (); To set up a basic configuration, Log4j logs at six levels, using the middle four:

// Add the following code if there is no custom configuration information
BasicConfigurator.configure();
Logger logger=Logger.getLogger(Log4jTest.class);
// Logger log level
logger.fatal("fatal");  // A critical error, usually resulting in a system crash and termination
logger.error("error");  // Error message, does not affect system operation
logger.warn("warn");   // Warning message that a problem may occur
logger.info("info");    // Run information, such as database connection, network connection, etc
logger.debug("debug");  // Debugging information, generally used to print debugging information during development
logger.trace("trace");  // Keep track of all process information of the program
Copy the code

1.3 Customizing Configuration Information

By analyzing the source of LoggerManager, Log4j looks for configuration information in the log4j.xml and log4j.properties files. So we also need to create one of these two files when we customize the configuration file, and log4j.properties is now widely used

Here is a simple configuration:

The Logger controls the log output level and whether to output logs. You can set the lowest log output level by using the rootLogger.

Appender specifies how logs should be output, in this case to the console

Layout Controls the output format of log information. The simple format is used here

log4j.rootLogger=info,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
Copy the code

Log4j log configuration file

The Log4j configuration file is described in detail:

Log4j. RootLogger =info,console # appender to console log output. To name here and fill in the above the console log4j. Appender. The console = org.. Apache log4j. ConsoleAppender # specified message format layout log4j.appender.console.layout=org.apache.log4j.SimpleLayoutCopy the code

2.1 Common Layout

HTMLLayout: Format log output as HTML table style

SimpleLayout: Simple log output format

PatternLayout: You can output logs according to a custom format, or the default format if no transformation format is specified

Focus on the most commonly used PatternLayout

Usage:

log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern= [%p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
Copy the code

ConversionPattern is a format. The format above can be used directly. Other parameters are set as follows:

%m Output the log information specified in the code %p output priority %n newline %r Output the number of milliseconds it took for the application to start the log information % C Output the full name of the class to which the print statement belongs %t Output the full name of the thread that generated the log %d Output the current server time, default ISO8601, You can also specify a format such as %d{YYYY-MM-DD HH: MM :ss.SSS} %l The location of the output log time, including the class name, thread, and line number in the code clock %F The name of the file where the output log message was generated %L The line number in the output code %% Output a % symbolCopy the code

2.2 Common appenders

ConsoleAppender: Console output

FileAppender: Output to a file

JDBCAppender: output in the database

2.2.1 FileAppender

Describes some custom configurations of FileAppender file output

RootLogger =info,console,file # Omit console configuration # specify appender output as file Log4j. Appender. The file = org, apache log4j. FileAppender # of the specified file name and path log4j. Appender. File. The file = / logs/log4j. Log # specified log file of the character set log4j.appender.file.encoding=UTF-8. # log format log4j appenders. File. Layout = org). Apache log4j. PatternLayout log4j. Appender. File. Layout. The conversionPattern = [p] % % % r l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%nCopy the code

RollingFIleAppender or DailyRollingFileAppender can split the file appender according to the size of the file, set the maximum file contents and the number of files, and override the previous one if both are exceeded.

# # according to the file size split specified appender to file format output log4j appenders. RollingFile = org.. Apache log4j. RollingFileAppender # of the specified file name and path . Log4j appenders. RollingFile. The file = / logs/log4j, log # specified log file of the character set log4j. Appender. RollingFile. Encoding = utf-88. # log format log4j appenders. RollingFile. Layout = org). Apache log4j. PatternLayout Log4j. Appender. RollingFile. Layout. ConversionPattern = [p] % % r % l % d {MM - dd yyyy - HH: MM: ss. The SSS} % m % n # specifies the size of the log file content . Log4j appenders. RollingFile. MaxFileSize = 1 MB # specifies the amount of the log file log4j. Appender. RollingFile. MaxBackupIndex =10
Copy the code

DailyRollingFileAppender splits files by date and generates log files according to date rules.

# according to split the time rule # specified appender to file format output log4j appenders. DailyFile = org.. Apache log4j. DailyRollingFileAppender # of the specified file name and path . Log4j appenders. DailyFile. The file = / logs/log4j, log # specified log file of the character set log4j. Appender. DailyFile. Encoding = utf-88. # log format log4j appenders. DailyFile. Layout = org.. Apache log4j. PatternLayout log4j. Appender. DailyFile. Layout. ConversionPattern = [p] % % r % l % d {MM - dd yyyy - HH: MM: ss. The SSS} % m % n # date split in accordance with the rules of log4j appenders. DailyFile. DatePattern ='. 'yyyy-MM-dd
Copy the code

2.2.2 JDBCAppender

JdbcAppender is to write log data to the database through SQL statements, so you need to build a table in advance, and then insert data through insert statements.

#JDBCAppender
log4j.appender.dbLog=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.dbLog.layout=org.apache.log4j.PatternLayout
log4j.appender.dbLog.Driver=com.mysql.jdbc.Driver
log4j.appender.dbLog.URL=jdbc:mysql://localhost:3306/test
log4j.appender.dbLog.User=root
log4j.appender.dbLog.Password=123456
log4j.appender.dbLog.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('logDemo'.'%d{yyyy-MM-dd HH:mm:ss}'.'%p'.'%c'.'%F'.'%t'.'%L'.'%l'.'%m')
Copy the code

(3) the SLF4J

The Simple Logging Facade For Java is intended to provide a standard API framework For Java Logging, which is implemented by other Logging frameworks, such as Log4j. A typical SpringBoot project will use SLF4J as a facade in conjunction with Log4j. Next, the SLF4J binding log4j is used.

Note that SLF4J can only have one binding logging framework at a time, so some boot dependencies that rely on SpringBoot may conflict with the following dependencies. You only need the following dependencies to learn.

3.1 Introducing dependencies:

<! --slf4j-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.26</version>
</dependency>

<! Log4j - slf4j binding - >
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.12</version>
</dependency>

<! --log4j-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
Copy the code

3.2 Configuration File

Place the previous log4j.properties configuration file in the resource directory.

3.3 write code

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {

    private static final Logger LOGGER= LoggerFactory.getLogger(LogTest.class);
    @Test
    public void test(a){
        // Log level
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        // Use placeholder output
        String name="Java fish larvae";
        String age="24";
        LOGGER.info("name:{},age:{}",name,age); }}Copy the code

3.3 SLF4J bridge

If a project uses log4J as its logging framework and changes to Logback, slF4J simply removes the log4J dependency and adds the logback dependency, but there is a problem with this. Code previously written using Log4J will report an error.

Slf4j provides a tool called a bridge, which is compatible with the old logging framework by introducing the corresponding dependencies, and the Logger in the previous code is automatically replaced with the new logging framework:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.725.</version>
</dependency>
Copy the code

Note that bridge dependencies cannot appear with formal dependencies!

(4) Log4j2

The updated version of Log4j has the following major improvements:

1. Exception handling. In Logback, exceptions in the Appender are not perceived by the application, but in Log4j2, some exception handling mechanisms are provided.

2. Performance improvements: Logj2 has significant performance improvements over log4J and LogBack.

3. Automatic reloading configuration, referring to the logback design, of course provides automatic refresh parameter configuration, the most useful is that we can dynamically change the log level in production without restarting the application.

4. Garbage-free mechanism. Log4j2 can use a garbage-free mechanism designed by log4J2 in most cases to avoid GC caused by frequent log collection.

Log4j2 itself is both a logging facade and a logging framework, but Slf4j+Log4j2 is still a popular selection.

4.1 Importing Dependencies

<! --slf4j-->
<dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.7.26</version>
</dependency>

<! -- use log4j2 to bind -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.9.1</version>
</dependency>

<! --log4j2 log implementation -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.10.0</version>
</dependency>
Copy the code

4.2 configuration

When log4j2 starts up, it selects the log4j2.xml configuration file from the resource path. Here is a list of XML templates that you can use directly


      

<! --status="WARN" Log output level of the log framework itself monitorInterval="5" The interval between automatically loading configuration files is not less than 5 seconds -->
<Configuration status="WARN" monitorInterval="5">

    <! ${name} -- ${name} -->
    <properties>
        <property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %l %c{36} - %m%n</property>
        <property name="logDir">/logs</property>
    </properties>
    <! --Logger definition, which loggers to use -->
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="console"/>
            <AppenderRef ref="rolling_file"/>
        </Root>
    </Loggers>

    <Appenders>
        <! -- Define output to console -->
        <Console name="console" target="SYSTEM_OUT" follow="true">
            <! -- Console outputs only level and above information -->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout>
                <Pattern>${pattern}</Pattern>
            </PatternLayout>
        </Console>
        <! Appender for log files split according to certain rules -->
        <RollingFile name="rolling_file"
                     fileName="${logDir}/rolling-file.log"
                     filePattern="${logDir}/rolling-file_%d{yyyy-MM-dd}.log">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout>
                <Pattern>${pattern}</Pattern>
            </PatternLayout>
            <Policies>
                <! -->
                <TimeBasedTriggeringPolicy interval="1"/>
            </Policies>
            <! -- Log retention policy, set to seven days -->
            <DefaultRolloverStrategy>
                <Delete basePath="${logDir}/" maxDepth="1">
                    <IfFileName glob="rolling-file_*.log" />
                    <IfLastModified age="7d" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>
</Configuration>
Copy the code

4.3 Use of code

Slf4j is used as the logging facade, but the underlying logging framework is changed to log4j2

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {

    private static final Logger LOGGER= LoggerFactory.getLogger(LogTest.class);
    @Test
    public void test(a){
        // Log level
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        // Use placeholder output
        String name="Java fish larvae";
        String age="24";
        LOGGER.info("name:{},age:{}",name,age); }}Copy the code

(5) log4j2 Asynchronous logs

Log4j2 provides the asynchronous log function. After configuring asynchronous log, log events generated by the logger.info code are processed in an asynchronous thread, which does not affect the running speed of the system. The following describes the implementation of log4j2 asynchronous logs:

5.1 Importing Dependencies

<! -- Asynchronous log -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>We do</version>
</dependency>
Copy the code

5.2 Local Asynchronous Processing

Local asynchronous processing can be done in two ways. The first is to add asynchronous processing to an Appender:

There are two main steps, the first is to introduce Async tags in appenders and the second is to introduce asynchronous tags in Loggers

<Appenders>
    <! -- Define output to console -->
    <Console name="console" target="SYSTEM_OUT" follow="true">
    <! -- Internal configuration see above -->    
    </Console>
    <! Appender for log files split according to certain rules -->
    <RollingFile name="rolling_file"
                 fileName="${logDir}/rolling-file.log"
                 filePattern="${logDir}/rolling-file_%d{yyyy-MM-dd}.log">
      <! -- Internal configuration see above -->            
    </RollingFile>
    <! -- Change rolling_file to asynchronous -->
    <Async name="Async">
        <AppenderRef ref="rolling_file"/>
    </Async>
</Appenders>

<Loggers>
    <Root level="INFO">
        <AppenderRef ref="console"/>
        <! -- Introduce asynchronous appender-->
        <AppenderRef ref="Async"/>
    </Root>
</Loggers>
Copy the code

The second way is to add asynchronous logging definitions to Loggers:

<Loggers>

    <! -- Name specifies the name of the customized asynchronous Logger. Level Specifies the lowest level includeLocation="false" Specifies the line number of logs to be closed. Additivity ="false" Does not inherit the RootLogger object.
    <AsyncLogger name="com.javayz" level="trace" includeLocation="false" additivity="false">
        <AppenderRef ref="rolling_file"/>
    </AsyncLogger>

    <Root level="INFO">
            <AppenderRef ref="console"/>
            <AppenderRef ref="rolling_file"/>
    </Root>
</Loggers>
Copy the code

5.3 Global Asynchronism

Under the resource file to create a new configuration, named log4j2.com ponent. The properties, add in the file:

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
Copy the code

6. Use Logger in SpringBoot

Logging using SpringBoot requires the introduction of a startup dependency, which is included in the Web startup dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
Copy the code

Slf4j is used as the logging facade and Logback is used as the logging implementation by default in SpringBoot.

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringlogApplicationTests {
    public static final Logger LOGGER= LoggerFactory.getLogger(SpringlogApplicationTests.class);
    @Test
    void contextLoads(a) {
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info"); // The default level is info
        LOGGER.debug("debug");
        LOGGER.trace("trace"); }}Copy the code

Simple configuration of application to use:

Console =[%-5level] %d{YYYY-MM-DD HH: MM :ss} %c [%thread] % MSG %n # File =[%-5level] %d{YYYY-MM-DD HH: MM :ss} %c  [%thread] %msg %nCopy the code

If this configuration is too simple, you can create logback.xml (for logback) in the resource directory.

However, since log4j2 performs better than logback, log4j2 is still used in most projects. In this case, you need to change the default logback to log4j2. How to change: Remove the spring-boot-starter-logging dependency and introduce the log4j2 dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <! - not logging -- -- >
        <exclusion>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>
<! - introduce log4j2 -- -- >
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Copy the code

Create log4j2. XML in the resource directory and press Log4j2 to configure it

(7) Summary

Log configuration and use is very simple, but it is a good help to find problems, I am fish, and we will see you next time.