log4j and slf4j

1. log4j

1.1 basic usage

  • Import jar package
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  • Create the configuration file resources/log4j.properties
log4j.rootLogger=INFO,console
log4j.additivity.org.apache=true
#console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=INFO
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
  • Create test class
import org.apache.log4j.Logger;
class Test {
    static final Logger log = Logger.getLogger(Test.class);
    public static void main(String[] args) {
        log.info("hello this is log4j info log");
    }
}

1.2 configure logj.properties

To output logs, we must first have log objects. Where do these log objects output logs, console (stdout) or file? This requires setting the output location (appender), output format and content. This requires setting the output style (layout). After these settings, the configuration of log4j is finished.

The concept of log4j log level. Log level is the importance of log. Log4j log is divided into seven levels: ALL, DEBUG, INFO, WARN, ERROR, FATAL and OFF. From left to right, the level is from low to high. Grading is to set the threshold for log output. Only logs with a level equal to or higher than this threshold can be output

1.2.1 logger

Log instance is the Logger object instantiated in the code. Format:

log4j.rootLogger=LEVEL,appenderName1,appenderName2,...
log4j.additivity.org.apache=false: Indicates that it will not be in the parent logger of appender Output in, default true

This is the configuration of the global logger. LEVEL is used to set the log LEVEL. Appendname defines the log output. The console in the example is a log output

A clearer example is given below to configure the Logger objects instantiated in all classes under the com.demo.test package

log4j.logger.com.demo.test=DEBUG,test
log4j.additivity.com.demo.test=false

1.2.2 appender

Log outputter, specifying the output location of logger, format:

log4j.appender.appenderName = className

appender has five options

org.apache.log4j.ConsoleAppender((console)
org.apache.log4j.FileAppender((file)
org.apache.log4j.DailyRollingFileAppender((one log file per day)
org.apache.log4j.RollingFileAppender(When the file size reaches the specified size, a new file is generated)
org.apache.log4j.WriterAppender(Send log information in stream format to any specified place)

Each appender has several configuration items:

  • ConsoleAppender (common console)

    #Specifies the minimum output level of log information. The default is DEBUG
    Threshold=WARN 
     #Indicates that all messages will be output immediately. If it is set to false, it will not be output. The default value is true
    ImmediateFlush=true
    #The default value is System.out
    Target=System.err 
    
  • FileAppender file

    # Specifies the minimum output level of log information. The default is DEBUG
    Threshold=WARN
    #Indicates that all messages will be output immediately. If it is set to false, it will not be output. The default is true
    ImmediateFlush=true 
    # True indicates that the message is added to the specified file. false overwrites the content of the specified file. The default is true
    Append=false 
    # Specifies that the message is output to the logging.log4j file
    File=D:/logs/logging.log4j 
    
  • Daily rolling file appender (commonly used) generates a log file every day

    # Specifies the minimum output level of log information. The default is DEBUG
    Threshold=WARN 
    #Indicates that all messages will be output immediately. If it is set to false, it will not be output. The default is true
    ImmediateFlush=true 
    #True indicates that the message is added to the specified file. false overwrites the content of the specified file. The default is true
    Append=false
    # Specifies that the current message is output to the logging.log4j file
    File=D:/logs/logging.log4j 
    # Scroll the log file once a month, that is, generate a new log file every month.
    # The log file name of the current month is logging.log4j, and the log file name of the previous month is logging.log4j.yyyy-MM
    DatePattern='.'yyyy-MM 
    
    #In addition, you can specify to scroll log files by week, day, hour, minute, etc. the corresponding format is as follows:
    # 1) '.' yyyy mm: Monthly
    # 2) '.' yyyy WW: Weekly
    # 3) '.' yyyy MM DD: every day
    # 4)'.'yyyy-MM-dd-a: twice a day
    # 5) '.' yyyy MM DD HH: per hour
    # 6) '.' yyyy MM DD HH mm: per minute
    
  • RollingFileAppender generates a new file when the file size reaches the specified size

    # Specifies the minimum output level of log information. The default is DEBUG
    Threshold=WARN 
    # Indicates that all messages will be output immediately. If it is set to false, it will not be output. The default is true
    ImmediateFlush=true 
    # True indicates that the message is added to the specified file. false overwrites the content of the specified file. The default is true
    Append=false 
    # Specifies that the message is output to the logging.log4j file
    File=D:/logs/logging.log4j 
    # The suffix can be KB,MB or GB.
    # When the log file reaches this size, it will automatically scroll, that is, move the original content to the logging.log4j.1 file
    MaxFileSize=100KB 
    # Specifies the maximum number of scrolling files that can be generated
    # For example, if it is set to 2, two rolling files of logging.log4j.1, logging.log4j.2 and one logging.log4j file can be generated
    MaxBackupIndex=2 
    

1.2.3 layout

Specify the output content of logger, format:

log4j.appender.appenderName.layout = className

There are four options for layout

org.apache.log4j.HTMLLayout(with HTML Tabular layout)
org.apache.log4j.PatternLayout((layout mode can be specified flexibly)
org.apache.log4j.SimpleLayout(Level and information string containing log information)
org.apache.log4j.TTCCLayout((including log generation time, thread, category and other information)

layout also has configuration items:

  • HTMLLayout
#Output the java file name and line number. The default is false
LocationInfo = true 
# The default value is Log4J Log Messages
Title = My Logging 
  • PatternLayout (the most commonly used configuration)
# Sets the format in which messages are displayed
ConversionPattern = %m%n 

The parameters for formatting are described below

%p: Priority of output log information, i.e DEBUG,INFO,WARN,ERROR,FATAL
%d: Output the date or time of the log time point. The default format is ISO8601,You can specify a format, such as:%d{yyyy/MM/dd HH:mm:ss,SSS}
%r: Output from application startup to log The number of milliseconds the message took
%t: Output the name of the thread that generated the log event
%l: The location of the output log event, equivalent to%c.%M(%F:%L)A combination of class names, methods, file names, and the number of lines in the code
%c: The category to which the output log information belongs is usually the full name of the class
%M: Output the name of the method that generates log information
%F: The file name where the output log message is generated
%L: Line number in output code
%m: Output the specific log information specified in the code
%n: Output a carriage return line feed, Windows Platform is"rn",Unix Platform is"n"
%x: Outputs the associated with the current thread NDC(Nested diagnostic environment)
%%: Output a"%"character

1.3 log4j complete configuration example

This example configures some common log outputs

log4j.rootLogger=DEBUG,console,logFile,rollingFile,dailyFile
log4j.additivity.org.apache=true
  • console log exporter

    # Console
    log4j.appender.console=org.apache.log4j.ConsoleAppender
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.ImmediateFlush=true
    log4j.appender.console.Target=System.err
    log4j.appender.console.layout=org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
    
  • File logFile log exporter

    # Log file (logFile)
    log4j.appender.logFile=org.apache.log4j.FileAppender
    log4j.appender.logFile.Threshold=DEBUG
    log4j.appender.logFile.ImmediateFlush=true
    log4j.appender.logFile.Append=true
    log4j.appender.logFile.File=D:/logs/log.log4j
    log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
    log4j.appender.logFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
    
  • Rolling file log exporter

    # Rollingfile
    log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
    log4j.appender.rollingFile.Threshold=DEBUG
    log4j.appender.rollingFile.ImmediateFlush=true
    log4j.appender.rollingFile.Append=true
    log4j.appender.rollingFile.File=D:/logs/log.log4j
    log4j.appender.rollingFile.MaxFileSize=200KB
    log4j.appender.rollingFile.MaxBackupIndex=50
    log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
    log4j.appender.rollingFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
    
  • Periodically scrolling files dailyFile log exporter

    log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.dailyFile.Threshold=DEBUG
    log4j.appender.dailyFile.ImmediateFlush=true
    log4j.appender.dailyFile.Append=true
    log4j.appender.dailyFile.File=D:/logs/log.log4j
    log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
    log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
    log4j.appender.dailyFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
    

2. Facade mode

In Alibaba Java development manual, there is a "mandatory" requirement in one specification:

[mandatory] the API in the log system (Log4j, Logback) cannot be directly used in the application, but the API in the log framework SLF4J should be used. The log framework in facade mode is used, which is conducive to the unification of maintenance and log processing methods of various classes.

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

Log facade is a typical application of facade mode.

Facade Pattern, also known as appearance pattern, its core is that the external communication with a subsystem must be carried out through a unified appearance object to make the subsystem easier to use.

In the field of software development, there is a saying that any problem in the field of computer science can be solved by adding an indirect middle layer. The facade model is a typical practice of this sentence.

3. slf4j is used in combination with log4j

What is slf4j?

slf4j only defines a set of log interfaces, but does not provide any implementation.

In that case, why use slf4j? Didn't log4j meet the requirements?

Yes, log4j meets the requirements. However, log4j is not the only logging framework. You prefer log4j. Some people may prefer logback, and some even use the logging framework provided by jdk. In this case, if you want to rely on other people's jars, the whole system uses two logging frameworks. If you rely on 10 jars, the logging framework used by each jar is different, If a project uses 10 log frames, it's a mess!

If your code uses the slf4j interface, you prefer to use log4j for the specific log implementation framework, and other people's code also uses the slf4j interface. The specific implementation is unknown. When you rely on other people's jar package, the whole project will only use the log4j log framework. This is a typical facade mode application. It has the same idea as the jvm. We write log code for slf4j, Slf4j handles the differences between specific log implementation frameworks. Just as we write java code for the jvm, the jvm handles the differences between operating systems. As a result, it can be written in one place and run everywhere. Besides, more and more open source tools are being used slf4j now.

  • Import slf4j jar package

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>
    
  • Import the jar package associated with slf4j and log4j

    Through this jar package, the call to the slf4j interface is converted to the call to log4j. Different log implementation frameworks and conversion tools are different

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.21</version>
    </dependency>
    
  • use

    Originally:

    import org.apache.log4j.Logger;
    class Test {
        static final Logger log = Logger.getLogger(Test.class);
        public static void main(String[] args) {
            log.info("hello this is log4j info log");
        }
    }
    

    Now:

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    class Test {
        Logger log = LoggerFactory.getLogger(Test.class);
        public static void main(String[] args) {
            log.info("hello, my name is {}", "chengyi");
        }
    }
    

    The dependent Logger has changed, and slf4j's api can also use placeholders, which is very convenient

4. Development skills

4.1 select the appropriate log level

There are five common log levels: error, warn, info, debug and trace. In daily development, we need to select the appropriate log level. Don't backhand or print info.

  • Error: error log, which refers to serious errors that affect normal business and require operation and maintenance configuration monitoring;
  • warn: warning log. It is a general error that has little impact on the business, but needs development attention;
  • info: information log, which records the key information of troubleshooting problems, such as call time, input and output parameters, etc;
  • Debug: the runtime data in the key logic used to develop debug;
  • trace: the most detailed information. Generally, this information is only recorded in the log file.

4.2 when the log level is low, judge the log switch

For low log levels such as trace and debug, you must judge the switch of log level.

Positive example:

User user = new User(1, "Jack", 18);
if (log.isDebugEnabled()) {
    logger.debug("userId is: {}", user.getId());
}

Because there are the following log Codes:

logger.debug("Processing trade with id: " + id + " and user: " + user);

If the configured log level is warn, the above log will not be printed, but the string splicing operation will be performed. If the user is an object, the toString() method will be executed, which wastes system resources. After the above operations are performed, the final log will not be printed. Therefore, it is recommended to add the log switch to judge.

4.3 use parameter placeholder {} instead of + splicing

slf4j supports placeholder {}. Using the + operator to splice strings has a certain performance loss, while using placeholder {} is only a replacement action

logger.debug("user id = {}, name = {}", user.getId(), user.getName());

4.4 do not use e.printStackTrace()

Generally, e.getMessage() can't get all the error information. You need to use e.printStackTrace() to view the complete error information

However:

  • e. The stack log printed by printstacktrace() is interleaved with the business code log. It is usually inconvenient to check the exception log.
  • e. The string generated by printstacktrace() statement records stack information. If the information is too long and too much, the memory block where the string constant pool is located has no space, that is, the memory is full, then the user's request is stuck
  • e. The return value of printstacktrace() method is void, which can only be output on the console. It is recommended to output it separately to the error.log file

Positive example:

try {
    // to do
} catch (Exception e) {
    logger.error("Something's wrong", e);
} 

4.5 it is forbidden to enable debug in the online environment

Because there are many debug logs in general systems, and debug logs are widely used in various frameworks, opening debug online may fill the disk soon, affecting the normal operation of the business system.

4.6 log file separation

  • Separate different types of logs, such as normal business log or error.log, which can be printed into a file separately
  • It can also be printed into different log files according to different business modules, so that it will be more convenient for us to troubleshoot problems and make data statistics

Keywords: Java log4j slf4j

Added by MarCn on Sat, 02 Oct 2021 01:38:50 +0300