Java log technology
1. Concept of log
1.1 types of log files
- Debug log
- system log
2.Java log framework
2.1 why use the log framework
- The software is complex, and there are too many design knowledge, content and topics.
- A small system does not need to use the log framework. You can concentrate on completing the business logic of the system by using someone else's framework.
2.2 popular log framework [log facade technology]
Log facade technology is interface oriented programming. Seamless switching of various log frameworks. [similar to JDBC]
Unpopular: JCL is a facade technology, but it also provides implementation, slf4j also provides implementation, but it is not needed. log4j is an implementation technology, but it also provides a facade API, but it is generally not used.
2.2.1 log facade
- JCL,slf4j
Advantages of log facade
- 1. Interface oriented programming to reduce coupling [by importing different log implementation classes, flexibly switching frameworks and unified configuration to facilitate project log management]
- 2. Unified API, hiding the details at the bottom of different frameworks, and hiding the API of log implementation framework. Easy to learn and use.
2.2.2 log implementation
- JUL[jdk comes with], logback[spring default], log4j, log4j2 [best performance]
3. Log framework from getting started to not getting started
3.0 all configuration files
3.0.1 JUL [the core is logManager and Logger object code]
## RootLogger processor (set when getting) handlers= java.util.logging.ConsoleHandler ## RootLogger processor (set when printing logs) .handlers= RootLogger.java.util.logging.FileHandler # RootLogger log level .level= INFO ## TestLog log processor TestLog.handlers= java.util.logging.FileHandler # TestLog log level TestLog.level= INFO # Ignore parent log processing TestLog.useParentHandlers=false ## Console processor # Output log level java.util.logging.ConsoleHandler.level = INFO # Output log format java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter ## File processor # Output log level java.util.logging.FileHandler.level=INFO # Output log format java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter # Output log file path java.util.logging.FileHandler.pattern = D:\\TestLog.log # Output log file limit size (50000 bytes) java.util.logging.FileHandler.limit = 50000 # Limit the number of output log files java.util.logging.FileHandler.count = 10 # Is the output log file appended java.util.logging.FileHandler.append=true
3.0.2 Log4j [the core is configuration file and Appender]
log4j.rootLogger=trace,console # Custom logger log4j.logger.com.biturd = info, file # The naming convention is generally the package name, which is user-defined # This is the level that inherits the rootLogger, which will be overwritten and appended by the appender log4j.logger.org.apache = error # Flexible log output log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m %n log4j.appender.file = org.apache.log4j.FileAppender log4j.appender.file.layout = org.apache.log4j.PatternLayout log4j.appender.file.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.file.file = /logs/log4j.log log4j.appender.file.encoding = UTF-8 log4j.appender.rollingFileAppender = org.apache.log4j.RollingFileAppender log4j.appender.rollingFileAppender.layout = org.apache.log4j.PatternLayout log4j.appender.rollingFileAppender.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.rollingFileAppender.file = /logs/log4j.log log4j.appender.rollingFileAppender.encoding = UTF-8 log4j.appender.rollingFileAppender.maxFileSize = 1MB log4j.appender.rollingFileAppender.maxBackupIndex = 10 log4j.appender.dailyRollingFileAppender = org.apache.log4j.DailyRollingFileAppender log4j.appender.dailyRollingFileAppender.layout = org.apache.log4j.PatternLayout log4j.appender.dailyRollingFileAppender.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.dailyRollingFileAppender.file = /logs/log4j.log log4j.appender.dailyRollingFileAppender.encoding = UTF-8 log4j.appender.dailyRollingFileAppender.datePattern = '.'yyyy-MM-dd-HH-mm-ss log4j.appender.dbAppender = org.apache.log4j.jdbc.JDBCAppender log4j.appender.dbAppender.layout = org.apache.log4j.PatternLayout log4j.appender.dbAppender.driver = com.mysql.jdbc.Driver log4j.appender.dbAppender.url = jdbc:mysql:///test # jdbc:mysql://localhost:3306/test log4j.appender.dbAppender.user = root log4j.appender.dbAppender.password = root log4j.appender.dbAppender.sql = INSERT INTO LOGGING (log_date, log_level, location, message) VALUES ('%d{ISO8601}', '%-5p', '%C,%L', '%m')
3.1 JUL [implementation framework]
There are two ways to output logs logger.log(Level.INFO, "msg"); // General method logger.info("123456"); // Special method logger. [level] ("[information]");
assembly[Non specific class]Call procedure - Application - Logger Set two contents 1. Level 2. Log message content - Handler Specify output path[Console, file, network] - Layouts[Formatters] (Format before output) - Filter[Fine grained log interception]
Log level control
There are seven log levels in total, which are controlled by values. By default, only those with higher default values than Logger.INFO are output. If you manually set the level of the Logger, you will output a higher level than that set manually.
If the dependency in Maven is test, an error will be reported if it is written under the main directory [the guide package cannot be found]
@Test public void testQuick() throws Exception{ Logger logger = Logger.getLogger("com.biturd.JULTest"); // Each logger needs to have a unique identification logger.info("hello jul"); logger.log(Level.INFO, "msg"); String name = "123456"; int a = 123456; logger.log(Level.INFO, "User information: character string{0},number{1}",new Object[]{name,a}); }
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle); public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle); public static final Level WARNING = new Level("WARNING", 900, defaultBundle); public static final Level INFO = new Level("INFO", 800, defaultBundle); public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle); public static final Level FINE = new Level("FINE", 500, defaultBundle); public static final Level FINER = new Level("FINER", 400, defaultBundle); public static final Level FINEST = new Level("FINEST", 300, defaultBundle); public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
@Test public void testLogLevel() throws Exception{ Logger logger = Logger.getLogger("com.biturd.JULTest"); // Each logger needs a unique identifier, usually a fully qualified class name logger.severe("server"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
Underlying principle and user-defined configuration file
- logger - demandLogger - LogManager.getLogManager() -ensureLogManagerInitialized() [Load profile] - readConfiguration public void readConfiguration() throws IOException, SecurityException { checkPermission(); // if a configuration class is specified, load it and use it. String cname = System.getProperty("java.util.logging.config.class"); if (cname != null) { try { // Instantiate the named class. It is its constructor's // responsibility to initialize the logging configuration, by // calling readConfiguration(InputStream) with a suitable stream. try { Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname); clz.newInstance(); return; } catch (ClassNotFoundException ex) { Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname); clz.newInstance(); return; } } catch (Exception ex) { System.err.println("Logging configuration class \"" + cname + "\" failed"); System.err.println("" + ex); // keep going and useful config file. } } String fname = System.getProperty("java.util.logging.config.file"); if (fname == null) { fname = System.getProperty("java.home"); if (fname == null) { throw new Error("Can't find java.home ??"); } File f = new File(fname, "lib"); f = new File(f, "logging.properties"); fname = f.getCanonicalPath(); } try (final InputStream in = new FileInputStream(fname)) { final BufferedInputStream bin = new BufferedInputStream(in); readConfiguration(bin); } } E:\Java\jre\lib\logging.properties logManager Is a singleton object,So all the front and back are one object The load stream must have been applied.
@Test public void testLogProperties() throws Exception{ // Load profile InputStream ins = JULTest.class.getClassLoader().getResourceAsStream("logging.properties"); // Create logManager LogManager logManager = LogManager.getLogManager(); // Loading configuration files through logManager logManager.readConfiguration(ins); Logger logger = Logger.getLogger("com.biturd"); logger.severe("server"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
Profile overview
## RootLogger processor (set when getting) handlers= java.util.logging.ConsoleHandler ## RootLogger processor (set when printing logs) .handlers= RootLogger.java.util.logging.FileHandler # RootLogger log level .level= INFO ## TestLog log processor TestLog.handlers= java.util.logging.FileHandler # TestLog log level TestLog.level= INFO # Ignore parent log processing TestLog.useParentHandlers=false ## Console processor # Output log level java.util.logging.ConsoleHandler.level = INFO # Output log format java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter ## File processor # Output log level java.util.logging.FileHandler.level=INFO # Output log format java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter # Output log file path java.util.logging.FileHandler.pattern = D:\\TestLog.log # Output log file limit size (50000 bytes) java.util.logging.FileHandler.limit = 50000 # Limit the number of output log files java.util.logging.FileHandler.count = 10 # Is the output log file appended java.util.logging.FileHandler.append=true
3.2 Log4j [implementation framework]
0. Code example
@Test public void QuickStartLog4j(){ // Do not use the configuration file in the default way // BasicConfigurator.configure(); // Get logger object Logger logger = Logger.getLogger(log4jTest.class); // Logging output logger.info("hello log4j"); logger.fatal("A fatal error that caused the system to crash"); // frequently-used logger.error("Error messages that do not stop the system"); logger.warn("Possible error warning messages"); logger.info("Operation information,Data connection, network connection IO,Operation, etc"); logger.debug("debug information,Generally used in development,Record program variable parameter transfer information, etc"); logger.trace("Tracking information,Record all process information of the program"); }
1.Log4j components
- Loggers controls the output level of the log and whether the log is output
- How the "Appenders" log is output
- Layout controls the output format of the log
1). Loggers Logger [inherits RootLogger by default]
In the early days, it was called Category, so it can be regarded as an alias of Category class
2). Appenders
3). Layouts
2. Source code analysis
- org.apache.log4j.logger - org.apache.log4j.logManager [Read configuration information] - stay Loader.getResource();Read configuration file - OptionConverter.selectAndConfigure();Load profile internal information - Then add the configuration information to rootLogger upper - configureRootCategory() - parseCategory() - parseCategory()Parsing information [StringTokenizer st = new StringTokenizer(value, ",");]
I don't know what the configuration file says. Check it here<< Learning framework methodology > >
In addition, there is the ognl expression set method
3. Others
3.1 Loglog: Log4j built-in log switch
3.2 use of layout
Specified by an ognl expression.
log4j.rootLogger=trace,console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n # %l == %c+%t+%F+%L
3.3 use of appender
- Console
- File [two subclasses, parent or child can be selected]
- Rolling [split by size]
- DailyRolling [split by time]
3.3.1 File
You need to specify an output file
log4j.appender.file = org.apache.log4j.FileAppender log4j.appender.file.layout = org.apache.log4j.PatternLayout log4j.appender.file.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.file.file = /logs/log4j.log log4j.appender.file.encoding = UTF-8
3.3.2 Rolling
log4j.appender.rollingFileAppender = org.apache.log4j.RollingFileAppender log4j.appender.rollingFileAppender.layout = org.apache.log4j.PatternLayout log4j.appender.rollingFileAppender.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.rollingFileAppender.file = /logs/log4j.log log4j.appender.rollingFileAppender.encoding = UTF-8 log4j.appender.rollingFileAppender.maxFileSize = 1MB log4j.appender.rollingFileAppender.maxBackupIndex = 10 # [more than ten will overwrite old logs]
3.3.3 DailyRolling
log4j.appender.dailyRollingFileAppender = org.apache.log4j.DailyRollingFileAppender log4j.appender.dailyRollingFileAppender.layout = org.apache.log4j.PatternLayout log4j.appender.dailyRollingFileAppender.layout.conversionPattern = [%p]%r %l %d{yyyy-mm-dd HH:mm:ss.SSS} %m%n #Specify the location of log output [ognl expression] log4j.appender.dailyRollingFileAppender.file = /logs/log4j.log log4j.appender.dailyRollingFileAppender.encoding = UTF-8 log4j.appender.dailyRollingFileAppender.datePattern = '.'yyyy-MM-dd-HH-mm-ss # [complete, most appropriate is by day]
3.3.4 JDBCAppender
log4j.appender.dbAppender = org.apache.log4j.jdbc.JDBCAppender log4j.appender.dbAppender.layout = org.apache.log4j.PatternLayout log4j.appender.dbAppender.driver = com.mysql.jdbc.Driver log4j.appender.dbAppender.url = jdbc:mysql:///test # jdbc:mysql://localhost:3306/test log4j.appender.dbAppender.user = root log4j.appender.dbAppender.password = root log4j.appender.dbAppender.sql = INSERT INTO log(preject_name, create_date, log_level, category,file_name,thread_name,line,all_category, message) VALUES ('pro_name', '%d{yyyy-MM-dd HH:mm:ss}', '%p', '%c', '%F','%t', '%L' , '%l' ,'%m')
3.4 user defined logger
log4j.logger.com.biturd = info, file # The naming convention is generally the package name, which is user-defined # This is the level that inherits the rootLogger, which will be overwritten and appended by the appender log4j.logger.org.apache = error # Flexible log output
The default is to inherit the rootlogger
- Before experiment
No print123456
- After the experiment
Print 123456
It can be seen that log4j determines how to use a custom logger through the package name
- principle
The log print logger object is compared with multiple customized loggers in the configuration file through the package name. If it is not found, the default rootlogger is used.
3.3 JCL [facade frame] [only these types are supported, so they are eliminated]
Background of appearance of facade frame: Jul - > log4j is used for small projects at the initial stage, and the frame needs to be switched at the later stage, which is troublesome
@Test public void testQuickJCL(){ Log log = LogFactory.getLog(JCLTest.class); log.info(123456); }
- 1. When there is no log4j dependency, jul is used by default
- Log4j is used by default when there is a log4j dependency
3.3.1 principle
// Range of log classes to find private static final String[] classesToDiscover = { LOGGING_IMPL_LOG4J_LOGGER, "org.apache.commons.logging.impl.Jdk14Logger", "org.apache.commons.logging.impl.Jdk13LumberjackLogger", "org.apache.commons.logging.impl.SimpleLog" };
// Find the specific implementation of the log class for(int i=0; i<classesToDiscover.length && result == null; ++i) { result = createLogFromClass(classesToDiscover[i], logCategory, true); }
// Using reflection technology to find classes according to name strings try { c = Class.forName(logAdapterClassName, true, currentCL); } catch (ClassNotFoundException originalClassNotFoundException) { // If you find it constructor = c.getConstructor(logConstructorSignature); Object o = constructor.newInstance(params); // Note that we do this test after trying to create an instance // [rather than testing Log.class.isAssignableFrom(c)] so that // we don't complain about Log hierarchy problems when the // adapter couldn't be instantiated anyway. if (o instanceof Log) { logAdapterClass = c; logAdapter = (Log) o; break; } // The adapter adapts the constructor of the found log class and the Name of the log class to the instance property. if (logAdapterClass != null && affectState) { // We've succeeded, so set instance fields this.logClassName = logAdapterClassName; this.logConstructor = constructor; // Identify the <code>setLogFactory</code> method (if there is one) try { this.logMethod = logAdapterClass.getMethod("setLogFactory", logMethodSignature); ....... } return logAdapter;
3.4 SLF4j [door frame]
Note that SLF4J-enabling your library implies the addition of only a single mandatory dependency, namely slf4j-api.jar. If no binding is found on the class path, then SLF4J will default to a no-operation implementation. slf4j This means that only one mandatory dependency is added, slf4j-api.jar. If no binding is found on the classpath,He defaults to no operation implementation.[It's just a set of interfaces]
3.4.1 principle:
// If there are multiple implementations, print and use the first implementation framework if (isAmbiguousStaticLoggerBinderPathSet(binderPathSet)) { Util.report("Class path contains multiple SLF4J bindings."); Iterator i$ = binderPathSet.iterator();
3.4.2 log bridging technology
3.4.3 [bridging technology] cause of dead loop [bridging cannot occur simultaneously with adapter (jar package)]
3.5 logback [implementation framework]
https://www.cnblogs.com/gavincoder/p/10091757.html
3.5.0 basic code
Dependency
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- Just import logback-classic That's it,The dependent will be imported automatically -->
<?xml version="1.0" encoding="utf-8" ?> <configuration debug="true"> <property name="pattern" value="%d{HH:mm:ss.SSS} [%thread] [%-5level] %logger{36} - %msg%n"></property> <property name="log_back" value="/logs"></property> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <target>System.err</target> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> </appender> <appender name="file" class="ch.qos.logback.core.FileAppender"> <!-- Where to save the log --> <file>${log_dir}/logback.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> </appender> <appender name="htmlFile" class="ch.qos.logback.core.FileAppender"> <file>${log_dir}/logback.html</file> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%d{HH:mm:ss.SSS} [%thread] [%-5level] %logger{36} - %msg%n"</pattern> </layout> </encoder> </appender> <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log_dir}/logback.html</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxFileSize>1MB</maxFileSize> </rollingPolicy> </appender> <root level="ALL"> <appender-ref ref="console"></appender-ref> </root> </configuration>
3.5.1 three modules
- Logback core: the foundation of the other two modules
- Logback classic: an improved version of log4j [fully implements the api of slf4j]
- Logback access: the access module is integrated with the servlet container to provide the function of accessing logs through Http
3.5.2 high level usage [filter, asynchronous log and user-defined logger]
<!-- Filter usage --> <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log_dir}/logback.html</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxFileSize>1MB</maxFileSize> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMisMatch>DENY</onMisMatch> </filter> </appender> <!-- Asynchronous log --> <appender name="async" class="ch.qos.logback.classic.AsyncAppender"> <!-- Specify a specific Appender --> <appender-ref ref="rollFile"/> </appender> <root level="ALL"> <appender-ref ref="console"></appender-ref> <appender-ref ref="async"></appender-ref> </root> <!-- custom logger object additivity Decide whether to integrate rootLogger --> <logger name="com.biturd" level="info" additivity="false"> <appender-ref ref="console"/> </logger>
3.5.3 log4j format to logback [pattern changed]
3.5.4 logback access usage
Use this to replace tomcat or jetty's log
3.6 log4j2[implementation framework]
Although it is also a log facade, it is customary to use slf4j as a log facade
1.log4j2 log facade usage [understand]
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.2</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <!--Log level and prioritization: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--Configuration hinder status,This is used to set log4j2 The internal information output can not be set when it is set to trace You'll see log4j2 Various internal detailed outputs--> <!--monitorInterval: Log4j It can automatically detect and modify the configuration file and reconfigure itself, and set the interval seconds--> <configuration status="WARN" monitorInterval="30"> <!--Define all first appender--> <appenders> <!--Configuration of this output console--> <console name="Console" target="SYSTEM_OUT"> <!--Format of output log--> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </console> <!--The file will print out all the information, this log The program will be emptied automatically every time it is run, and the append Attribute decision, which is also very useful and suitable for temporary testing--> <File name="log" fileName="log/test.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <!-- This will print out all the information info And below, each time the size exceeds size,Then this size Logs of size are automatically saved by year-The folder created in the month is compressed as an archive--> <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log"> <!--Console output only level And above( onMatch),Other direct rejection( onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> </RollingFile> <RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> <!-- DefaultRolloverStrategy If the property is not set, it defaults to up to 7 files in the same folder. Here, 20 files are set --> <DefaultRolloverStrategy max="20"/> </RollingFile> <RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> </RollingFile> </appenders> <!--Then define logger,Only defined logger And introduced appender,appender Will take effect--> <loggers> <!--Filter out spring and mybatis Some useless DEBUG information--> <logger name="org.springframework" level="INFO"></logger> <logger name="org.mybatis" level="INFO"></logger> <root level="all"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> <appender-ref ref="RollingFileWarn"/> <appender-ref ref="RollingFileError"/> </root> </loggers> </configuration>
2. log4j2 asynchronous log principle
Two ways
- AsyncAppender
- AsyncLogger
<!-- log4j2 Dependencies to be provided for asynchronous logging --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.3.4</version> </dependency>
3.7 application in springboot
Although using the default logback, you can set the log frame information in application.xml instead of importing the logback.xml file, but it is generally rough, so you still need a specific configuration file
SpringBoot Starters contains a series of dependency packages that can be integrated into the application. You can integrate Spring and other technologies in a one-stop manner without looking for sample code and dependency packages everywhere. If you want to use Spring JPA to access the database, you can use it by adding Spring boot starter data JPA initiator dependency. https://blog.csdn.net/qq_35974759/article/details/871682 fifty-seven
Starters contains many dependencies that need to be used in projects. They can run quickly and continuously. They are a series of supported management transitive dependencies.
Dependency: depend on who you point to
3.8 code summary
JUL
Logger logger = Logger.getLogger("com.biturd.JULTest"); // Each logger needs to have a unique identification logger.info("hello jul"); logger.log(Level.INFO, "msg");
log4j
// Do not use the configuration file in the default way // BasicConfigurator.configure(); LogLog.setInternalDebugging(true); // Get logger object Logger logger = Logger.getLogger(log4jTest.class); // Logging output logger.info("hello log4j"); logger.fatal("A fatal error that caused the system to crash"); // frequently-used logger.error("Error messages that do not stop the system"); logger.warn("Possible error warning messages"); logger.info("Operation information,Data connection, network connection IO,Operation, etc"); logger.debug("debug information,Generally used in development,Record program variable parameter transfer information, etc"); logger.trace("Tracking information,Record all process information of the program");
JCL
Log log = LogFactory.getLog(JCLTest.class); log.info(123456);
slf4j[key points]
public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class); @Test public void testSlf4j(){ LOGGER.warn("123456"); LOGGER.error("123456"); }
log4j2 [own facade]
public static final Logger LOGGER = LogManager.getLogger(log4j2Test.class); @Test public void testQuick() throws Exception{ LOGGER.fatal("fatal"); LOGGER.error("error"); LOGGER.warn("warn"); LOGGER.info("info"); LOGGER.debug("debug"); LOGGER.trace("trace"); }
Various dependencies of slf4j [repeat if it is more important]
1. slf4j-jdk
2. slf4j-log4j
3. slf4j-logback
4.slf4j-log4j2
Others, such as bridging technology [detailed: https://blog.csdn.net/jeikerxiao/article/details/62423749 ]
Use slf4j to unify various logs
When a project uses multiple logging API s, it can be uniformly adapted to slf4j, and then the underlying implementation can be adapted through slf4j.
In the middle, slf4j is used to unify the API s of various logging frameworks used in the project, and then forwarded to slf4j. Slf4j then implements the logging system with a logging framework that the developer wants to use at the bottom, so as to achieve the unified implementation of various logs.
-
Adapter from old log API to slf4j
-
slf4j adapter to new log implementation
Problem: the following API s have been used in current application s to program logs:
- commons-logging
- jdk-loging
Now I want to uniformly give the log output to log4j1.
Solution: [two]
- Convert all the above log systems to slf4j [bridging technology]
- Remove commons logging (it can not be removed), and use jcl-over-slf4j (bridging) to switch the underlying log output of Commons logging to sl4j
- Use jul-to-slf4j (bridging) to switch Jul's log output to slf4j
- Let slf4j select log4j1 as the underlying log output
- Add slf4j-api.jar
- Add slf4j-log4j12.jar
- Add log4j.jar