Detailed explanation of Java logging framework

Log frame

Basic concepts of log

Log: in the computer field, a log file is a file that records events that occur in the running operating system or other software, or records messages sent between users of network chat software.

Logging: refers to the behavior of saving logs. The simplest way is to write the logs to a single log file.

Log function:
The log records the time, place, status and other relevant information of the system behavior, which can help us understand and monitor the system status, timely remind us to deal with errors or close to a dangerous state, and help us quickly locate, diagnose and solve problems when there are problems in the system.

Overview of common logging frameworks in Java

Common log frameworks in Java programs can be divided into two categories:

  • Abstract facade framework without concrete implementation, such as common logging and SLF4J
  • Specific implementation frameworks, such as Log4j, Log4j 2, Logback, JUL

Java common logging framework history:
In early 1996, the European secure electronic market project team decided to write its own program tracking API. After continuous improvement, this API has finally become a very popular Java logging package, namely Log4j. Later, Log4j became a member of the Apache foundation project.
During this period, Log4j almost became the logging standard of the Java community. It is said that the Apache foundation once suggested sun to introduce Log4j into the Java standard library, but sun refused.
2002 Java 1 4 release, Sun launched its own log library JUL(Java Util Logging), whose implementation basically imitates the implementation of log4j. Before JUL came out, log4j has become a mature technology, which makes log4j occupy a certain advantage in selection.
Then, Apache launched Jakarta Commons Logging. JCL only defines a set of logging interfaces (it also provides a simple implementation of Simple Log) to support the implementation of dynamically loading logging components at runtime. In other words, in your application code, you only need to call the interface of Commons Logging, and the underlying implementation can be log4j or Java Util Logging.
Later (2006), Ceki G ü lc ü did not adapt to the working mode of Apache and left Apache. Then he created two projects, slf4j (log facade interface, similar to common logging) and Logback (implementation of slf4j), and returned to Sweden to create QOS company. The description of Logback on the QOS official website is as follows: The Generic, reliable, fast & flexible logging framework (a general, reliable, fast and flexible logging framework).
Today, the Java logging field is divided into two camps: the common logging camp and the SLF4J camp.
Common logging is shrouded in the Apache tree and has a large user base. But there is evidence that the form is changing. At the end of 2013, someone analyzed 30000 projects on GitHub and counted the 100 most popular Libraries. It can be seen that slf4j's development trend is better:
Apache saw the momentum of being overtaken by logback, and rewritten log4j 1.0 on July 2012 x. A new project log4j 2 was established. Log4j 2 has all the features of logback.

Relationship between common Java log frameworks:
Great changes have taken place between log4j2 and log4j1. Log4j2 is incompatible with log4j1.
Common logging and Slf4j are log facade (facade mode is a software design mode commonly used in software engineering, also known as facade mode and appearance mode. It provides a unified high-level interface for a group of interfaces in the subsystem, making the subsystem easier to use). log4j and Logback are specific log implementation schemes. It can be simply understood as the implementation of interfaces and interfaces. Only the interface needs to be paid attention to when calling There is no need to pay attention to the specific implementation to achieve decoupling.
Slf4j is used in combination with Logback, and common logging is used in combination with Log4j.
Logback must be used with Slf4j. Since logback and Slf4j are the same author, their compatibility is self-evident.

Log facade frame:

Relationship between log facade and log implementation:

Log facade is a typical application of appearance mode. The log facade framework provides a set of interfaces for log related functions without specific implementation, which calls the specific implementation framework for logging. In other words, the log facade is naturally compatible with the log implementation framework. Typical log interfaces are common logging and SLF4J.

  • Commons Logging:
    Apache Commons Logging is a Java based logging utility and a programming model for logging and other toolkits. It provides API, log implementation and wrapper implementation through other tools.

  • SLF4J:
    Java simple log facade The Simple Logging Facade for Java (SLF4J for short) is a set of interface programs that package the Logging framework, which is implemented in appearance mode. The Logging framework to be used can be determined during software deployment. At present, it mainly supports Java Logging API, Log4j, Logback and other frameworks. It is published under MIT authorization. The author of SLF4J is Ceki G ü lc ü, the author of Log4j and Logback

  • Implementation mechanism of common logging and SLF4J:

    • Common logging implementation mechanism:
      Common logging uses its own ClassLoader to find and load local specific implementations during program running through a dynamic search mechanism. See commons logging - *. For detailed policies Org. Jar package apache. commons. logging. impl. LogFactoryImpl. Java file. Because different OSGi plug-ins use independent classloaders, this mechanism of OSGi ensures that plug-ins are independent of each other, and its mechanism limits the normal use of common logging in OSGi.
    • Slf4j implementation mechanism:
      Slf4j is statically bound to the local LOG library during compilation, so it can be used normally in OSGi. It is by looking up the classpath under org slf4j. impl. Staticloggerbinder and binding work are all carried out in this class.

Advantages of log facade:
Log facade is a bridge between the specific log framework and the system. Through the application of log facade framework, the decoupling between the system and the specific log framework is realized. No matter how the specific log framework changes, it will not affect the recording function of the system log, and there is no need to change the system code, which conforms to the opening and closing principle.

Log implementation framework:

  • JUL: Java Util Logging, from java1 4 since the official log implementation.

  • Log4j: Apache Log4j is a Java based logging tool. It was pioneered by Ceki G ü lc ü and is now a project of the Apache Software Foundation.

  • Log4j2: Apache Log4j 2 is an upgraded product of log4j developed by apache and is not compatible with log4j.

  • Logback: logback is a log framework. It is the same author as Log4j and is written by Ceki G ü lc ü.

Selection of Java log framework:

  • Cost considerations: Logback documents are free. All documents of Logback are fully provided free of charge. Unlike Log4J, which only provides some free documents, users need to buy paid documents.
  • Resource overhead: common logging is more expensive than SLF4J
  • Performance: logback has better performance than log4j and Log4j2. Logback claims that the performance of some key operations, such as determining whether to record a log statement, has been significantly improved. This operation takes 3 nanoseconds in logback and 30 nanoseconds in log4j. Logback also creates loggers faster: 13 milliseconds, compared with 23 milliseconds in log4j. More importantly, it only takes 94 nanoseconds to obtain existing loggers, while log4j takes 2234 nanoseconds, reducing the time to 1 / 23. Compared with JUL, the performance improvement is also significant.

JUL log quick start (not commonly used, just understand)

  • The full name of JUL is Java Util Logging, which is the native logging framework of Java. Compared with other logging frameworks, it is easy to use, easy to learn, and can be used flexibly in small applications.

  • JUL architecture:

    • Logger: called a logger, an application program publishes log information by obtaining a logger object and calling its API. Logger is usually the entry program for applications to access the logging system
    • Handler: each Logger will be associated with a group of handlers. The Logger will submit the log to the associated handler for processing, and the handler is responsible for recording the log. Handler is an abstraction here. Its specific implementation determines the location of logging, which can be console, file, other logging services on the network or operating system logs
    • Formatter: also known as Layout, it is responsible for converting and formatting the data in log events. The formatter determines the final form of data in a log record
    • Level: each log message has an associated log level. This level provides a rough guide to the importance and urgency of log messages
    • Filter: filter, which information will be recorded and which information will be let go according to needs
  • JUL quick start:

    package com.xukai;
    
    import org.junit.Test;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public class JULTest {
        @Test
        public void quickstart() throws Exception {
            // 1. Get logger object
            Logger logger = Logger.getLogger("com.xukai.JULTest");
            // 2. Output logging
            logger.info("Hello, JUL");
    
            // Use the general log method for logging
            logger.log(Level.INFO, "INFO Level message");
    
            // Output variable values as placeholders
            String name = "Xukai";
            int age = 21;
            logger.log(Level.INFO, "User information:{0}, {1}", new Object[]{name, age});
        }
    }
    

    Output:

    August 23, 2021 11:39:22 am com xukai. JULTest quickstart
    Info: Hello, JUL
    August 23, 2021 11:39:22 am com xukai. JULTest quickstart
    Message: INFO Level message
    August 23, 2021 11:39:22 am com xukai. JULTest quickstart
    Information: user information: Xukai, 21

  • JUL log level:

    /**
     * java.util.logging.Level Part of the source code display
     */
    
    // Log switch
    public static final Level OFF = new Level("OFF", Integer.MAX_VALUE, defaultBundle);
    // error level
    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
    // Warning level
    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
    // Message level
    public static final Level INFO = new Level("INFO", 800, defaultBundle);
    // Configuration information level
    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
    // debug record level (three different granularity)
    public static final Level FINE = new Level("FINE", 500, defaultBundle);
    public static final Level FINER = new Level("FINER", 400, defaultBundle);
    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
    // Log switch
    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
    

    It can be seen that JUL has nine log levels: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, filter, last and ALL

  • Configure JUL through configuration file:

    /**
       * Load the custom configuration file under resources
       * @throws Exception
       */
    @Test
    public void testSelfDefinedConfig() throws Exception {
        // 1. Read the configuration file
        InputStream resource = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        // 2. Create LogManager
        LogManager logManager = LogManager.getLogManager();
        // 3. Load the configuration file through the LogManager object
        logManager.readConfiguration(resource);
        // 4. Create loggers
        Logger logger = Logger.getLogger("com.xukai");
        // 5. Log
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }
    

    Profile content:

    # The default processor specified by the RootLogger top-level parent element is: ConsoleHandler
    handlers = java.util.logging.ConsoleHandler
    # The default log level of the top-level parent element of RootLogger is INFO, which is set to ALL here
    .level = ALL
    
    # Configuration of FileHandler
    java.util.logging.FileHandler.pattern = %h/java%u.log
    java.util.logging.FileHandler.limit = 50000
    java.util.logging.FileHandler.count = 1
    java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
    
    # Configuration of ConsoleHandler
    java.util.logging.ConsoleHandler.level = ALL
    java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
    

Log4j log quick start (almost obsolete, just understand)

Log4j is an open source project of Apache. By using log4j, we can control that the destinations of log information transmission are console, files, GUI components, even socket server, NT event recorder, UNIX Syslog daemon, etc; We can also control the output format of each log; By defining the level of each log information, we can control the log generation process in more detail. The most interesting thing is that these can be flexibly configured through a configuration file without modifying the application code.

  • Quick start code example:

    /**
       * Quick start cases
       * @throws Exception
       */
    @Test
    public void testQuickStart() throws Exception {
        // Initialize the configuration information and configure it directly in quickStart temporarily
        BasicConfigurator.configure();
    
        // 1. Get logger object
        Logger logger = Logger.getLogger(Logger.class);
        // 2. Log record output
        logger.info("Hello, log4j");
    }
    

    Output:

    0 [main] INFO org.apache.log4j.Logger - Hello, log4j

  • Log4j log level

    • FATAL: indicates a system level error that needs to be processed immediately. When this error occurs, it indicates that the service has been unavailable to some extent, and the system administrator needs to intervene immediately

    • ERROR: this level of ERROR also needs to be handled immediately, but the urgency is lower than the FATAL level. When the ERROR error occurs, the normal access of the user has been affected

    • WARN: this log indicates that the system may or may not have problems, such as network fluctuations. For those cases that are not errors at present, but will become errors if they are not handled in time, they can also be recorded as a warning log. For example, the disk usage of a storage system exceeds the threshold, or the storage quota of a user in the system is running out, etc

    • INFO: this kind of log records the normal operation status of the system, such as the initialization of a subsystem, the successful execution of a request, etc

    • DEBUG or TRACE: the specific specifications of these two logs should be defined by the project team. The main function of this level of log is to accurately record the operation status of each step of the system. Through this kind of log, you can view the execution process of each step of an operation, and accurately locate what operation, what parameters and what order caused some errors. It can also diagnose the problem through the DEBUG (or TRACE) log without reproducing the error. It should be noted that the DEBUG log also needs to standardize the log format. It should be ensured that in addition to the developers who record the log, other operation and maintenance personnel and testers can also locate the problem through the DEBUG (or TRACE) log

    Log level priority:
    ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF

    Code example:

    /**
       * log level
       * @throws Exception
       */
    @Test
    public void testLevel() throws Exception {
        BasicConfigurator.configure();
    
        Logger logger = Logger.getLogger(Logger.class);
    
        // log level
        logger.fatal("fatal");
        logger.warn("warn");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
    

    Output:

    0 [main] FATAL org.apache.log4j.Logger - fatal
    1 [main] WARN org.apache.log4j.Logger - warn
    1 [main] INFO org.apache.log4j.Logger - info
    1 [main] DEBUG org.apache.log4j.Logger - debug

    Obviously, the default log level is the debug level

  • Log4j component

    • Appender
      Appender is used to specify where the log is output, and the output destination of the log can be specified at the same time. Log4j commonly used output destinations are as follows:

      Output typeeffect
      ConsoleAppenderOutput log to console
      FileAppenderOutput log to file
      DailyRollingFileAppenderOutput the log to a log file, and output to a new file every day
      RollingFileAppenderOutput the log information to a log file and specify the file size. When the file size reaches the specified size, the file will be renamed automatically and a new file will be generated at the same time
      JDBCAppenderSave the log information to the database
    • Layout

      The Layout is used to control the format of log output content, so that we can output logs in various required formats. Log4j commonly used layouts are:

      Layout typeeffect
      HTMLLayoutFormat the log output to HTML tabular form
      SimpleLayoutSimple log output format. The print format is (info - message)
      PatternLayoutThe most powerful formatter can output the log according to the custom format. If the conversion format is not specified, the default conversion format is used

      Format of Layout:

      log4j uses the print format of printf function similar to C language to format log information. The specific placeholders and meanings are as follows:

      Format charactermeaning
      %mOutput the log information specified in the code
      %pOutput priority
      %nOutput newline
      %rOutput the number of milliseconds spent from application startup to outputting this log information
      %cOutput the fully qualified name of the class to which the print statement belongs
      %tOutput the full name of the thread that generated the log
      %dThe current time of the output server is ISO8601 by default. You can also customize the format
      %lThe location where the output log time occurs, including class name, thread and the number of lines in the code, such as test main(Test.java:10)
      %FThe name of the file where the output log message is generated
      %LLine number in output code
      %%Output a '%' character

      You can also add modifiers between% and characters to control the minimum width, maximum width, and text alignment:

      Format stringmeaning
      %5cOutput the full name of the class. The minimum width is 5. If it is not long enough, align it right
      %-5cOutput the full name of the class. The minimum width is 5. If it is not long enough, add a space and align it to the left
      %.5cOutput the full name of the class. The maximum width is 5. If it is too long, the super long part will be cut off
      %20.30cWhen the length is less than 20, fill in the right alignment of the space, and when the length is greater than 30, cut off the super long part
  • Configure Log4j through configuration file

    /**
       * Custom profile
       * @throws Exception
       */
    @Test
    public void testSelfDefinedConfig() throws Exception {
        // The log4j. Log under resource is read by default Properties configuration file
        // BasicConfigurator.configure();
        Logger logger = Logger.getLogger(Logger.class);
    
        logger.fatal("fatal");
        logger.warn("warn");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
    

    Profile content:

    # Configure Logger level and type (level, type)
    log4j.rootLogger = trace, console
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.layout = org.apache.log4j.SimpleLayout
    

Commons logging log facade (now obsolete, just understand)

The full name is Jakarta common logging, which is a general logging API provided by Apache. It provides a unified interface for "all Java log implementations". It also provides a log implementation itself, but the function is very weak (SimpleLog), so it is generally not used alone. It allows developers to use different specific log implementation tools, such as Log4j, JUL, etc.

  • Architecture diagram

  • Significance of using log facade frame

    • It conforms to the principle of dependency inversion and is interface oriented, no longer depends on specific implementation, and reduces the coupling to the log implementation framework
    • The project can flexibly switch the log framework by importing different log implementation classes
    • Unified API for developers to learn and use
    • Unified configuration is convenient for project log management
  • Common logging principle

    There are two major components in commons logging: Log interface and LogFactory factory class. Commons logging dynamically loads Log implementation classes through LogFactory, which can be JULLogger, Log4jLogger, etc.

    Priority of log implementation framework in source code: log4j > Jul > simplelog

Slf4j log facade (current mainstream, need to master)

  • The full name of slf4j is Simple Logging Facade For Java, that is, java simple logging facade. Its birth is mainly to provide a set of standard and standardized API framework for Java log access. Its main significance is to provide interfaces. The specific implementation can be handed over to other implementation frameworks, such as Log4j or Logback. Slf4j itself also provides a relatively simple implementation, but it is rarely used. For general Java projects, the log framework will choose slf4j API as the facade, coupled with specific implementation frameworks (Log4j, Logback, etc.), and use a bridge to complete the bridging.

    Official website: https://www.slf4j.com

    Slf4j is the mainstream log facade at present. Slf4j is basically used as our log system in current projects. Slf4j mainly provides two functions:

    • Binding of log framework
    • Bridging of log frame
  • Slf4j getting started

    • Import Maven coordinates:

      <!--    Slf4j Facade    -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.5</version>
      </dependency>
      <!--    Slf4j realization    -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-simple</artifactId>
          <version>1.7.5</version>
      </dependency>
      
    • Write a Demo:

      public class Slf4jTest {
      
          // Static Logger object
          public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);
      
          /**
           * quick get start
           * @throws Exception
           */
          @Test
          public void testQuickStart() throws Exception {
              LOGGER.error("error");
              LOGGER.warn("warn");
              LOGGER.info("info");
              LOGGER.debug("debug");
              LOGGER.trace("trace");
      
              // Output log information using placeholders
              String name = "xukai";
              int age = 21;
              LOGGER.info("User:{},{}", name, age);
      
              // Output daily system information
              try {
                  int i = 1/0;
              } catch (Exception e) {
                  LOGGER.error("Exception occurred:{}", e.getMessage());
              }
          }
      }
      
  • Slf4j log binding

    • Slf4j API does not bind to the implementation framework: output to / dev/null, that is, no output
    • Slf4j API binding Logback: import Logback core Jar or Logback classic jar
    • Slf4j API binding Log4j: if an adapter is required, import Log4j first Jar to implement the framework, and then import slf4j-log412 Jar adapter
    • Slf4j API binding JUL: import JUL-to-slf4j Jar adapter is enough
    • Slf4j API binding SimpleLog: import slf4j simple jar
    • Slf4j API binding no operation: import slf4j NOP Jar, output to / dev/null (equivalent to the log switch)
  • Slf4j Bridge

    • Application scenario: replace Log4j in the old project with Slf4j+Logback
    • Specific implementation: import log4j-over-slf4j Jar Bridge
    • Note:
      • Bridge and adapter cannot appear at the same time
      • All bridging is valid only for Logger logger objects. If the internal configuration class or object such as Appender or Filter is invoked in the program, it will not be effective.

Logback log framework (current mainstream, need to master)

Logback is another open source log component designed by the founder of Log4j, and its performance is better than Log4j

Official website: https://logback.qos.ch/

  • Main modules of Logback

    • Logback core: the basic module of the other two modules
    • Logback classic: it is an improved version of log4j, and it fully implements the Slf4j API
    • Logback access: the access module is integrated with the Servlet container and provides the function of accessing logs through Http
  • Getting started with Logback

    1. Import Maven coordinates:

      <dependencies>
      <!--    Slf4j Facade    -->
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
                  <version>1.7.5</version>
              </dependency>
          
      <!--    Logback    -->
              <dependency>
                  <groupId>ch.qos.logback</groupId>
                  <artifactId>logback-classic</artifactId>
                  <version>1.2.3</version>
              </dependency>
          </dependencies>
      
    2. Write a Demo:

      public class LogbackTest {
      
          public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);
      
          /**
           * quick get start
           * @throws Exception
           */
          @Test
          public void testQuickStart() throws Exception {
              LOGGER.error("error");
              LOGGER.warn("warn");
              LOGGER.info("info");
              LOGGER.debug("debug");
              LOGGER.trace("trace");
          }
      }
      
  • Logback profile

    • Logback will read the following types of configuration files in turn (if none exist, the default configuration will be adopted):

      • logback.groovy
      • logback-test.xml
      • logback.xml
    • Relationship between Logback components:

      1. Logger: a logger. After it is associated with the corresponding context of the application, it is mainly used to store log objects. It can also define log types and levels
      2. Appender: used to specify the destination of log output. The destination can be console, file, database, etc
      3. Layout: it is responsible for converting events into formatted string log information. In Logback, the layout object is encapsulated in the encoder
    • Logback configuration details:

      <?xml version="1.0" encoding="UTF-8" ?>
      <configuration>
          <!--
              Log output format pattern definition:
                  %-5level
                  %d{yyyy-MM-dd HH:mm:ss.SSS}date
                  %c The full name of the class
                  %M by method
                  %L Is the line number
                  %thread Thread name
                  %m or%msg For information
                  %n Newline character
            -->
          <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n"></property>
      
          <!--  Specify the storage path of the log file  -->
          <property name="log_dir" value="logs/"></property>
      
          <!--  Console log output Appender  -->
          <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
              <!--    Console output stream object, default to System.out,Change here to System.err    -->
              <target>System.err</target>
              <!--    Log output format configuration    -->
              <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                  <pattern>${pattern}</pattern>
              </encoder>
          </appender>
      
          <!--  Log file output Appender  -->
          <appender name="file" class="ch.qos.logback.core.FileAppender">
              <!--    Save path of log file    -->
              <file>${log_dir}/logback.log</file>
              <!--    Log message format configuration    -->
              <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                  <pattern>${pattern}</pattern>
              </encoder>
          </appender>
      
          <!--  html Format output Appender  -->
          <appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
              <!--    Save path of log file    -->
              <file>${log_dir}/logback.html</file>
              <!--    html Message format configuration    -->
              <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                  <layout class="ch.qos.logback.classic.html.HTMLLayout">
                      <!--     html The format needs to be rewritten without spaces and other symbols     -->
                      <pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%m</pattern>
                  </layout>
              </encoder>
          </appender>
      
          <!--  Log splitting and archive compression Appender object  -->
          <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
              <!--    Save path of log file    -->
              <file>${log_dir}/roll_logback.log</file>
              <!--    Log message format configuration    -->
              <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                  <pattern>${pattern}</pattern>
              </encoder>
      
              <!--    Specify split policy    -->
              <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                  <!--    Declare split file names by time and compression format    -->
                  <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-mm-ss}.log%i.gz</fileNamePattern>
                  <!--    Split by file size    -->
                  <maxFileSize>1MB</maxFileSize>
              </rollingPolicy>
      
              <!--    Log level filter    -->
              <filter class="ch.qos.logback.classic.filter.LevelFilter">
                  <!--    Log filter level    -->
                  <level>ERROR</level>
                  <!--    If the conditions are met ACCEPT    -->
                  <onMatch>ACCEPT</onMatch>
                  <!--    Do not meet DENY    -->
                  <onMisMatch>DENY</onMisMatch>
              </filter>
          </appender>
      
          <!--  Asynchronous log Appender,Used to solve log4j Performance bottleneck, the bottom layer is blockingQuene -->
          <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
              <!--    It is abstract and needs to specify the specific implementation Appender    -->
              <appender-ref ref="rollFile"/>
          </appender>
      
          <!--
              RootLogger You can specify the output level of the log in,
              Default to DEBUG,
              Optional TRACE,DEBUG,INFO,WARN,ERROR,ALL and OFF
           -->
          <root level="ALL">
              <appender-ref ref="console"/>
              <appender-ref ref="rollFile"/>
          </root>
      
          <!--
              custom Logger
              additivity Property is used to define the current Logger Whether the object inherits RootLogger
           -->
          <logger name="com.xukai" level="info" additivity="false">
              <!--    appoint Appender    -->
              <appender-ref ref="console"/>
          </logger>
      </configuration>
      
  • Logback access module
    The logback access module is integrated with the Servlet container (Tomcat and Jetty) to provide HTTP access log function. We can use the logback access module to replace the access log of Tomcat.

    Use steps:

    1. Set logback access Jar and logback core Jar to $Tomcat_ Under home / lib /

    2. Modify $Tomcat_ HOME/conf/server. Append to the Host element in XML:

      <value className="ch.qos.logback.access.tomcat.LogbackValue"/>
      
    3. Logback will be in $Tomcat by default_ Find the file logback access under home / conf xml
      logback-access. For the official XML configuration, please refer to: https://logback.qos.ch/access.html#configuration

Log4j2 log framework (new project trends need to be mastered)

  • Apache Log4j2 is an upgraded version of Log4j. It refers to some excellent designs of logback, fixes some problems, and brings some major improvements at one time, mainly including:

    • Exception handling: in logback, the exception of the Appender will not be perceived by the application, but in log4j 2, some exception handling mechanisms are provided
    • Performance improvement: compared with Log4j and logback, Log4j2 has obvious performance improvement
    • Hot update: it refers to the design of logback and provides the function of automatically refreshing parameter configuration, which greatly facilitates the modification and update of configuration files in the production environment
    • No garbage mechanism: log4j can use its designed garbage free mechanism in most cases to avoid JVM GC caused by frequent log collection

    Log4j2 official website: https://logging.apache.org/log4j/2.x/

  • Log4j2 getting started

    At present, the most mainstream log facade in the market is slf4j. Although Log4j2 is also a log facade, because its log implementation function is very powerful and superior performance, developers generally regard Log4j2 as a log implementation. Slf4j + Log4j2 should be the general trend in the future.

    1. Import Maven coordinates:

      <dependencies>
          <!--    Log4j2 Log facade    -->
          <dependency>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-api</artifactId>
              <version>2.13.3</version>
          </dependency>
      
          <!--    Log4j2 Log implementation    -->
          <dependency>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-core</artifactId>
              <version>2.13.3</version>
          </dependency>
      </dependencies>
      

      Write a Demo:

      public class Log4j2Test {
      
          /**
           * Define logger objects
           */
          public static final Logger LOGGER = LogManager.getLogger(Log4j2Test.class);
      
          /**
           * quick get start
           * @throws Exception
           */
          @Test
          public void testQuickStart() throws Exception {
              LOGGER.fatal("fatal");
              LOGGER.error("error");
              LOGGER.warn("warn");
              LOGGER.info("info");
              LOGGER.debug("debug");
              LOGGER.trace("trace");
          }
      }
      
  • Detailed description of configuration file:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--  
    	status="warn" The output log level of the log framework itself
    	monitorInterval="5" The interval between automatic loading of configuration files shall not be less than 5 seconds
      -->
    <Configuration status="warn" monitorInterval="5">
    
        <!--  Centrally configure attributes for management. When used, it can be managed through el Expression( ${name})Can  -->
        <properties>
            <property name="LOG_HOME">F:/JavaProject/LogFrameWorks/Log4j2/logs</property>
        </properties>
    
        <Appenders>
            <!--  Console output Appender  -->
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
            </Console>
    
          <!--  Log file output Appender  -->  
            <File name="File" fileName="${LOG_HOME}/myfile.log">
                <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
            </File>
    
            <!--  Log file output of random read / write stream Apender,Greatly improved performance  -->
            <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
                <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
            </RandomAccessFile>
    
            <!--  Splitting log files by policy Appender  -->
            <RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"
                         filePattern="logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
                <!--  Log level filter  -->
                <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
                <!--  Log message format  -->
                <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
                <Policies>
                    <!--  When the system starts, the split rule is triggered to generate a new log file  -->
                    <OnStartupTriggeringPolicy/>
                    <!--  Split by file size  -->
                    <SizeBasedTriggeringPolicy size="10 MB"/>
                    <!--  Split by time node  -->  
                    <TimeBasedTriggeringPolicy/>
                </Policies>
                <!--  The number of files in the same directory is limited to 30. If it exceeds 30, the old log will be overwritten  -->
                <DefaultRolloverStrategy max="30"/>
            </RollingFile>
        </Appenders>
        <!--  Logger definition  -->
        <Loggers>
            <Root level="trace">
                <!--  Specify console processor  -->
                <AppenderRef ref="Console"/>
            </Root>
        </Loggers>
    </Configuration>
    
  • Asynchronous log:
    Log4j2 provides two ways to implement logging. One is through AsyncAppender, and the other is through asyncloger, which corresponds to the two components of Appender and Logger respectively. However, asyncloger is the most commonly used and the official recommended asynchronous method

    • Asynchronous logs need to import dependencies:

      <dependency>
          <groupId>com.lmax</groupId>
          <artifactId>disruptor</artifactId>
          <version>3.3.4</version>
      </dependency>
      
    • Modify profile

      <?xml version="1.0" encoding="UTF-8" ?>
      <Configuration status="warn" monitorInterval="5">
      
          <properties>
              <property name="LOG_HOME">F:/JavaProject/LogFrameWorks/Log4j2/logs</property>
          </properties>
      
              <File name="File" fileName="${LOG_HOME}/myfile.log">
                  <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
              </File>
      
              <!--    Specify asynchronous Appender    -->
              <Async name="Async">
                  <AppenderRef ref="file"/>
              </Async>
          </Appenders>
      
          <Loggers>
              <Root level="trace">
                  <AppenderRef ref="File"/>
                  <!--    Enable asynchronous    -->
                  <AppenderRef ref="Async"/>
              </Root>
              
              <!--    
      			custom AsyncLogger
         			includeLocation="false" Turn off the line number information of logging
      			additivity="false" No longer inherit RootLogger
       			-->
              <AsyncLogger name="com.xukai" level="trace" includeLocation="false" additivity="false">
                  <AppenderRef ref="File"/>
              </AsyncLogger>
          </Loggers>
      </Configuration>
      
    • Issues needing attention when using asynchronous logs:

      • If asynchronous logging is used, AsyncAppender, asyncloger and global logging should not appear at the same time. Otherwise, performance will be minimized
      • If includeLocation=false is set, printing location information will dramatically reduce the performance of asynchronous logs, which is slower than synchronous logs
  • Log4j2 no garbage record

    Garbage collection pauses are a common cause of performance impact. Many logging frameworks allocate temporary objects during steady-state logging, such as log event objects, strings, character arrays, byte arrays, and so on. This puts pressure on the JVM's garbage collector and increases the frequency of GC pauses

    Since version 2.6, Log4j runs in "garbage free mode" by default, in which objects and buffers are reused and temporary objects are not allocated as much as possible. In addition, there is a "low garbage mode", which is not completely garbage free, but does not use the ThreadLocal field

    Log4j2. The garbage free logging part of 6 is realized by reusing the object in the ThreadLocal field, and the other part is realized by reusing the buffer when converting text to bytes

    Log usage in Springboot

    Springboot framework is more and more widely used in enterprises. Springboot logging is also the most commonly used logging system in development. By default, springboot uses Slf4j as the log facade and Logback as the log implementation to record logs

    • Log design in Springboot

      • Import Maven coordinates:

        <dependency>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </dependency>
        
      • Dependency diagram:

        It can be seen that:

        1. The bottom layer of Springboot uses logback as the log implementation by default
        2. slf4j is used as the log facade
        3. The JUL is also converted to slf4j
        4. log4j2 can also be used as the log facade, but it is finally converted into slf4j calling logback through the bridge
  • Springboot log configuration:

    Application. Basic configuration in YML:

    logging:
    	level:
    		com.xukai: true
    	pattern:
    		console:  "%d - %msg%n"
    		file: "[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread] - %msg %n"
    	file:
    		path: logs/
    

    Specify configuration:
    Put each logging framework's own configuration file on the classpath, and Springboot will no longer use the default configuration

    Log frameconfiguration file
    Logbacklogback-spring.xml / logback.xml
    Log4j2log4j2-spring.xml / log4j2.xml
    JULlogging.properties
  • Springboot switches the logging framework to log4j2

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--  Exclude default logback  -->  
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!--  add to log4j2 rely on  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
    </dependencies>
    

Keywords: Java Spring Boot slf4j

Added by charlestide on Sat, 18 Dec 2021 15:15:01 +0200