What is a log


The function of logs is to develop and locate problems when there is no Debug tool in the test or production environment. If logs are well typed, online problems can be quickly located and solved based on log trajectories. Otherwise, if logs are poorly output, problems cannot be located and system performance deteriorates. Good projects are designed to locate problems based on logs, not debug them online, or get frustrated when you can’t find useful logs…

The history of


Log4j: In early 1996, E.U.S Per, the European Secure Electronic Marketplaces project, needed a Tracing API to centralize programs. Over time, the API became a popular Java logging package called Log4j, which was translated into C/C++/C#/Perl/Python and later became part of the Apache Foundation project. Log4j has become a near-standard for logging in the Java community. The Apache Foundation is also said to have suggested that Sun introduce Log4j into the Java standard library, but Sun declined.

JUL: In February 2002, WHEN JDK1.4 was released, Sun introduced its own Logging standard library, JUL (Java Util Logging), which was copied from Log4j. It was after JDK1.5 that performance and availability improved

JCL: In the same year, Apache launched Jakarta Commons Logging, which in this case means an organization rather than the Indian capital Jakarta, an early Apache open source project to manage Java subprojects, Examples include Tomcat, Ant, Maven, Struts, JMeter, Velocity, JMeter, Commons, etc. In December 2011, the Jakarta name was discontinued after all subprojects were migrated to standalone projects. JCL was created because some Java packages use JUL, and Log4j users use a lot of it, so JCL provides an API to switch between different loggers. JCL simply defines a Logging interface (it also provides a Simple implementation of Simple Log) that supports dynamically loading Logging components at run time. That is, in your application code, you can simply invoke the Commons Logging interface, and the underlying implementation can be Log4j. It can also be Java Util Logging. Last updated on September 9, 2014

SLF4J: In 2006, Ceki Gulcu (author of log4j1.x) was not comfortable with the way Apache worked and left. Then I created two projects SLF4J(Logging Facade, similar to Commons Logging) and Logback(implementation of SLF4J), and went back to Sweden to create QOS Company, SLF4J(Simple Logging Facade For Java), It has similar functions to JCL, but JCL has a fatal shortcoming that its algorithm is complex and problems are difficult to be eliminated. SLF4J was born to solve the shortcoming of JCL. Logback is a Generic, Reliable, fast and flexible Logging Framework.

Logback: In 2006, Ceki created the Logback logging library based on THE Slf4j interface. As the default implementation of Slf4j, Logback was also very useful. It surpasses all existing logging standard libraries in functional integrity and performance.

Log4j2: In 2012, Apache rewrote log4j1.x and established the Log4j2 project. In 2014, the general version of Log4j2 was released. Log4j2 has the same functions as Logback, but also has its own functions, such as plug-in structure, configuration file optimization, asynchronous logging, etc. Log4j2 is an upgrade to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides many of the improvements available in Logback, while fixing some inherent problems in the Logback architecture.

Common Logging frameworks


System. The out and System. Err

Before 2001, Java did not have a log library, so it printed logs only by system. out and system. err, I was stupid, very ridiculous

Disadvantages:

  • Generates a large number of I/O operations and cannot reasonably control the need for output in the production environment
  • The output cannot be saved to a file
  • It’s only printed on the console, and then it’s gone, that is, unless you’re watching the program run
  • Cannot be customized, and the log granularity is not fine enough

Log4j

background

At this point, a big guy named Ceki came out and said, “You don’t use this, I use this,” and then in 2001, Log4j came out, and it really did work better than the System series, and Log4j became the industry standard for logging

introduce

Log4j is an open source logging framework under Apache. By using Log4j in your projects, you can control the output of log information to the console, files, and even databases. You can control the output format of each log. By defining the output level of the log, you can control the output process of the log more flexibly. Convenient project debugging

The official website: logging.apache.org/log4j/1.2/

use

Introduction to the

  1. Add the dependent
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <groupId> <groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>  </dependencies>Copy the code

2. Code testing

Public class Log4jTest {@test public void testQuick() throws Exception {// Initialize system configuration, no configuration file data is required. // Initialize system configuration, Don't need to configure file number etc BasicConfigurator. Configure (); Logger = logger.getLogger (log4jtest.class); // Log output logger.info("hello log4j"); // Log level logger.fatal("fatal"); Logger. error("error"); Logger.warn ("warn"); // Error message, but does not affect system running logger.warn("warn"); Logger.info ("info"); // Warning message, possible problem logger.info("info"); Logger. debug("debug"); // Program running information, database connection, network, IO operation, etc. Logger. Trace ("trace"); }}Copy the code

The level of logging

  • Each Logger is assigned a log level to control the output of log information. The log levels in descending order are as follows:
Fatal indicates that every critical error event will cause the application to exit. Error indicates that an error event occurs but does not affect the system. Warn indicates that a potential error situation will occur. Info, generally and at a coarse-grained level, emphasizes the entire run of an application. Debug is generally used at a fine-grained level and is very helpful for debugging applications. Trace is a program trace that can be used to output variables as the program is running and to show the process being executed.Copy the code
  • There are also two special levels:
OFF can be used to turn OFF logging. ALL: Enables the logging of ALL messages.Copy the code

Note: Generally only four levels are used, and the priority is ERROR > WARN > INFO > DEBUG from high to low

Log4j components

Log4J consists primarily of Loggers, Appenders, and Layout. Loggers control the output level of logs and whether logs are output. Appenders specifies the log output method (output to console, file, etc.); Layout Controls the output format of log information

Loggers (Loggers)

Logger, which collects and processes log records. Instance name is the full Quailied name of class “XX”. The name of Logger is case-sensitive, A logger whose name is org.apache.commons inherits a logger whose name is org.apache

Log4J has a special logger called “root”, which is the root of all loggers, meaning that all other loggers inherit directly or indirectly from root. The root logger can be obtained using the logger.getrootLogger () method

Configure the root Logger with the syntax:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

Example:

log4j.rootLogger=info, stdout, log, errorlog
log4j.Logger=search,Test
Copy the code

Appenders(output)

An Appender is used to specify where logs are to be output to, as well as the log output destination. Log4j commonly uses the following output destinations:

Output type role
ConsoleAppender Output logs to the console
FileAppender Output logs to a file
DailyRollingFileAppender Output logs to a log file, and a new file every day
RollingFileAppender Output log information to a log file and specify the file size. When the file size reaches the specified size, the system automatically changes the file name and generates a new file
JDBCAppender Save log information to the database

Configure the Appender destination for log output. The syntax is:

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
log4j.appender.appenderName.option = valueN
Copy the code

Example:

log4j.rootLogger=info, stdout, log, errorlog
log4j.Logger=search,Test
###Console ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} [ %t ] [ %p ]:%L - %m%n
### Log ### 
log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
log4j.appender.log.File = log/log.log
log4j.appender.log.Append = true
log4j.appender.log.Threshold = INFO
log4j.appender.log.DatePattern='.'yyyy-MM-dd
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t ] %m%n
Copy the code

Detailed configuration may refer to: wiki.jikexueyuan.com/project/log…

Layout(Log formatter)

The Layouts control the format of log output content, allowing you to use any format you want. Popular Layouts for Log4j

Formatter type role
HTMLLayout Formatted logs are output as HTML tables
SimpleLayout Simple log output format. The log output format is (info-message).
PatternLayout The most powerful formatting period, you can output logs according to a custom format, if no conversion format is specified, the default conversion format is used

In the log4j.properties configuration file, we define the log output level and output side, and configure the log output format in the output side respectively:

Log4j formats the log information in a format similar to the PRINtf function in C. The placeholders and their meanings are as follows: %m Output the specified log information %p output priority, DEBUG, INFO, etc. %n Newline character (on Windows, the newline character is "\n", Unix "\n") %r Indicates the number of milliseconds elapsed since the application was started. %c Indicates the full name of the class to which the print statement belongs. %t Indicates the full name of the thread that generated the log. For example, %d{YYYY year MM month DD day HH: MM :ss} % L Indicates the location of the output log time, including the class name, thread, and number of lines in the code. For example: test.main (test.java :10) %F Output the name of the file where the log message was generated %L Line number in the output code %% Output a "%" character * Modifiers can be placed between % and characters to control the minimum width, maximum width, and how the text is treated. Such as: %5c outputs the category name with a minimum width of 5 and a category<5. By default, right-aligned %-5c outputs the category name with a minimum width of 5 and a category<5, left-aligned "-" with space %.5c outputs the category name. %20.30c Category name <20 fill space, and right align, >30 characters, then cut off the left side of the characterCopy the code

Custom Logger

Log com.lm package log4j.logger.com.lm = info,file log4j.logger.org.lm = errorCopy the code
@test public void testCustomLogger() throws Exception {// Customize com.lm Logger logger1 = Logger.getLogger(Log4jTest.class); logger1.info("info"); Logger logger2 = logger.getLogger (logger.class); }Copy the code

JUL(java util logging)

background

Java Util Logging is a Java native Logging framework, which does not need to reference third-party class libraries. Compared with other Logging frameworks, JUL is easy to use, easy to learn, and can be used flexibly in small applications

introduce

  • Loggers: Called Loggers, applications publish logs by taking Logger objects and calling their APIS. Logger is usually the entry program for applications to access the logging system.
  • Appenders: Also called Handlers, each Logger is associated with a set of Handlers, and the Logger hands the logs to the Handlers, who take care of the logging. Handlers are an abstraction whose concrete implementation determines the location of logging, whether in a console, a file, other logging services on the network, or operating system logs.
  • Also known as Formatters, Layouts transform and format data in log events. Layouts determine 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, and we can associate Level with Loggers and Appenders so that we can filter messages.
  • Filters: Filters that customize what information is recorded and what information is left out as needed.

To sum up:

The user uses the Logger to record logs. The Logger holds several handlers. The output of logs is performed by handlers. Before outputting logs, the Handler checks the Filter to determine which log levels are filtered and which blocks are allowed. The Handler outputs logs to specific locations (such as log files and consoles). The Handler uses Layout to output logs

use

Introduction to the

No special jar to introduce, JDK native support

Public class JULTest {// Quick start @test public void testQuick(){//1. Logger = logger.getLogger (" com.lm.jultest "); Logger. info("hello jul"); //2. Logger. log(level. INFO," INFO MSG "); String name = "lm"; Integer age = 13; Logger. The log (Level. The INFO, "user information: {0}, {1}", the new Object [] {name, age}); }}Copy the code

The level of logging

Java.util.logging. Level defines the logging levels: SEVERE (maximum) WARNING INFO (default) CONFIG FINE FINER FINEST (minimum) There are also two special levels: OFF can be used to turn OFF logging. ALL: Enables the logging of ALL messages.Copy the code

Although we tested seven logging levels, we only implemented levels above INFO by default

@Test public void testLogLevel(){ //1. Logger = logger.getLogger ("com.com.lm.JULTest"); //2. Log output logger. Severe ("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); } Result: severe Warning infoCopy the code

Custom log level control

@Test public void testLogConfig() throws IOException { // 1. Logger = logger.getLogger ("com.com.lm.JULTest"); / / close the system default configuration logger. SetUseParentHandlers (false); // Create ConsolHandler ConsoleHandler ConsoleHandler = new ConsoleHandler(); SimpleFormatter SimpleFormatter = new SimpleFormatter(); / / associated consoleHandler. SetFormatter (simpleFormatter); logger.addHandler(consoleHandler); // Set the specific log Level logger.setlevel (level.all); consoleHandler.setLevel(Level.ALL); FileHandler FileHandler = new FileHandler("F:/logs/jul.log"); FileHandler. SetFormatter (simpleFormatter); logger.addHandler(fileHandler); // 2. Log output logger. Severe ("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); } Result: All logs are printedCopy the code

The parent-child relationship between loggers

There are parent-child relationships among loggers in JUL, which are stored in a tree structure. When JUL initializes, a top-level RootLogger is created as the parent Logger of all Loggers and stored as the root node of the tree structure. And parent-child relationships are related by paths

@test public void testLogParent() throws Exception{Logger logger1 = logger.getLogger (" com.lm.app "); Logger logger2 = Logger.getLogger("com"); // Test system.out.println (logger1.getParent() == logger2); // The top-level parent of all loggers LogManager$RootLogger, name "" System.out.println("logger2 Parent:"+logger2.getParent() + ",name:"+ logger2.getParent().getName()); / / close the system default configuration logger2. SetUseParentHandlers (false); ConsolHandler = new ConsoleHandler(); ConsoleHandler = new ConsoleHandler(); SimpleFormatter SimpleFormatter = new SimpleFormatter(); / / associated consoleHandler. SetFormatter (simpleFormatter); logger2.addHandler(consoleHandler); // Set the log Level logger2.setLevel(level.all); consoleHandler.setLevel(Level.ALL); logger1.severe("severe"); logger1.warning("warning"); logger1.info("info"); logger1.config("config"); logger1.fine("fine"); logger1.finer("finer"); logger1.finest("finest"); }Copy the code

Result: Logger1 inherits the configuration of Logger2

True logger2 Parent: Java. Util. Logging. That the LogManager $6 f94fa3e RootLogger @, name: on May 24, 2021 com 12:36:51 afternoon. Lm. The App main serious: Severe May 24, 2021 12:36:51 PM com.lm.App main Warning: Warning May 24, 2021 12:36:51 PM com.lm.App main Message: Info May 24, 2021 12:36:51 PM com.lm.App main config May 24, 2021 12:36:51 PM com.lm.App main Fine on May 24, 2021 com 12:36:51 afternoon. Lm. The App main: detail finer on May 24, 2021 com 12:36:51 afternoon. Lm. The App main very detailed: the finestCopy the code

Log configuration file

Default configuration file path $JAVAHOME\jre\lib\logging.properties

@test public void testProperties() throws IOException {// Read from the defined configuration file InputStream in = JULDemo01.class.getClassLoader().getResourceAsStream("logging.properties"); LogManager LogManager = logManager.getLogManager (); / / by log manager. Load the configuration file that the logManager readConfiguration (in); Logger logger = Logger.getLogger("com.lm.JULDemo01"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }Copy the code

Configuration file:

# RootLogger the default handler specified by the top-level parent element is: ConsoleHandler handlers = Java. Util. Logging. # ConsoleHandler RootLogger top parent default log level to ALL. The level = INFO # # custom Logger Com. Itheima. Handlers = Java. Util. Logging. The FileHandler # custom Logger log level com. Itheima. Level = INFO # ignore the father log Settings Com. Itheima. UseParentHandlers # # = false to the console output handler object specified handler object log level Java. Util. Logging. ConsoleHandler. Level = INFO # specified format of log message handler object object Java. Util. Logging. ConsoleHandler. Formatter = Java. Util. Logging. SimpleFormatter # specified The handler object character set Java. The util. Logging. ConsoleHandler. Encoding = utf-8 # # # file processor output log level Java. Util. Logging. FileHandler. Level = INFO # # to the log file output handler object specified log file path: F/logs/Java % u.l og Java. Util. Logging. FileHandler. The pattern = F: / logs/Java % u.l og # specified log file contents size (50000 bytes) Java. Util. Logging. FileHandler. Limit = 50000 # specified log file number Java. Util. Logging. FileHandler. Count = 1 # specified hanlder log message format object Java. Util. Logging. FileHandler. The formatter = Java. Util. Logging. SimpleFormatter # assigned to add additional way log contents Java. Util. Logging. FileHandler. Append = true # specified log message format java.util.logging.SimpleFormatter.format = %1$tc %2$s%n%4$s: %5$s%6$s%nCopy the code

Log Principle Analysis

  1. Initialization that the LogManager
    1. LogManager loads the logging.properties configuration
    2. Add Logger to LogManager
  2. Get the Logger from the singleton LogManager
  3. Set the Level Level and specify LogRecord
  4. Filters provide more fine-grained control beyond the log level
  5. Handler is used to handle the log output location
  6. The Formatter is used to format the LogRecord

JCL(Jakarta Commons Logging)

introduce

Jakarta Commons Logging (JCL) provides a Logging interface that is both lightweight and independent of specific Logging implementation tools. It provides middleware/logging tool developers with a simple logging operation abstraction, allowing application developers to use different concrete logging implementation tools. Users are assumed to be familiar with a higher level of detail of a logging implementation tool. JCL provides an interface that simply wraps around other logging tools, including Log4J, Avalon LogKit, and JDK 1.4, and more closely resembles the Log4J and LogKit implementations

Shortly after JUL came out, In August 2002 Apache introduced JCL (Jakarta Commons Logging), a Logging abstraction layer that supports dynamically loading Logging components at runtime, Of course, Simple Log is also provided as a default implementation (look in the ClassLoader, if Log4j is found, the default implementation is Log4j, if not, use JUL implementation, if not, use JCL internal Simple Log implementation).

Why log facade?

  1. Interface oriented development, no longer dependent on concrete implementation classes. Reduce code coupling
  2. The project can flexibly switch the logging framework by importing different logging implementation classes
  3. Unified API, convenient for developers to learn and use
  4. Unified configuration facilitates project log management

use

Introduction to the

1. Add commons-logging dependencies

<! Commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId> Commons-logging </artifactId> The < version > 1.2 < / version > < / dependency >Copy the code

2. Use commons-logging to get the log instance from LogFactory (using JUL).

public class App { public static void main(String[] args) { Log logger1 = LogFactory.getLog(App.class); logger1.info("lm.test"); }} Results: May 24, 2021 1:05:34 PM com.lm.app main info: lm.testCopy the code

Add log4j dependencies

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

4. Print using log4j (log styles can be changed with log4j.properties)

public class App { public static void main(String[] args) { Log logger1 = LogFactory.getLog(App.class); logger1.info("lm.test"); }} Results:  log4j:WARN No appenders could be found for logger (com.lm.App). log4j:WARN Please initialize the log4j system properly. Log4j: WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.Copy the code

The principle of analysis

  1. The Log implementation class is dynamically loaded through LogFactory

2. Log facade supported log implementation array

private static final String[] classesToDiscover =
    new String[]{"org.apache.commons.logging.impl.Log4JLogger",
                 "org.apache.commons.logging.impl.Jdk14Logger",
                 "org.apache.commons.logging.impl.Jdk13LumberjackLogger",
                 "org.apache.commons.logging.impl.SimpleLog"};
Copy the code
  1. Get a concrete logging implementation
for(int i = 0; i < classesToDiscover.length && result == null; ++i) {
    result = this.createLogFromClass(classesToDiscover[i], logCategory,true); 
}
 
Copy the code

SLF4J( Simple Logging Facade for Java)

background

SLF4J: In 2006, Ceki Gulcu (author of log4j1.x) was not comfortable with the way Apache worked and left. Then I created two projects SLF4J(Logging Facade, similar to Commons Logging) and Logback(implementation of SLF4J), and went back to Sweden to create QOS Company, SLF4J(Simple Logging Facade For Java), It has similar functions to JCL, but JCL has a fatal shortcoming that its algorithm is complex and problems are difficult to be eliminated. SLF4J was born to solve the shortcoming of JCL. Logback is a Generic, Reliable, fast, and flexible Logging Framework.

Official website: www.slf4j.org/

Since Slf4j came out late, it has an interface and an unimplemented logging library, such as JUL and Log4j, which do not implement Slf4j, even if developers wanted to use Slf4j, they would not be able to use it

Then Ceki said, “It doesn’t matter if Sum and Apache don’t implement my interface, I’ll implement it, only magic can defeat magic.” Ceki provides a series of bridge packages to help Slf4j interfaces relate to other logging libraries in an approach called the bridge design pattern.

introduce

SLF4J(The Simple Logging Facade for Java) is a Simple Facade for Logging systems that allows end users to deploy their applications using their desired Logging frameworks, such as Log4j/LogBack/Log4j2, etc

JCL versus SLF4J implementation mechanism

use

Simple introduction

Maven adds dependencies

<! Slf4j </groupId> <artifactId> slf4J-api </artifactId> slf4j-api</artifactId> The < version > 1.7.28 < / version > < / dependency > <! Slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> The < version > 1.7.28 < / version > < / dependency >Copy the code

2, test,

public class App { public final static Logger LOGGER = LoggerFactory.getLogger(App.class); Public static void main(String[] args) {// Declare the log object logger.info ("lm.test"); LOGGER.warn("lm.test"); }} Result: [main] INFO com.lm.app-lm.test [main] WARN com.lm.app-lm.testCopy the code

Slf4j + use log4j

1. Increase dependency

<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency> Slf4j </groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>Copy the code

2, test,

public class App { public final static Logger LOGGER = LoggerFactory.getLogger(App.class); Public static void main (String [] args) {/ / initializes the system configuration, do not need to configure file number etc. BasicConfigurator configure (); // Declare the LOGGER object logger.info ("lm.test"); LOGGER.warn("lm.test"); }} Result: 1 [main] info.lm.app-lm.test 3 [main] WARN com.lm.app-lm.testCopy the code

SLF4J log binding

When the facade framework is integrated with the logging framework, it needs to be adapted through bridging packages — note that there can only be one log implementation

Log binding process using SLF4J

1. Add slF4J-API dependencies 2. Use THE SLF4J API for unified logging in projects 3. 1. Bind the logging framework that implements SLF4J and add the corresponding dependency 2. 4. Slf4j has one and only one logging implementation framework binding (if multiple logging implementations occur, the first dependency logging implementation is used by default)Copy the code

Integration solutions

Bridging old logging frames

If a project uses multiple specific logging frameworks and you want to use slF4J, slF4J will then use a logging framework for output. Like log4j used before, now you want to use SLf4J as a facade, unlike when the API import code was introduced

The binding adaptation JAR cannot exist at the same time as the bridging framework adaptation JAR, otherwise an infinite loop may occur. Jar and slf4j-jcl.jar cannot be deployed at the same time, and log4J-over-slf4j. jar and slf4j-log4j12.jar cannot be deployed at the same time


Logback

background

In 2006, Ceki created the Logback logging library based on THE Slf4j interface. As the default implementation of Slf4j, Logback was also very useful. It surpasses all existing logging standard libraries in functional integrity and performance

The current Java logging system diagram is as follows:

introduce

Slf4j, short for The Simple Logging Facade for Java, is a Simple Logging Facade abstraction framework that itself provides only a log Facade API and a Simple Logging class implementation. It is commonly used in conjunction with Log4j, LogBack, Use Java. Util. Logging. Slf4j as the application layer Log access, the program can dynamically adjust the underlying Log implementation framework according to the actual application scenarios (Log4j/LogBack/JdkLog…) . LogBack and Log4j are both open source journaling libraries. LogBack is an improved version of Log4j with more features and performance improvements than Log4j.

LogBack is divided into three components, logback-core, Logback-classic, and logback-access.

Logback-core provides the core functionality of Logback and is the basis for the other two components. Logback-classic implements the Slf4j API, so when you want to use it with Slf4j, you need to add logback-classic to your classpath. Logback-access is prepared for integration with the Servlet environment and provides an HTTP-Access logging interface.Copy the code

Logback configuration

Logback Indicates the execution sequence of the configuration file

If neither of the two files exists, the BasicConfigurator automatically configits itself and outputs the records to the consoleCopy the code

Configuration file import mode

RPC services: you only need to have configuration files in the classpath

Web services:

<! --logback--> <context-param> <param-name>logbackConfigLocation</param-name> <param-value>/WEB-INF/conf/logback.xml</param-value> </context-param> <listener> <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class> </listener>Copy the code

Logback configuration structure

A simple example:

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
    <property name="glmapper-name" value="glmapper-demo" /> 
    <contextName>${glmapper-name}</contextName> 
    
    
    <appender>
        //xxxx
    </appender>   
    
    <logger>
        //xxxx
    </logger>
    
    <root>             
       //xxxx
    </root>  
</configuration>  
Copy the code

Attributes contained in the root node < Configuration >

scan

When this property is set to true, the configuration file will be reloaded if it changes. The default value is true.

scanPeriod

If no time unit is given, the default unit is milliseconds. This attribute takes effect when scan is true. The default interval is 1 minute.

debug

When the value is set to true, internal logback logs are displayed to view the running status of logback in real time. The default value is false

<configuration scan="true" scanPeriod="60 seconds" debug="false"> <! -- Other configuration omitted --> </configuration>Copy the code

Set variable <property>

property

<property> is the label used to define the value of a variable. <property> has two attributes, name and value; The value of name is the name of the variable, and the value of value is the value defined by the variable. The defined values are inserted into the Logger context. After you define variables, you can make “${}” to use them.

<configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="APP_Name" value="myAppName" /> <contextName>${APP_Name}</contextName> <! -- Other configuration omitted --> </configuration>Copy the code

Get timestamp string <timestamp>

timestamp

Two attributes key: identifies the name of this <timestamp>; DatePattern: set the current time (time) parsing the configuration file is converted into a string pattern, follow the Java. TXT. SimpleDateFormat format

<configuration scan="true" scanPeriod="60 seconds" debug="false"> <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/> <contextName>${bySecond}</contextName> <! -- Other configuration omitted --> </configuration>Copy the code

To configure the logger

<logger> is used to set the logging level for a particular package or class and to specify <appender>. <logger> has only a name attribute, an optional level, and an optional addtivity attribute

name:

Used to specify a package or a class that is bound by this loger

level:

This is used to set the printing level, which is case-insensitive: TRACE, DEBUG, INFO, WARN, ERROR, ALL, and OFF. INHERITED or the synonym NULL is used to enforce the higher level. If this property is not set, the current LOger inherits the level of the parent.

addtivity:

Whether to send printed information to the upper logger. The default is true

<appender-ref>

<logger> can contain zero or more <appender-ref> elements, indicating that the appender will be added to the logger

Example:

<appender name="watcherScribe" class="com.scribe.logback.AsyncScribeAppender"> <! - is this scribe send the flume configuration - > < sizeOfInMemoryStoreForward > 2000 < / sizeOfInMemoryStoreForward > < appender > < logger name="metrics_banma_watcher" additivity="false"> <level value="INFO"/> <appender-ref ref="watcherScribe"/> </logger>Copy the code

Configure the root

It’s also an element, but it’s the root logger. Only one level attribute should already be named “root”

<root> can contain zero or more <appender-ref> elements, indicating that the appender will be added to the loger

<! -- Root Logger --> <root> <level value="INFO" /> <appender-ref ref="banmaLogModule" /> <appender-ref ref="errorlog" /> <appender-ref ref="banmaErrorLogModule" /> </root>Copy the code

Appender configuration

The component responsible for writing logs has two necessary attributes, name and class. Name specifies the name of the appender, and class specifies the fully qualified name of the appender

Example:

<appender name="GLMAPPER-LOGGERONE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>
        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
    </file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>
Copy the code
The filter child tags

It says so. One or more filters can be added to the appender, and logs can be filtered with any criteria. When appenders have multiple filters, they are executed in the order configured

ThresholdFilter

Threshold filter: Filters out logs whose values are lower than the specified threshold. When the log level is equal to or above the critical value, the filter returns NEUTRAL. When the log level is lower than the threshold, logs are rejected

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>INFO</level>
</filter>
Copy the code

LevelFilter

Level filter: Filters logs by log level. If the log level is equal to the configuration level, the filter receives or rejects logs based on onMath(used to configure operations that match the filtering criteria) and onMismatch(used to configure operations that do not match the filtering criteria).

<configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <! -- Set the log level of the filter to INFO. All INFO logs are processed by the appender. Non-info logs are filtered out. --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root>Copy the code
Appender

ConsoleAppender:

Adding logs to the console has the following sub-nodes:


  • : Formats the log. (Specific parameters will be explained later)

  • : string system. out or system. err, default system. out;

Such as:

<configuration>  
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
    <encoder>  
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>  
    </encoder>  
  </appender>  
  
  <root level="DEBUG">  
    <appender-ref ref="STDOUT" />  
  </root>  
</configuration>  
Copy the code

FileAppender:

Adding a log to a file has the following sub-nodes:


  • : indicates the file name to be written to. It can be a relative directory or an absolute directory. If the upper-level directory does not exist, the system automatically creates the file.

  • : If true, the log is appended to the end of the file. If false, the existing file is emptied. The default is true.

  • : Formats the recorded events. (Specific parameters will be explained later)
  • : If true, logs are safely written to the file, even if other Fileappenders are also writing to the file. Default is false.

Example:

<configuration>  
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">  
    <file>testFile.log</file>  
    <append>true</append>  
    <encoder>  
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>  
    </encoder>  
  </appender>  
          
  <root level="DEBUG">  
    <appender-ref ref="FILE" />  
  </root>  
</configuration>  
Copy the code

RollingFileAppender:

Logs are first logged to a specified file. When a condition is met, logs are logged to other files. Have the following sub-nodes:


  • : indicates the file name to be written to. It can be a relative directory or an absolute directory. If the upper-level directory does not exist, the system automatically creates the file.

  • : If true, the log is appended to the end of the file. If false, the existing file is emptied. The default is true.

  • : Formats the recorded events. (Specific parameters will be explained later)

  • : Determines the behavior of the RollingFileAppender when scrolling occurs, involving file movement and renaming.
  • : Tells RollingFileAppender to properly enable scrolling.
  • : When true, FixedWindowRollingPolicy is not supported. TimeBasedRollingPolicy is supported, but there are two limitations: 1 does not support and does not allow file compression, 2 cannot set the file property, must be left blank

RollingPolicy:

<appender name="jmonitorappender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <! /var/sankuai/logs/${app.key}.jmonitor.log.%d{YYYY-MM-DD}</FileNamePattern> <! -- Log file retention days --> <MaxHistory>5</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <! Format output: %d indicates the date, %thread indicates the thread name, %-5level indicates the level from the left 5 character width % MSG: Log messages, SSS} [%thread] %-5level % Logger {50} - % MSG %n</pattern> </encoder> </appender>Copy the code

TimeBasedRollingPolicy:

The most commonly used scroll policy, it according to the time to make the scroll policy, both responsible for the scroll and the start of the scroll, this includes two attributes:

  • FileNamePattern: necessary nodes, including file name and conversion operator “% d”, “% d” can contain a Java. The text. The SimpleDateFormat specified time format, such as: % d} {yyyy – MM. If % D is used directly, the default format is YYYY-MM-DD. RollingFileAppender’s file byte point is optional. By setting file, you can specify different locations for active and archive files. The current log is always recorded to the file specified by File (the active file) and the name of the active file does not change. If file is not set, the name of the active file changes at regular intervals based on the value of fileNamePattern. “/” or “\” are used as directory separators
  • MaxHistory: Optional node that controls the maximum number of archived files that can be retained and deletes old files if the number exceeds that. If scrolling is set to 6 per month, only files in the last 6 months are saved and old files in the previous 6 months are deleted. Note that when old files are deleted, directories created for archiving are also deleted.
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <! ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{YYYY-MM-DD}  </FileNamePattern> <! -- <MaxHistory>30</MaxHistory> </rollingPolicy>Copy the code

FixedWindowRollingPolicy:

A scrolling strategy for renaming files according to the fixed window algorithm


  • : minimum window index value

  • : indicates the maximum value of the window index. If the specified window is too large, the window is automatically set to 12.

  • : the value must contain % I. For example, if the minimum value is 1 and the maximum value is 2, and the naming mode is mylog%i.log, the archive files mylog1.log and mylog2.log are generated. You can also specify file compression options, for example, mylog%i.log.gz or no log%i.log.zip

Example of splitting logs by date and size:

<! - by date and size split logs - > < configuration > < appender name = "ROLLING" class = "ch. Qos. Logback. Core. ROLLING. RollingFileAppender" > <file>mylog.txt</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <! -- rollover daily --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <! -- Each file has a maximum of 100MB and is retained for 60 days of historical significance. </maxFileSize> <maxHistory>60</maxHistory> <totalSizeCap>20GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="ROLLING" /> </root> </configuration>Copy the code

Log4j2

Since Logback came out, Slf4j+Logback has been in the ascendency of JCL+Log4j, and Apache has been overtaken by Logback

In 2012, Apache introduced a new project Log4j2 (incompatible with Log4j), which fully borrowed Slf4j+Logback.

Log4j2 not only has all the features of Logback, but also has been designed to be separated into log4J-API and log4j-core. Log4j-api is the logging interface, log4j-core is the logging standard library, and Apache also provides various bridge packages for Log4j2

So far, Java logging has been divided into two camps, the Apache camp and Ceki camp, as shown in the figure below

introduce

Apache Log4j 2 is an upgrade to Log4j, with some good design references from Logback and some fixes, so it brings some significant improvements

  • Log4j2 has a significant performance improvement over log4J and LogBack. Official test data will be available later.
  • 2, automatic reloading configuration, reference logback design, of course will provide automatic refresh parameter configuration, the most useful is that we can dynamically change the log level in production without restarting the application.
  • Garbage-free. Log4j2 can use a garbage-free mechanism designed by log4J2 in most cases to avoid JVM GC due to frequent log collection
  • 4. Exception handling. In Logback, exceptions in the Appender are not perceived by the application, but in Log4j2, some exception handling mechanisms are provided.

The process of logging can be roughly divided into three steps:

Collect original log information in the program. Format the collected log information. 3Copy the code

Log4j2 has three important components that implement these functions: Logger, Layout, and Appender.

use

Slf4j + LOG4j2 Start configuration

1. Add configurations

<! Log4j-api --> <dependency> <groupId>org.apache.logging. Log4j </groupId> <artifactId> The < version > 2.11.1 < / version > < / dependency > <! Log4j </groupId> <artifactId>log4j-core</artifactId> The < version > 2.11.1 < / version > < / dependency > <! Slf4j </groupId> <artifactId> slf4J-api </artifactId> The < version > 1.7.25 < / version > < / dependency > <! > <dependency> <groupId>org.apache.logging.log4j</groupId> < artifactId > log4j - slf4j - impl < / artifactId > < version > 2.10.0 < / version > < / dependency >Copy the code

2. Add the log4j2 configuration file

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

Test your code

import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class App { public final static Logger LOGGER = LoggerFactory.getLogger(App.class); Public static void main(String[] args) {// Declare the log object logger.debug ("lm.test"); LOGGER.info("lm.test"); LOGGER.warn("lm.test"); }} result: 14:23:38.229 [main] info.lm.app-lm.test 14:23:38.233 [main] WARN com.lm.app-lm.testCopy the code
Logger logger = LogManager.getLogger(loggerName);
logger.info(msg);
Copy the code

For the general flow of getting logger and calling info I’ll use the flow chart directly:

Web Project Configuration

Web projects need to be added to web.xml

<context-param>  
    <param-name>log4jConfiguration</param-name>  
    <param-value>/WEB-INF/conf/log4j2.xml</param-value>  
</context-param>  
  
<listener>  
    <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>  
</listener>  
Copy the code

Log4j2 configuration

Log4j2 Configuration mode

Log4j2 can be configured in two ways:

  • Configuration is done programmatically through the ConfigurationFactory
  • Configuration file configuration supports file types such as XML, JSON, YAML, and Properties

The way to achieve this through programming is as follows:

@Plugin(name = "CustomerConfigurationFactory", category = ConfigurationFactory.CATEGORY)
public class CustomerConfigurationFactory extends ConfigurationFactory {
    protected String[] getSupportedTypes() {
        return new String[0];
    }
    public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource configurationSource) {
        ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
        builder.setStatusLevel(Level.INFO);
        return builder.build();
    }
}
Copy the code

In Log4j2, there are four default configurationFactories, JSON, log4j. JSN, log4j2. XML, etc. By default, the classpath directory will look for log4j. JSON, log4j. JSN, log4j2. XML, etc. This is output to the console, and the default Level is level.error

If the log4j2.properties log4j2.yaml log4j2.json log4j2. XML configuration files exist at the same time, the load priority is properties > YAMl > JSON > XML

Log4j2 configuration file description

The Configuration Configuration

Confirguration is the root element of the configuration file, and there is one or only one per configuration file. If you do not use the configuration file and use the default configuration, the following configuration is equivalent to the default configuration:

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

Each configuration contains at least one Appender and Logger. The status attribute is used to set the log level of Log4j2

Log levels from low to high are TRACE < DEBUG < INFO < WARN < ERROR < FATAL. If the log level is set to WARN, logs lower than WARN are not output

Log4j2 automatically detects configuration file changes, and monitorInterval sets the time for the monitorInterval to automatically detect configuration file changes. The minimum value of the monitorInterval is 5, indicating that it detects configuration file changes every five seconds

<? The XML version = "1.0" encoding = "utf-8"? > <Configuration monitorInterval="30"> .... </Configuration>Copy the code
The Logger configuration

The Logger element is used to configure the Logger. Logger comes in two forms, Logger and Root, the difference being that Root has no name attribute and does not support additivity

Suppose we want to fetch a certain level of logs for a particular class. Increasing the log level does not fulfill this requirement. One possible way to do this is to add a Logger to Loggers as follows:

<Loggers>
    <Logger name="cn.rayjun.Log4j2HelloWorld" level="trace">
       <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
        <AppenderRef ref="Console"/>
    </Root>
 </Loggers>
Copy the code

This configuration, in addition to the cn. Rayjun. Log4j2HelloWorld class will print out the trace levels of the log, the other is will only print out the error level log, print the results are as follows:

19:59:06. [the main] TRACE 957 cn. Rayjun. Log4j2HelloWorld - Enter 19:59:06. 957 [main] TRACE cn rayjun. Log4j2HelloWorld - Enter 19:59:06. [the main] ERROR 959 cn. Rayjun. Log4j2HelloWorld - Hello world 19:59:06. [the main] ERROR 959 cn.rayjun.Log4j2HelloWorld - Hello worldCopy the code

However, there is a problem with the log printed above. The information has been printed twice. To solve this problem, the additivity parameter needs to be added and set to false.

<Loggers>
    <Logger name="cn.rayjun.Log4j2HelloWorld" level="trace" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
        <AppenderRef ref="Console"/>
    </Root>
</Loggers>
Copy the code

If Logger additivity is set to false, the log will no longer be passed to the parent Logger

Asynchronous logger

The main feature of log4j2 is asynchronous logs. The performance of log4j2 is mainly benefited from asynchronous logs

Loggers are synchronous by default, but there are also asynchronous implementations. The asynchronous version of Root is AsyncRoot, and the asynchronous version of Logger is AsyncLogger. Asynchronous Loggers rely on an external queue, LMAX Disruptor. Using asynchronous Loggers requires external dependencies:

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.2</version>
</dependency>
Copy the code

Log4j2 provides two ways to implement logging, one via AsyncAppender and one via AsyncLogger, which correspond to the Appender component and Logger component respectively

AsyncAppender way

Asynchrony depends on the ArrayBlockingQueue queue

The core component of AsyncAppender is a blocking queue. Logger puts data into the blocking queue through append method, and then background thread retrieves data from the queue and performs subsequent operations

Use case:

<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
    <Async name="Async">
      <AppenderRef ref="MyFile"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Async"/>
    </Root>
  </Loggers>
</Configuration>
Copy the code

AsyncLogger way

The asynchronous version of Root is AsyncRoot, and the asynchronous version of Logger is AsyncLogger, which relies on an external queue, LMAX Disruptor.

AsyncLogger calls the Disruptor and returns directly.Disruptor eats memory and can cause CPU spikes. Use with caution

Example:

<Configuration status="WARN" monitorInterval="30"> <Appenders> <RollingRandomAccessFile name="applicationAppender" fileName="./log/application.log" filePattern="./log/$${date:yyyy-MM}/common-%d{yyyy-MM-dd}.log.gz" append="false"> <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> </Policies> </RollingRandomAccessFile> </Appenders> <Loggers> <! --> <AsyncLogger name="log4j2" > <AppenderRef ref="applicationAppender"/> </AsyncLogger> <Root level="info"> <AppenderRef ref="applicationAppender"/> </Root> </Loggers> </Configuration>Copy the code

Pay attention to

  1. If using asynchronous logging, AsyncAppender, AsyncLogger, and global logging should not be used at the same time. The performance will be the same as AsyncAppender and will be minimal
  2. Set includeLocation=false. To print location information, the performance of asynchronous logs is significantly lower than that of synchronous logs
The Filter configuration

ThresholdFilter

Filters determine whether the log event can be output. The filter criteria are ACCEPT, DENY and NEUTRAL.

Output logs of a warn level or lower

<Filters> <! -- If error level is rejected, <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/> <! --> <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/> </Filters>Copy the code

Only logs with the error level or higher are generated

<Filters>
    <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
Copy the code

Reference: www.docs4dev.com/docs/zh/log…

Appender configuration

The Appender is responsible for distributing logs to the appropriate destination. This means that the Appender decides how the log will be displayed, and the ConsoleAppender used here prints the log directly to the console. It also supports output of logs to files, databases, and message queues

<Appenders> <! <Console name="Console" target="SYSTEM_OUT"> <! -- The console outputs only messages of level and above (onMatch), --> <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> <! PatternLayout pattern="%d{HH:mm: ss.sss} %-5level %class{36} %L %M - % MSG %xEx%n"/> </Console> <! OnMatch ="ACCEPT" onMismatch="DENY" onMatch="ACCEPT" onMismatch="DENY" --> <File name="ERROR_FILE" fileName="./logs/error.log"> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <File name="WARN_FILE" fileName="./logs/warn.log"> <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/> <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <! -- This will print all the information, every time the size exceeds the size, the size of the log will be automatically saved in the folder created by year to month and compressed. As an archive --> <RollingFile name="INFO_RollingFile" fileName="./logs/info.log" filePattern="logs/$${date:yyyy-MM}/info-%d{MM-dd-yyyy}-%i.log.gz"> <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="NEUTRAL"/> <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> <SizeBasedTriggeringPolicy size="2MB"/> </RollingFile> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <! - TimeBasedTriggeringPolicy will match filePattern configuration, if filePattern is {} dd HH - MM yyyy - MM, the smallest time granularity is minutes, then every minute to generate a file, If change - dd HH} {yy - MM, minimum granularity is hours, then will every hour to generate a file - > < TimeBasedTriggeringPolicy / > <! Set the size of the log - SizeBasedTriggeringPolicy said, The configuration above refers to the log size to 250 MB after began to generate a new log file -- > < SizeBasedTriggeringPolicy size = "250 MB" / > < / Policies > < / RollingFile > < / Appenders >Copy the code
Layouts configuration

The Appender uses Layout to format the log. Layouts in Lo4j1 and Logback convert logs to strings, while Log4j2 uses byte arrays, which is optimized for performance

Layout Supports multiple configuration methods. The most commonly used pattern is PatternLayout, which uses regular expressions to format logs. The basic configuration is as follows

<PatternLayout>
    <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
Copy the code
%d indicates the time. By default, it means to print the full timestamp 2012-11-02 14:34:02,123. You can adjust the parameter after %d to adjust the output time format. You can use %highlight{%p} to highlight the log level %c to output the class name. The default output is the full package name and class name. %c{1. %M indicates the method name. %n indicates the newline character. %L indicates the number of lines of code to print the logCopy the code

Complete simple demo implementation

Assume that a log needs to be saved as a file. Complete log information, including the number of lines of code corresponding to the log, needs to be saved, and a new log file needs to be generated according to the time and size of the log file

<Configuration status="warn">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] [%t] [%C.%M] [%m]%n"/>
        </Console>
        <RollingRandomAccessFile name="${service_name}-log"
                                 fileName="~/${service_name}/${service_name}.log"
                                 filePattern="~/${service_name}/${service_name}.log.%d{yyyyMMddHH}"
                                 append="true" immediateFlush="false">
            <PatternLayout
                    pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] [%t] [%C.%M] [%m]%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="250 MB"/>
            </Policies>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <AsyncRoot level="${log_level}" includeLocation="true">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="${service_name}-log" />
        </AsyncRoot>
    </Loggers>
</Configuration>
Copy the code

After includeLocation is added to the Logger, the log performance will be significantly degraded. If the log location information is not necessary, it is not necessary to add the log location information