Java log - summary [this is enough]

Programmer light 2022-02-13 07:52:37 阅读数:406

java log summary

  JDK journal 、log4j Series log 、logback Series log

  common-logging Log interface

  sl4j Log interface

One 、JDK journal (java.util.logging=jul)

from jdk1.4 rise ,JDK Start to bring your own log system .JDK Logger The biggest advantage is that you don't need any class library support , As long as there is Java You can use the . Compared to other logging frameworks ,JDK The log you bring with you is chicken ribs , Regardless of ease of use , The function and scalability are slightly inferior , Therefore, it is rarely used directly in commercial systems .

JDK default logging The configuration file is :$JAVA_HOME/jre/lib/logging.properties, You can use system properties java.util.logging.config.file Specify the corresponding configuration file to overwrite the default configuration file , such as , java -Djava.util.logging.config.file=myfile

JDK Logging The log is divided into the following seven levels , The grades are reduced in turn .

If the level is set to INFO, be INFO The following will not output .info All previous outputs . Achieve the purpose of controlling the output through the control level .

import java.util.logging.Level;
import java.util.logging.Logger;
public class LogJDKTest {
private static Logger log = Logger.getLogger(LogJDKTest.class.toString());
public static void main(String[] args) {
// all→finest→finer→fine→config→info→warning→server→off
// The ranks go up in turn , The later log level will mask the previous level
log.setLevel(Level.INFO);
log.finest("finest");
log.finer("finer");
log.fine("fine");
log.config("config");
log.info("info");
log.warning("warning");
log.severe("server");
}
}

  Console output :

 June 23, 2021 11:07:29 In the morning com.test.log.LogJDKTest main
Information : info
June 23, 2021 11:07:29 In the morning com.test.log.LogJDKTest main
Warning : warning
June 23, 2021 11:07:29 In the morning com.test.log.LogJDKTest main
serious : server

1.JDK log There will be a console output by default , It has two parameters , The first parameter sets the output level , The second parameter sets the output string .

2. You can also set multiple outputs (Hander), Each output setting is not used level, And then through addHandler Added to the log in .

Be careful : by log Set the level and for each handler The meaning of setting the level is different .

import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogJDKTest {
public static Logger log = Logger.getLogger(LogJDKTest.class.toString());
static {
Handler console = new ConsoleHandler();
console.setLevel(Level.SEVERE);
log.addHandler(console);
Handler console2 = new ConsoleHandler();
console2.setLevel(Level.INFO);
log.addHandler(console2);
}
public static void main(String[] args) {
// all→finest→finer→fine→config→info→warning→server→off
// The ranks go up in turn , The later log level will mask the previous level
log.setLevel(Level.INFO);
log.finest("finest");
log.finer("finer");
log.fine("fine");
log.config("config");
log.info("info");
log.warning("warning");
log.severe("server");
}
}

Console output :

 June 23, 2021 11:09:03 In the morning com.middleware.test.log.LogJDKTest main
Information : info
June 23, 2021 11:09:03 In the morning com.middleware.test.log.LogJDKTest main
Warning : warning
June 23, 2021 11:09:03 In the morning com.middleware.test.log.LogJDKTest main
serious : server
June 23, 2021 11:09:03 In the morning com.middleware.test.log.LogJDKTest main
serious : server

all, Then all the information will be output , If it is set to off, Then all information will not be output .

Two 、log4j1

Apache An open source project of , By using Log4j, The destination where we can control the delivery of log information is the console 、 file 、GUI Components 、 Even socket Services   device 、NT Event recorder for 、UNIX Syslog Daemons, etc ; Users can also control the output format of each log ; By defining the level of each log message , Users can more carefully control the log generation process . These can be done through a   Configuration file to flexibly configure , Without modifying the program code .

Import maven

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

stay resources Create and set up log4j.properties

### Set up ###
log4j.rootLogger = debug,stdout,D,E
### Output information to control lifting ###
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 = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### Output DEBUG Log above level to =E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### Output ERROR Log above level to =E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

Set log content

import org.apache.log4j.Logger;
public class TestLog4j {
private static Logger logger = Logger.getLogger(TestLog4j.class);
public static void main(String[] args) {
// Record debug Level information
logger.debug("This is debug message.");
// Record info Level information
logger.info("This is info message.");
// Record error Level information
logger.error("This is error message.");
}
}

Output results

The first is the information on the console

[DEBUG] 2021-06-23 12:00:46,717 method:com.middleware.test.log.TestLog4j.main(TestLog4j.java:11)
This is debug message.
[INFO ] 2021-06-23 12:00:46,719 method:com.middleware.test.log.TestLog4j.main(TestLog4j.java:13)
This is info message.
[ERROR] 2021-06-23 12:00:46,719 method:com.middleware.test.log.TestLog4j.main(TestLog4j.java:15)
This is error message.

Let's look at the output file

The contents are as follows , It is found that it has been output to the corresponding document as required .

  3、 ... and 、log4j2

Import maven package

 <dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>

  Test code

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LoggerTest {
public static void main(String argv[]) {
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
logger.error(" String splicing one :{}, Record main perform :","logger");
logger.error(" String splicing II :","logger");
}
}

Four 、logback

Logback By log4j Another open source diary component designed by the founder .logback Currently divided into three modules :logback-core,logback- classic and logback-access.logback-core It is the basic module of the other two modules .logback-classic yes log4j One of the   Improved version . Besides logback-classic Complete implementation SLF4J API So that you can easily change to other diary systems, such as log4j or JDK14 Logging.logback-access Access module and Servlet Container integration is provided through Http To access the diary function .

One 、logback Introduction to

Logback By log4j Another open source logging component designed by the founder , Official website : Logback Home. It is currently divided into the following modules :

  •  logback-core: The basic modules of the other two modules
  •  logback-classic: It is log4j An improved version of , At the same time, it completely realizes slf4j API So that you can easily change to other log systems such as log4j or JDK14 Logging
  •  logback-access: Access module and Servlet Container integration is provided through Http To access the function of the log

Two 、logback replace log4j The reason of :

1、 Faster implementation :Logback The kernel of , Performance improvement on some critical execution paths 10 More than times . and logback Not only is the performance improved , Initialization memory loading is also smaller .

2、 Very well tested :Logback After a few years , Countless hours of testing .Logback The tests of are totally different levels .

3、Logback-classic It's very natural SLF4j:Logback-classic Realized SLF4j. In the use of SLF4j in , You can't feel logback-classic. And because logback-classic It's very natural that slf4j ,  the   To switch to log4j Or other , Very easy to , Just provide another jar Baojiu OK, There's no need to move those through SLF4JAPI Implemented code .

4、 Very well documented   The official website has more than 200 pages of documents .

5、 Auto reload profile , When the configuration file is modified ,Logback-classic Can automatically reload configuration files . Scanning is fast and safe , It doesn't need to create another scan thread . This technology ensures that the application can run happily JEE In the environment .

6、Lilith yes log The observer of the event , and log4j Of chainsaw similar . and lilith It can also handle a large number of log data  .

7、 Careful mode and very friendly recovery , In cautious mode , Multiple FileAppender Examples run in multiple JVM Next , can   Safe enough to write the same log file .RollingFileAppender There will be some restrictions .Logback Of FileAppender And its subclasses include  RollingFileAppender Can be very friendly from I/O Recover in exception .

8、 Configuration files can handle different situations , Developers often need to judge different Logback Configuration files in different environments ( Development , test , production ). And these profiles are just a few small differences , Can pass , And to achieve , Such a configuration file can adapt to multiple environments .

9、Filters( filter ) Sometimes , Need to diagnose a problem , Need to log . stay log4j, Only reduce the log level , But it's going to be a lot of logs , Will affect application performance . stay Logback, You can go on   Keep that log level and get rid of some special situation , Such as alice This user logs in , Her diary will be in DEBUG Level and other users can continue to type in WARN Level . To achieve this function, just add 4 That's ok XML To configure . You can refer to MDCFIlter .

10、SiftingAppender( A very versatile Appender): It can be used to split the log file according to any given running parameter . Such as ,SiftingAppender Can distinguish log event follow-up users Session, Then each user will have a log file .

11、 Automatic compression has been printed out log:RollingFileAppender When new documents are produced , Will automatically compress the log files that have been printed out . Compression is an asynchronous process , So even for large log files , Application will not be affected during compression .

12、 Stack tree with package version :Logback When making a stack tree log , Will bring the package's data .

13、 Automatically remove old log files : By setting TimeBasedRollingPolicy perhaps SizeAndTimeBasedFNATP Of maxHistory attribute , You can control the maximum number of log files that have been generated . If you set maxHistory 12, Those log The document exceeds 12 Months will be automatically removed .

3、 ... and 、logback Configuration of

  •  Logger、appender And layout

Logger As a log recorder , Relate it to the application's corresponding context After the , It is mainly used to store log objects , You can also define the log type 、 Level .

Appender It is mainly used to specify the destination of log output , The destination can be the console 、 file 、 Remote socket server 、 MySQL、PostreSQL、 Oracle And other databases 、 JMS And remote UNIX Syslog Daemons, etc .

Layout  Responsible for converting events to strings , Output of formatted log information .

  • logger context

each logger  It's all connected to a  LoggerContext,LoggerContext Be responsible for manufacturing logger, It is also responsible for arranging the trees logger. All of the other logger Also through org.slf4j.LoggerFactory  Class static methods getLogger obtain . getLogger Methods to  logger The name is parameter . Call... With the same name LoggerFactory.getLogger  The results of the method are always the same logger References to objects .

  • Valid levels and inheritance of levels

Logger  Can be assigned levels . Levels include :TRACE、DEBUG、INFO、WARN  and  ERROR, Defined in ch.qos.logback.classic.Level class . If  logger Not assigned a level , Then it will inherit the level from the nearest ancestor who has the assigned level .root logger  The default level is  DEBUG.

  • Printing methods and basic selection rules

The printing method determines the level of recording request . for example , If  L  It's a  logger  example , that , sentence  L.info("..") Is a level for  INFO The record statement of . Record requests at a level higher than or equal to  logger  The effective level of is called enabled , otherwise , Called Disabled . The record request level is  p, Its  logger The effective level of is  q, Only when  p>=q when , The request will be executed .

The rule is  logback  At the heart of . The ranking is : TRACE < DEBUG < INFO < WARN < ERROR

Four 、logback Default configuration

If the profile  logback-test.xml  and  logback.xml  It doesn't exist , that  logback  By default... Is called BasicConfigurator , Create a minimized configuration . Minimized configuration is associated with a root  logger  Of ConsoleAppender  form . The output mode is %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n  Of  PatternLayoutEncoder  format .root logger  The default level is  DEBUG.

  •  Logback Configuration file for

Logback  The syntax of the configuration file is very flexible . Because of the flexibility , So I can't use  DTD  or  XML schema  Define . For all that , The basic structure of the configuration file can be described in this way : With <configuration> start , There are zero or more at the back <appender> Elements , There are zero or more <logger> Elements , There is at most one <root> Elements .

  •   Logback Default configuration steps

1、 Try to  classpath Look for the file logback-test.xml;

2、 If the file doesn't exist , Find the file logback.xml;

3、 If neither file exists ,logback use BasicConfigurator Automatically configure yourself , This causes the record to be output to the console .

5、 ... and 、logback.xml General configuration details

(1)  The root node <configuration>, Contains the following three properties :

scan:  When this property is set to true when , If the configuration file changes , Will be reloaded , The default value is true.

scanPeriod:  Set the time interval between changes in the monitoring profile , If no time unit is given , The default unit is milliseconds . When scan by true when , This property takes effect . The default time interval is 1 minute .

debug:  When this property is set to true when , Will print out logback Internal log information , Real-time view logback Running state . The default value is false.

for example :

<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- Other configurations are omitted -->
</configuration> 

(2)  Child node <contextName>: Used to set the context name , Every logger All related to logger Context , The default context name is default. But you can use <contextName> Set to a different name , Records used to distinguish different applications . Once set , Do not modify .

for example :

<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>myAppName</contextName>
<!-- Other configurations are omitted -->
</configuration> 

Child node <property> : Used to define variable values , It has two properties name and value, adopt <property> The defined value will be inserted into logger In the context of , You can make “${}” To use variables .

name:  The name of the variable

value:  The value of is the value defined by the variable

for example :

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

Child node <timestamp>: Get the timestamp string , He has two attributes key and datePattern

key:  Mark this <timestamp>  Name ;

datePattern:  Set the current time ( Time to parse the configuration file ) Conversion to string mode , follow java.txt.SimpleDateFormat The format of .

for example :

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

(5)  Child node <appender>: The component responsible for writing logs , It has two necessary attributes name and class.name Appoint appender name ,class Appoint appender Full name of

5.1、ConsoleAppender  Output the log to the console , There are the following child nodes :

<encoder>: Format the log .( The specific parameters will be explained later  )

<target>: character string System.out( Default ) perhaps System.err( There's no more difference )

for example :

<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>

>=DEBUG Level logs are output to the console

5.2、FileAppender: Add log to file , There are the following child nodes :

<file>: The name of the file being written , It can be a relative Directory , It can also be an absolute catalog , If the parent directory does not exist, it will be created automatically , No default .

<append>: If it is  true, The log is appended to the end of the file , If it is  false, Empty existing files , The default is true.

<encoder>: Format the recorded events .( The specific parameters will be explained later  )

<prudent>: If it is  true, The log will be safely written to the file , Even if the others FileAppender Also writing to this file , Low efficiency , The default is  false.

for 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>

The above configuration shows that >=DEBUG Level logs are output to testFile.log

5.3、RollingFileAppender: Scroll record file , First log to the specified file , When a condition is met , Log to other files . There are the following child nodes :

<file>: The name of the file being written , It can be a relative Directory , It can also be an absolute catalog , If the parent directory does not exist, it will be created automatically , No default .

<append>: If it is  true, The log is appended to the end of the file , If it is  false, Empty existing files , The default is true.

<rollingPolicy>: When rolling happens , decision RollingFileAppender act , It involves moving and renaming files . attribute class Define specific rolling strategy classes class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy":  The most common rolling strategy , It makes rolling strategies based on time , Responsible for rolling as well as starting rolling . There are the following child nodes :

<fileNamePattern>: Necessary nodes , Contains the file name and “%d” Conversion character ,“%d” It can contain a java.text.SimpleDateFormat Specified time format , Such as :%d{yyyy-MM}.

If used directly  %d, The default format is  yyyy-MM-dd.RollingFileAppender Of file Byte points are optional , By setting file, You can specify different locations for active and archived files , The current log always records file Specified file ( Activity file ), The name of the active file will not change ;

If not file, The name of the activity file will be based on fileNamePattern  Value , Change every once in a while .“/” perhaps “\” Will be used as a directory separator

<maxHistory>:

Optional nodes , Control the maximum number of archive files that are retained , Delete old files if the number exceeds . Suppose you set the scroll every month , And <maxHistory> yes 6, Save only recent 6 Months of documents , Delete old files before . Be careful , Deleting old files is , Directories created for archiving will also be deleted .

class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy":  View the size of the currently active file , If it exceeds the specified size, it will inform RollingFileAppender  Triggers the scrolling of the currently active file . Only one node :

<maxFileSize>: This is the size of the active file , The default value is 10MB.

<prudent>: When it comes to true when , I won't support it FixedWindowRollingPolicy. Support TimeBasedRollingPolicy, But there are two limitations ,1 File compression is not supported or allowed ,2 Cannot set file attribute , Must be left blank .

<triggeringPolicy >:  inform  RollingFileAppender  Appropriate to activate scrolling .

class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"  According to the fixed window algorithm rename the file rolling strategy . There are the following child nodes :

<minIndex>: Minimum window index

<maxIndex>: Maximum window index , When the window specified by the user is too large , Will automatically set the window to 12.

<fileNamePattern>: Must contain “%i” for example , Suppose that the minimum and maximum values are respectively 1 and 2, The naming pattern is  mylog%i.log, There will be an archive mylog1.log and mylog2.log. You can also specify file compression options , for example ,mylog%i.log.gz  perhaps   No, log%i.log.zip

for example :

<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>

remarks : The above configuration means that a log file is generated every day , preservation 30 Days of log files .

<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>

On 5MB when , Generate a new log file . The window size is 1 To 3, When saved 3 After filing , The oldest log will be overwritten .

<encoder>: Format the recorded events . Responsible for two things , One is to convert log information into byte array , The second is to write the byte array to the output stream .

PatternLayoutEncoder  Is the only useful and default encoder , There is one <pattern> node , Used to set the input format of the log . Use “%” Add “ Conversion character ” The way , If you want to output “%”, You have to use “\” Yes “\%” Transference .

5.4、 also SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender, Is not commonly used , I won't go into details here .

You can refer to the official documents (Documentation), You can also write your own Appender.

6) Child node <loger>:

Used to set the log printing level of a package or a specific class 、 And the designation <appender>.<loger> There is only one name attribute , An optional one level And an optional addtivity attribute .

It can contain zero or more <appender-ref> Elements , Identify this appender Will be added to this loger

name:  Used to designate the recipient loger A package of constraints or a specific class .

level:  Used to set the print level , Case is irrelevant :TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF, There is also a special custom value INHERITED Or synonyms NULL, Represents the level of enforcement superior .  If this property is not set , Then the current loger Will inherit the level of the superior .

addtivity:  Whether to report to the superior loger Transfer printed information . The default is true. Same as <loger> equally , It can contain zero or more <appender-ref> Elements , Identify this appender Will be added to this loger.

(7) Child node <root>:

So is it <loger> Elements , But it's the root loger, It's all <loger> My superior . only one level attribute , because name It has been named "root", And he's already at the top .

level:  Used to set the print level , Case is irrelevant :TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF, Cannot be set to INHERITED Or synonyms NULL.  The default is DEBUG.

6、 ... and 、 Commonly used logger To configure

<!-- show parameters for hibernate sql Specially designed for Hibernate customized -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>

7、 ... and 、Demo

(1) Add dependency package logback Use needs and slf4j Use it together , So the total packages that need to be added are slf4j-api

logback Use needs and slf4j Use it together , So the total packages that need to be added are slf4j-api.jar,logback-core.jar,logback-classic.jar,logback-access.jar This is not available for the time being, so we don't add dependencies ,maven To configure

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<logback.version>1.1.7</logback.version>
<slf4j.version>1.7.21</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>

(2)logback.xml To configure

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- Define the storage address of the log file Stay away LogBack The relative path is used in the configuration of -->
<property name="LOG_HOME" value="/home" />
<!-- Console output -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- Format output :%d Indicates the date ,%thread Represents the thread name ,%-5level: The level is shown from the left 5 Character width %msg: Log message ,%n Is a newline -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- Generate log files per day -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- The filename of the log file output -->
<FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- Log file retention days -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- Format output :%d Indicates the date ,%thread Represents the thread name ,%-5level: The level is shown from the left 5 Character width %msg: Log message ,%n Is a newline -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!-- Maximum log file size -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- Log output level -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

(3)java Code

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
private final static Logger logger = LoggerFactory.getLogger(LogbackTest.class);
public static void main(String[] args) {
logger.info("info succeed ");
logger.error("error succeed ");
logger.debug("debug succeed ");
}
}

(4) Output

2021-06-24 16:42:59.131 INFO --- [ main] com.middleware.test.log.LogbackTest : info succeed
2021-06-24 16:42:59.136 ERROR --- [ main] com.middleware.test.log.LogbackTest : error succeed 

logback Integrate springboot

springboot2.0 Integrate logback journal ( detailed ) - Baidu on Google - Blog Garden

8.1、 explain

springboot It has built-in log function

8.2、SpringBoot Built in log analysis

Create an empty SpringBoot project , Otherwise, the analysis will find other jar Package dependent logs

springboot Of pom Every document will quote a parent

 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath />
</parent>

Point in this parent, There will be one of these dependency

 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.0</version>
</parent>

Just a little bit more 2.4 edition , So called it gives you integrated package dependencies , And the version number , One of the bags is as follows

 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.0</version>
</dependency>

Click in again

 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.4.0</version>
<scope>compile</scope>
</dependency>
 <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.13.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.30</version>
<scope>compile</scope>
</dependency>

8.3、 Use maven helper analysis

First, in the idea Install the plug-in in

You can clearly see dependencies

5、 ... and 、common-logging( Log interface )

Jakarta  Commons-logging(JCL) yes apache The earliest interface for logging . Provide simple log implementation and log decoupling function .

common-logging yes apache Provides a general log interface . Users can freely choose the third-party log component as the specific implementation , image log4j, perhaps jdk Self contained logging, common-logging Through the mechanism of dynamic search , Automatically find out the real log library when the program is running . Of course ,common-logging There's a Simple logger Simple implementation of , But the function is very weak . So use common-logging, Usually with log4j To use . The advantage of using it is , Code dependency is common-logging Instead of log4j,  Avoid direct coupling with specific logging schemes , When necessary , Third party libraries that can change the log implementation .

Use common-logging Common code for :

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class A {
private static Log logger = LogFactory.getLog(this.getClass());
} 

Dynamic search principle :Log  Is an interface declaration .LogFactory  The internal will load the specific log system , And achieve the Log  Implementation class of interface .LogFactory  The process of internal loading log system is as follows :

1、 First , seek org.apache.commons.logging.LogFactory  Attribute configuration .

2、 otherwise , utilize JDK1.3  Start offering service  Discovery mechanism , Can scan classpah  Under the META-INF/services/org.apache.commons.logging.LogFactory file , If found, load the configuration inside , Use the configuration inside .

3、 otherwise , from Classpath  Looking for commons-logging.properties , If found, load according to the configuration inside .

4、 otherwise , Use the default configuration : If you can find Log4j  It is used by default log4j  Realization , Use if not JDK14Logger  Realization , If not, use commons-logging  Provided internally SimpleLog  Realization .

From the above loading process , Just introduce log4j  And in classpath  Configured with log4j.xml , be commons-logging  Will make log4j  Normal use , And the code doesn't need to rely on anything log4j  Code for .

Maven rely on :

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

One 、Commons-logging Simple log implementation :

① newly build commons-logging.properties file , Put in classpath Under the root path :

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

② The code uses

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CommonsTest {
private final static Log logger = LogFactory.getLog(CommonsTest.class);
public static void main(String[] args) {
logger.debug("DEBUG ...CommonsTest");
logger.info("INFO ...CommonsTest");
logger.error("ERROR ...CommonsTest");
}
}

Output :

17:09:33.884 [main] DEBUG com.middleware.test.log.CommonsTest - DEBUG ...CommonsTest
17:09:33.886 [main] INFO com.middleware.test.log.CommonsTest - INFO ...CommonsTest
17:09:33.887 [main] ERROR com.middleware.test.log.CommonsTest - ERROR ...CommonsTest

Two 、Commons-logging Decoupling function of :

commons-logging The most central and useful function is decoupling , its SimpleLog The implementation performance is not as good as other implementations , Such as log4j etc. .

① Add dependency

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

Change commons-logging.properties file : Specify by display log4j

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

And add log4j.properties Configuration file for :

log4j.rootLogger=DEBUG,console
# Output to console
log4j.appender.console=org.apache.log4j.ConsoleAppender
# Set the output style
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# The format of log output information is
log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CommonsTest {
private final static Log logger = LogFactory.getLog(CommonsTest.class);
public static void main(String[] args) {
logger.debug("DEBUG ...CommonsTest");
logger.info("INFO ...CommonsTest");
logger.error("ERROR ...CommonsTest");
}
}

Output :

17:15:00.459 [main] DEBUG com.middleware.test.log.CommonsTest - DEBUG ...CommonsTest
17:15:00.461 [main] INFO com.middleware.test.log.CommonsTest - INFO ...CommonsTest
17:15:00.461 [main] ERROR com.middleware.test.log.CommonsTest - ERROR ...CommonsTest

6、 ... and 、slf4j( Log interface )

6.1、 Simply review the facade pattern

slf4j It's a typical application of facade pattern , So I'm talking about slf4j front , Let's briefly review the facade pattern , Facade mode , Its core is that external communication with a subsystem must be carried out through a unified appearance object , Makes the subsystem easier to use . The structure of the door pattern represented by a graph is :

The core of facade mode is Facade That is, the facade object , The core of the facade object is a few points :

  • Know the functions and responsibilities of all sub roles
  • Delegate the request from the client to the subsystem , There's no real business logic
  • Do not participate in the implementation of business logic in the subsystem

Generally speaking , That's enough for the review of facade mode , Start next to SLF4J Learning from .

6.2、 Why do we use it slf4j

slf4j Its full name is Simple Logging Facade for JAVA,java Simple log face . Be similar to Apache Common-Logging, It is a facade package provided for different log frames , You can access a log implementation scheme without modifying any configuration during deployment . however , He statically binds real at compile time Log library . Use SLF4J when , If you need to use some kind of logging implementation , Then you have to choose the right SLF4J Of jar Collection of bags ( All kinds of bridge packages ).

Why do we use it slf4j, for instance :

 We use... In our own system logback This log system
Our system uses A.jar,A.jar The logging system used in is log4j
Our system is using again B.jar,B.jar The logging system used in is slf4j-simple
such , Our system has to support and maintain at the same time logback、log4j、slf4j-simple Three logging frameworks , Very inconvenient .

Print the log without caring about how to print the log ,slf4j perhaps commons-logging This is the adaptation layer ,slf4j Is the object of this study .

From the description above , We have to know a little bit about :slf4j It's just a log standard , It's not the specific implementation of the log system . It's very important to understand this sentence ,slf4j Do only two things :

  • Provide log interface
  • Provides a way to get specific log objects

slf4j-simple、logback All are slf4j The concrete realization of ,log4j Not directly slf4j, But there is a special bridge slf4j-log4j12 To achieve slf4j.

For a better understanding of slf4j, Let's look at the example first , Reread the source code , I believe that readers will be right slf4j Have a deeper understanding of .

6.3、slf4j Application, for example,

It says ,slf4j Direct / Indirect realization slf4j-simple、logback、slf4j-log4j12, Let's define a pom.xml, To introduce the relevant jar package :

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>

Write a simple paragraph Java Code :


import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestLog {
@Test
public void testSlf4j() {
Logger logger = LoggerFactory.getLogger(Object.class);
logger.info("info test");
logger.warn("warn test");
logger.debug("debug test");
logger.error("error test");
logger.trace("trace test");
}
}

Output :

09:40:10.438 [main] INFO java.lang.Object - info test
09:40:10.445 [main] WARN java.lang.Object - warn test
09:40:10.445 [main] DEBUG java.lang.Object - debug test
09:40:10.445 [main] ERROR java.lang.Object - error test

Note out the following :

<!--<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>-->

Once again, the output :

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

No log output , This proves our point of view :slf4j No specific implementation of logging is provided , Only slf4j It's impossible to print the log .

Then open logback-classic Notes , function Test Method , Let's look at the output of the console as :

10:02:51.496 [main] INFO testlog.TestLog - info test
10:02:51.499 [main] WARN testlog.TestLog - warn test
10:02:51.499 [main] DEBUG testlog.TestLog - debug test
10:02:51.499 [main] ERROR testlog.TestLog - error test

See, we just introduced one slf4j Implementation class of , You can use the log framework to output logs .

Finally, take a test , We open all the logs , introduce logback-classic、slf4j-simple、log4j, function Test Method , The console output is :

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/44075/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/44075/.m2/repository/org/slf4j/slf4j-simple/1.7.25/slf4j-simple-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/44075/.m2/repository/org/slf4j/slf4j-log4j12/1.7.21/slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
10:03:51.185 [main] INFO testlog.TestLog - info test
10:03:51.187 [main] WARN testlog.TestLog - warn test
10:03:51.187 [main] DEBUG testlog.TestLog - debug test
10:03:51.187 [main] ERROR testlog.TestLog - error test

The difference from the above is , Log can be output , However, some alarm logs will be output , Prompt that we have introduced multiple slf4j The implementation of the , Then choose one of them as the logging system we use .

For example, we can draw an important conclusion , namely slf4j The role of : As long as all code uses facade objects slf4j, We don't need to care about its implementation , In the end, a specific implementation can be used everywhere , Replace 、 Maintenance is very convenient .

7、 ... and 、slf4j  And  common-logging  Compare

common-logging Through dynamic search mechanism , Automatically find out the real log library when the program is running . Because it uses ClassLoader Find and load the underlying log Library ,  Led to something like OSGI Such a framework doesn't work , because OSGI Different plug-ins use their own ClassLoader. OSGI This mechanism ensures that plug-ins are independent of each other , But it makes Apache Common-Logging Unable to work .

slf4j Static binding at compile time really Log library , So you can OSGI Use in . in addition ,SLF4J  Support parameterized log character string , Avoid having to write in order to reduce the performance loss of string splicing if(logger.isDebugEnable()), Now you can write directly :logger.debug(“current user is: {}”, user). The assembly message is delayed until it can determine whether to display the message , But the cost of getting parameters is not spared .

8、 ... and 、Log4j  And  LogBack  Compare

LogBack As a general and reliable 、 Fast and flexible logging framework , Will serve as a Log4j Substitution and SLF4J A complete implementation of the new logging system .LOGBack Claim to have excellent performance ,“  Some key operations , For example, determine whether to record a log statement , Its performance has been greatly improved . This operation is LogBack China needs 3 nanosecond , And in the Log4J We need 30 nanosecond . LogBack Create a recorder (logger) It's faster :13 Microsecond , And in the Log4J China needs 23 Microsecond . what's more , It only needs to 94 nanosecond , and  Log4J need 2234 nanosecond , Time has been reduced to 1/23. Follow JUL Compared to the performance improvement is also significant ”.  in addition ,LOGBack All documents of are provided completely free of charge , Don't like Log4J In that way, only part of the free documents are provided and users need to purchase the paid documents .

Nine 、slf4j Bridging with other log components

Use... In application code slf4j Interface , The specific implementation method of access

Other log interfaces are used in the application code , Turn into slf4j Methods  

Ten 、 Log component related history

Java  There are many tools in the world to implement the logging function , The first widely used is  log4j, The log section of many applications is handed over to  log4j, But as a component developer , They want their components not to rely on a single tool , After all, there are many other logging tools at the same time , If an application uses two components , Just two components use different logging tools , Then the application will have two log outputs .

To solve this problem ,Apache Commons Logging ( Formerly called  Jakarta Commons Logging,JCL) make oneself up and go on the stage ,JCL  Only available  log  Interface , The specific implementation dynamically looks for . In this way, component developers only need to target  JCL  Interface development , The application calling the component can match its own logging practice tool at runtime .

So even now you'll still see a lot of applications  JCL + log4j  This collocation , But as the program gets bigger and bigger ,JCL Dynamic binding is not always successful , For specific reasons, you can  Google  once , I won't go into that here . One of the solutions is to statically bind the specified logging tool when the program is deployed , This is it.  SLF4J  Cause of occurrence .

Dynamic binding 、 Static binding :

Java Dynamic binding and static binding - polymorphic - J-Star - Blog Garden One 、 problem Java During method call ,Jvm How to know which class method is called ?Jvm How to deal with it ? Two 、 Concept a、 When subclasses and superclasses ( Interface and implementation classes ) When the same method exists , Subclasses override superclasses ( Interface ) When the method is used , Called by the program at run time https://www.cnblogs.com/xyz-star/p/10152676.html

Follow  JCL  equally ,SLF4J  It's just about providing  log  Interface , The specific implementation is the binder put in when packaging the application ( The name is  slf4j-XXX-version.jar) To decide ,XXX  It can be  log4j12, jdk14, jcl, nop  etc. , They have implemented specific logging tools ( such as  log4j) Binding and proxy work for . for instance : If a program wants to use  log4j  Logging tools , Then the program only needs to be directed at  slf4j-api  Interface programming , And then put it in when you pack it  slf4j-log4j12-version.jar  and  log4j.jar  That's all right. .

Now there's another question , If you are developing a component called by an application that already uses  JCL  Of , There are also some components that may directly call  java.util.logging, Now you need a bridge ( The name is  XXX-over-slf4j.jar) Redirect their log output to  SLF4J, The so-called bridge is a fake log implementation tool , For example, when you put  jcl-over-slf4j.jar  Put it in  CLASS_PATH  when , Even if a component originally passes through  JCL  Output log , Now it will be  jcl-over-slf4j “ In some of the ”SLF4J  in , then  SLF4J  According to the binding machine, the log will be handed over to the specific log implementation tool . The process is as follows

Component

|

| log to Apache Commons Logging

V

jcl-over-slf4j.jar --- (redirect) ---> SLF4j ---> slf4j-log4j12-version.jar ---> log4j.jar --->  Output log

Looking at the flow chart above, you may find an interesting problem , If be in,  CLASS_PATH  At the same time  log4j-over-slf4j.jar  and  slf4j-log4j12-version.jar  What's going to happen ? you 're right , Logs will be kicked around , Finally, it goes into a dead cycle .

So use  SLF4J  The more typical collocation is to  slf4j-api、JCL  Bridge 、java.util.logging(JUL) Bridge 、log4j  Binder 、log4j  this 5 individual  jar  Put in  CLASS_PATH  in .

But not all APP Containers are used  log4j  Of , such as  Google AppEngine  It uses  java.util.logging(JUL), This is the time to apply  SLF4J  The collocation becomes  slf4j-api、JCL Bridge 、logj4 Bridge 、JUL The binder is 4 individual  jar  Put in  WEB-INF/lib  in .

 

copyright:author[Programmer light],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/02/202202130752333385.html