Why log base 4j2?
Apache Log4j 2 is an upgrade to Log4j that provides significant improvements over its predecessor, Log4j 1.x, And provides many of the errors available in Logback while fixing some inherent problems in Logback’s architecture.
Apache Log4j 2 is an upgrade of Log4j that significantly improves Log4j 1.x and provides many of the improvements available in Logback, while addressing some inherent issues in the Logback architecture.
why
-
When reconfigured, both Log4j 1.x and Logback will lose events. Log4j 2 does not. In Logback, exceptions in an Appender are never visible to the application. In Log4j 2, an Appender can be configured to allow exceptions to infiltrate an application.
-
Log4j 2 includes the next generation of asynchronous loggers based on the LMAX Disruptor library. In multithreaded scenarios, asynchronous Loggers have 10 times higher throughput and several orders of magnitude lower latency compared to Log4j 1.x and Logback.
-
For standalone applications, Log4j2 has no garbage, while web applications have less garbage during steady-state logging. This reduces stress on the garbage collector and can provide better response time performance.
-
Log4j 2 uses a plug-in system that makes it easy to extend the framework without making any changes to Log4j by adding new Appenders, Filters, Layouts, Lookups, and Pattern Converters.
-
The plug-in system is simpler to configure. Entries in the configuration do not need to specify class names
-
Supports custom log levels. Custom log levels can be defined in code or configuration.
-
Lambda expressions are supported. Client code running on Java 8 can lazily construct log messages using lambda expressions only if the logging level of the request is enabled. No explicit level checking is required, making the code clearer.
-
Support for message objects. Messaging enables interesting and complex constructs to be delivered through logging systems and to operate efficiently. Users are free to create their own message types and write custom Layouts, Filters, and Lookups to manipulate them.
-
Log4j 1.x supports filters on Appender. The Logback adds TurboFilter to allow the Logger to filter events before they are processed. Log4j 2 supports filters that can be configured to be handled by a Logger before being processed by a Logger or on an add-on.
-
Many Logback appenders do not accept layouts and simply send data in a fixed format. Most Log4j2 appenders accept layouts and allow data to be transferred in whatever format you want.
-
Layout in Log4j 1.x and Logback returns a string. This leads to the problem discussed in Logback encoders. Log4j 2 takes a simpler approach, in that it always returns a byte array. The nice thing about doing this is that it means they can actually be used with any Appender, not just the Appender that writes to the OutputStream.
-
Syslog Appender supports TCP and UDP as well as BSD Syslog and RFC 5424
-
Log4j 2 leverages Java 5 concurrency support and performs locking at the lowest level. Log4j 1.x is known to have deadlock problems. Many of these have been fixed in Logback, but many Logback classes still require a higher level of synchronization.
-
It is an Apache Software Foundation project that follows the community and support model used by all ASF projects. If you want to contribute or earn the right to commit changes, follow the path listed in the contribution.
Explain in detail
For the second point in the above reasons
More information can check website: logging.apache.org/log4j/2.x/p…
Log4j 2’s asynchronous Loggers use lockless data structures, while Logback, Log4j 1.2, and Log4j 2’s asynchronous adders use ArrayBlockingQueue. For blocking queues, multithreaded applications often encounter lock contention when trying to enqueue log events.
Asynchronous logging – Peak throughput comparison
Refer to reason # 7 above
If the corresponding logging level is not enabled, the calculation of log messages can be avoided, which can lead to potential performance improvements for applications that use logging.
logger.trace("Number is {}", getRandomNumber());
Copy the code
In this line of logging code, we call the getRandomNumber() method instead of the log parameter. The getRandomNumber() method executes regardless of the log level, such as DEBUG. But the getRandomNumber() method is executed. In other words, the implementation of this method may not be necessary.
Before adding support for lambda expressions, we can avoid constructing unlogged messages by explicitly checking the log level before executing the log statement:
if (logger.isTraceEnabled()) {
logger.trace("Number is {}", getRandomNumer());
}
Copy the code
By using lambda expressions, we can further simplify the above code:
logger.trace("Number is {}", () -> getRandomNumber());
Copy the code
Lambda expressions are evaluated only if the corresponding logging level is enabled. This is called lazy logging.
We can also use multiple lambda expressions in log messages:
logger.trace("Name is {} and age is {}", () -> getName(), () -> getRandomNumber());
Copy the code
If you’re using Lombok, you can annotate it with @log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
Copy the code
However, if you follow alibaba’s programming conventions, you’ll have to use @slf4j. This is because SLF4J is used as a uniform facade
Synchronous or asynchronous?
Log4j 2 provides two log recording modes: synchronous and asynchronous.
Synchronization logs are generated only after the log output statements are completed, and then the following service logic statements can be executed. For example, the following configuration:
<Configuration>
<Properties>
<! -- Log output level -->
<Property name="LOG_INFO_LEVEL" value="info"/>
<! -- Error level log -->
<Property name="LOG_ERROR_LEVEL" value="error"/>
<! Create a directory named log under current directory -->
<Property name="LOG_HOME" value="./log"/>
<! -- Directory for storing archive logs -->
<Property name="LOG_ARCHIVE" value="./log/archive"/>
<! -- Module name, influence log configuration name, log file name, configure according to your project -->
<Property name="LOG_MODULE_NAME" value="spring-boot"/>
<! -- Log file size, exceeding this size will be compressed
<Property name="LOG_MAX_SIZE" value="100 MB"/>
<! -- How many days to keep the log -->
<Property name="LOG_DAYS" value="15"/>
<! The format of the output log is: %d indicates the date, %thread indicates the thread name, %-5level indicates the level of 5 characters from the left, % MSG indicates the log message, %n indicates the newline character -- -->
<Property name="LOG_PATTERN" value="%d [%t] %-5level %logger{0} - %msg%n"/>
<! -- Interval specifies how often to scroll -->
<Property name="TIME_BASED_INTERVAL" value="1"/>
</Properties>
<Appenders>
<! -- Console output -->
<Console name="STDOUT" target="SYSTEM_OUT">
<! -- Output log format -->
<PatternLayout pattern="${LOG_PATTERN}"/>
<! -- The console only outputs messages of level and above (onMatch). The rest will be rejected (onMismatch) -->
<ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>
<! - this will print out all of the above info, error level the following logs, each size than the size or meet TimeBasedTriggeringPolicy, log will automatically deposit according to (date) (month) (year) to establish the folder below and compression, as archive - >
<RollingRandomAccessFile name="RollingRandomAccessFileInfo"
fileName="${LOG_HOME}/${LOG_MODULE_NAME}-infoLog.log"
filePattern="${LOG_ARCHIVE}/${LOG_MODULE_NAME}-infoLog-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<! Set onMismatch="NEUTRAL" to allow the log to pass through subsequent filters.
<ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="DENY" onMismatch="NEUTRAL"/>
<! -- If info\warn is output -->
<ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<! -- Interval specifies how many times to scroll. The current filePattern setting is once a day -->
<TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
<SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
</Policies>
<! DefaultRolloverStrategy if not set, a maximum of 7 files will be saved in the same folder by default.
<DefaultRolloverStrategy max="${LOG_DAYS}"/>
</RollingRandomAccessFile>
<! Only logs at or above the error level are stored in different files.
<RollingRandomAccessFile name="RollingRandomAccessFileError"
fileName="${LOG_HOME}/${LOG_MODULE_NAME}-errorLog.log"
filePattern="${LOG_ARCHIVE}/${LOG_MODULE_NAME}-errorLog-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
<SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${LOG_DAYS}"/>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<! -- Development environment use -->
<! --<Root level="${LOG_INFO_LEVEL}"> <AppenderRef ref="STDOUT"/> </Root>-->
<! -- Test, production environment use -->
<Root level="${LOG_INFO_LEVEL}">
<AppenderRef ref="RollingRandomAccessFileInfo"/>
<AppenderRef ref="RollingRandomAccessFileError"/>
</Root>
</Loggers>
</Configuration>
Copy the code
Through the info (” whether for asynchronous log: {} “, AsyncLoggerContextSelector. An isSelected ()); You can check whether the log is asynchronous.
Log4j2 provides two ways to implement asynchronous logging, one through AsyncAppender and one through AsyncLogger. ** The Async Logger is officially recommended
- Async Appender. A queue (ArrayBlockingQueue) and a background thread for internal use. Logs are first queued and the background thread retrieves logs from the queue. Blocking queues are susceptible to lock contention, and performance may deteriorate when more threads are logging simultaneously.
- Async Logger. Is * *Log4j2 New function.** Internally using LMAX Disruptor technology, Disruptor is a lockless inter-thread communication library that is not a queue and does not require queuing, resulting in higher throughput and lower latency.
Async Appender
Async Appender is the original asynchronous log implementation of log4j2. It takes other appenders as input, outputs logEvents to the default ArrayBlockingQueue, and then uses another thread to output logs to implement asynchron.
But the official document also says:
This is important in the practice of multi-threaded applications: blocking queues are prone to lock contention, and tests have shown that performance is even worse when a large number of threads are writing to the log concurrently. So consider using ** unlocked Asyn Loggers ** for optimization.
Here are the official examples:
<Configuration status="debug">
<Appenders>
<File name="TEMP" fileName="temp">
<PatternLayout pattern="%r [%t] %p %c %notEmpty{%ndc }- %m%n"/>
</File>
<Async name="ASYNC">
<AppenderRef ref="TEMP"/>
</Async>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="ASYNC"/>
</Root>
</Loggers>
</Configuration>
Copy the code
This is a typical configuration using AsyncAppender. With AsyncAppender configured, writing log events to files is performed in a separate thread.
All configuration items supported by AsyncAppender and what each of them does:
The name of the | type | describe | The default value |
---|---|---|---|
AppenderRef | String | The name of the Appender to invoke asynchronously. Multiple AppenderRef elements can be configured. | |
blocking | boolean | If true, the appender will wait until there are free slots in the queue. If false, the event is written to the Error appender when the queue is full. | true |
shutdownTimeout | integer | How many milliseconds should the Appender wait to flush pending log events in the queue when closed? The default value is zero. | 0(Close immediately) |
bufferSize | integer | Maximum capacity of blocking queues. Default value: 1024. Note that this buffer must be a power of 2 when using BlockingQueue disruptor-style. | 1024 |
errorRef | String | The name of the error appender to invoke if no appender can be invoked due to an error in the appender or if the queue is full. If not specified, the error is ignored. | |
filter | Filter | The filter | |
name | String | The name of the appender | |
ignoreExceptions | boolean | Used to determine whether exceptions that occur during logging event processing need to be logged | true |
BlockingQueueFactory | BlockingQueueFactory | Types of buffers (default ArrayBlockingQueue, can support DisruptorBlockingQueue, JCToolsBlockingQueue, LinkedTransferQueue) | ArrayBlockingQueueFactory |
Async Logger
Internally, AsyncLogger in Log4j2 uses the **Disruptor ** framework. Disruptor is a high-performance queue developed by UK foreign exchange trading company LMAX that supports 6 million orders per second through a single thread. Disruptor is currently used by well-known projects including Apache Strom and Log4j2 to achieve high performance. The internal core data structure of the Disruptor framework is RingBuffer, which is a lockless ring queue.
<Configuration status="debug" name="MyApp" packages="">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/app-%d{yyyy-MM-dd HH}.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="500MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFile2" fileName="logs/app2.log"
filePattern="logs/app2-%d{yyyy-MM-dd HH}.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="500MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<AsyncLogger name="com.abc.Main" level="trace" additivity="false">
<appender-ref ref="RollingFile"/>
</AsyncLogger>
<AsyncLogger name="RollingFile2" level="trace" additivity="false">
<appender-ref ref="RollingFile2"/>
</AsyncLogger>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
Copy the code
During the startup phase of loading log4j2.xml, if AsyncRoot or AsyncLogger configuration is detected, a Disruptor instance will be started.
Global asynchronous mode (best performance, recommended)
JVM startup parameters plus:
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
Copy the code
<! -- Don't forget to set system property -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector to make all loggers asynchronous. -->
<Configuration status="WARN">
<Appenders>
<! -- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
<RandomAccessFile name="RandomAccessFile" fileName="async.log" immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<Root level="info" includeLocation="false">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
</Configuration>
Copy the code
When using AsyncLoggerContextSelector to make all the recorder asynchronous, be sure to use the configuration of the ordinary and elements
Synchronous and asynchronous mixed mode
Synchronous and asynchronous loggers can be combined in configuration. This provides greater flexibility at the cost of slightly reduced performance (compared to making all loggers asynchronous). Use or configure the element to specify the logger that needs to be asynchronous. A configuration can contain only one root logger (or element), but can combine asynchronous and non-asynchronous loggers. For example, a configuration file that contains elements can also contain elements of and synchronize loggers.
By default, asynchronous loggers do not pass location to the I/O thread. If location information is required for a layout or custom filter, you need to set “includeLocation = true” in the configuration of all associated loggers, including the root logger.
<Configuration>
<Properties>
<! -- Log output level -->
<Property name="LOG_INFO_LEVEL" value="info"/>
<! -- Error level log -->
<Property name="LOG_ERROR_LEVEL" value="error"/>
<! Create a directory named log under current directory -->
<Property name="LOG_HOME" value="./log"/>
<! -- Directory for storing archive logs -->
<Property name="LOG_ARCHIVE" value="./log/archive"/>
<! -- Module name, influence log configuration name, log file name, configure according to your project -->
<Property name="LOG_MODULE_NAME" value="spring-boot"/>
<! -- Log file size, exceeding this size will be compressed
<Property name="LOG_MAX_SIZE" value="100 MB"/>
<! -- How many days to keep the log -->
<Property name="LOG_DAYS" value="15"/>
<! The format of the output log is: %d indicates the date, %thread indicates the thread name, %-5level indicates the level of 5 characters from the left, % MSG indicates the log message, %n indicates the newline character -- -->
<Property name="LOG_PATTERN" value="%d [%t] %-5level %logger{0} - %msg%n"/>
<! -- Interval specifies how often to scroll -->
<Property name="TIME_BASED_INTERVAL" value="1"/>
</Properties>
<Appenders>
<! -- Console output -->
<Console name="STDOUT" target="SYSTEM_OUT">
<! -- Output log format -->
<PatternLayout pattern="${LOG_PATTERN}"/>
<! -- The console only outputs messages of level and above (onMatch). The rest will be rejected (onMismatch) -->
<ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>
<! - this will print out all of the above info, error level of logging, each size than the size or meet TimeBasedTriggeringPolicy, log will automatically deposit according to (date) (month) (year) to establish the folder below and compression, as archive - >
<! -- Asynchronous logs are automatically flushed in batches, so set the immediateFlush property to false-->
<RollingRandomAccessFile name="RollingRandomAccessFileInfo"
fileName="${LOG_HOME}/${LOG_MODULE_NAME}-infoLog.log"
filePattern="${LOG_ARCHIVE}/${LOG_MODULE_NAME}-infoLog-%d{yyyy-MM-dd}-%i.log.gz"
immediateFlush="false">
<Filters>
<! Set onMismatch="NEUTRAL" to allow the log to pass through subsequent filters.
<ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="DENY" onMismatch="NEUTRAL"/>
<! -- If info\warn is output -->
<ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<! -- Interval specifies how many times to scroll. The current filePattern setting is once a day -->
<TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
<SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
</Policies>
<! DefaultRolloverStrategy if not set, a maximum of 7 files will be saved in the same folder by default.
<DefaultRolloverStrategy max="${LOG_DAYS}"/>
</RollingRandomAccessFile>
<! Only logs at or above the error level are stored in different files.
<RollingRandomAccessFile name="RollingRandomAccessFileError"
fileName="${LOG_HOME}/${LOG_MODULE_NAME}-errorLog.log"
filePattern="${LOG_ARCHIVE}/${LOG_MODULE_NAME}-errorLog-%d{yyyy-MM-dd}-%i.log.gz"
immediateFlush="false">
<Filters>
<ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
<SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${LOG_DAYS}"/>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<! -- Development environment use -->
<! --<Root level="${LOG_INFO_LEVEL}"> <AppenderRef ref="STDOUT"/> </Root>-->
<! -- Test, production environment use -->
<! <asyncLogger> or <asyncRoot> < Log4jContextSelector >
<AsyncLogger name="com.jourwon" level="${LOG_INFO_LEVEL}" additivity="false">
<AppenderRef ref="RollingRandomAccessFileInfo"/>
<AppenderRef ref="RollingRandomAccessFileError"/>
</AsyncLogger>
<Root level="${LOG_INFO_LEVEL}">
<AppenderRef ref="RollingRandomAccessFileInfo"/>
<AppenderRef ref="RollingRandomAccessFileError"/>
</Root>
</Loggers>
</Configuration>
Copy the code
Log4j2 configuration file description
Recommend to see this article, write quite full: mp.weixin.qq.com/s?__biz=MzI…
In addition, is the reference document the club’s official website: logging.apache.org/log4j/2.x/m…
Two template files
<! -- Log levels and priorities: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<! If log4j2 is traced, you will see the details of the internal output of log4j2 -->
<! --monitorInterval: Log4j automatically detects changes to configuration files and reconfigures itself, sets the interval -->
<configuration status="INFO" monitorInterval="300">
<! -- Define attributes -->
<properties>
<property name="log_deploy_path">logs/deploy</property>
<property name="log_test_path">logs/test</property>
</properties>
<! Define all appenders -->
<appenders>
<! -- Configuration of the output console -->
<Console name="Console" target="SYSTEM_OUT" follow="true">
<! -- Console only outputs messages of level and above (onMatch).
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<! -- Output log format -->
<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n"/>
</Console>
<! -- The file will print out all the information. This log will be automatically cleared every time the program runs, as determined by the append property.
<File name="test_log" fileName="${log_test_path}/testlog.html" append="false">
<! --> < span style = "font-size: 14px;
<HTMLLayout title="Log"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<! --<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n"/>-->
</File>
<! -- This will print all the info level and below information, each time the size of the log exceeds the size, the size of the log will be automatically saved in the folder created by year and month and compressed, as an archive.
<! --${sys:user.home} -->
<RollingFile name="RollingFileInfo" fileName="${log_deploy_path}/info.log"
filePattern="${log_deploy_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<! -- Console only outputs messages of level and above (onMatch).
<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="${log_deploy_path}/warn.log"
filePattern="${log_deploy_path}/$${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 default to a maximum of 7 files in the same folder
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${log_deploy_path}/error.log"
filePattern="${log_deploy_path}/$${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>
<! An appender will not work until logger is defined and appender is appended.
<loggers>
<! -- Filter out spring and Mybatis DEBUG messages -->
<logger name="org.springframework.core" level="INFO">
</logger>
<logger name="org.springframework.beans" level="INFO">
</logger>
<logger name="org.springframework.context" level="INFO">
</logger>
<logger name="org.springframework.web" level="INFO">
</logger>
<logger name="org.apache.http" level="INFO">
</logger>
<logger name="org.mybatis" level="INFO">
</logger>
<! -- Root Logger -->
<root level="all" includeLocation="true">
<appender-ref ref="Console"/>
<AppenderRef ref="test_log"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
Copy the code
<! -- Log levels and priorities: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<! If log4j2 is traced, you will see the details of the internal output of log4j2 -->
<! --monitorInterval: Log4j automatically detects changes to configuration files and reconfigures itself, sets the interval -->
<configuration status="WARN" monitorInterval="1800">
<Properties>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = common configuration = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! -- Set the directory name of the log file -->
<property name="logFileName">qfxLog4jDemoLog</property>
<! -- The default log location can be set to root path or absolute path -->
<! -- Save path 1: Common path, Window platform -->
<! -- <property name="basePath">d:/logs/${logFileName}</property> -->
<! Java project does not have this variable, need to delete, otherwise it will report an exception, here put the log in the root directory of the Web project -->
<! -- <property name="basePath">${web:rootDir}/${logFileName}</property> -->
<! Tocmat logs directory tocmat logs directory tocmat logs
<property name="basePath">${sys:catalina.home}/logs/${logFileName}</property>
<! -- Console default output format,"%-5level": log level,"%l": output full error location, lowercase L, because there is line number display, so affect the performance of the log output -->
<property name="console_log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %l - %m%n</property>
<! -- The default output format of log files without line numbers (line numbers may affect log output performance); %C: uppercase, class name; %M: method name; %m: error message; % n: line -- -- >
<! -- <property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %C.%M - %m%n</property> -->
<! -- Log file default output format, alternative output with line number (log output performance unknown); %C: uppercase, class name; %M: method name; % L: line number; %m: error message; % n: line -- -- >
<property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %C.%M[%L line] - %m%n</property>
<! -- Minimum unit of log default cut -->
<property name="every_file_size">20MB</property>
<! -- Default log output level -->
<property name="output_log_level">DEBUG</property>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = all levels logging configuration = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! Default path for storing logs (all levels of logs) -->
<property name="rolling_fileName">${basePath}/all.log</property>
<! -- Default log compression path. Logs exceeding the specified file size are automatically saved in the folder created by "year" and compressed as an archive -->
<property name="rolling_filePattern">${basePath}/%d{yyyy-MM}/all-%d{yyyy-MM-dd-HH}-%i.log.gz</property>
<! -- Default number of logs that can be stored in a folder of the same type. If this attribute is not set, the default value is 7. FilePattern takes effect only after % I is added.
<property name="rolling_max">500</property>
<! -- Log default log type, how often to generate a new log file, this configuration needs to be combined with filePattern; If filePattern is set to 1,filePattern is in %d{YYYY-MM-dd} to day format. If filePattern is set to 12,filePattern is in %d{YYYY-MM-DD-hh} to hour format.
<property name="rolling_timeInterval">12</property>
<! If this parameter is set to true, the storage time will be adjusted at the boundary of 0 o 'clock. For example, it is 3am in the morning,interval is 4, so the first scroll is at 4am, then 8am, then 12am... Instead of 7am -->
<property name="rolling_timeModulate">true</property>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Info log = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! -- Info Default directory for storing logs (Info level logs) -->
<property name="info_fileName">${basePath}/info.log</property>
<! -- Info Default path to compress logs. Logs exceeding the specified size are automatically saved to a folder created by "year" and compressed as an archive. -->
<property name="info_filePattern">${basePath}/%d{yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz</property>
<! -- Info Specifies the number of logs that can be stored in the same folder by default. If this attribute is not set, the default value is 7.
<property name="info_max">100</property>
<! -- Log default log type, how often to generate a new log file, this configuration needs to be combined with filePattern; If filePattern is set to 1,filePattern is in %d{YYYY-MM-dd} to day format. If filePattern is set to 12,filePattern is in %d{YYYY-MM-DD-hh} to hour format.
<property name="info_timeInterval">1</property>
<! If this parameter is set to true, the storage time will be adjusted at the boundary of 0 o 'clock. For example, it is 3am in the morning,interval is 4, so the first scroll is at 4am, then 8am, then 12am... Instead of 7am -->
<property name="info_timeModulate">true</property>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Warn level log = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! -- Warn log default path (Warn level logs) -->
<property name="warn_fileName">${basePath}/warn.log</property>
<! -- Warn Default log compression path. Logs that exceed the specified file size will be automatically stored in a folder created by "year" and compressed as an archive.
<property name="warn_filePattern">${basePath}/%d{yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz</property>
<! -- Warn Specifies the number of logs that can be stored in the same folder by default. If this property is not set, the default is 7.
<property name="warn_max">100</property>
<! -- Log default log type, how often to generate a new log file, this configuration needs to be combined with filePattern; If filePattern is set to 1,filePattern is in %d{YYYY-MM-dd} to day format. If filePattern is set to 12,filePattern is in %d{YYYY-MM-DD-hh} to hour format.
<property name="warn_timeInterval">1</property>
<! If this parameter is set to true, the storage time will be adjusted at the boundary of 0 o 'clock. For example, it is 3am in the morning,interval is 4, so the first scroll is at 4am, then 8am, then 12am... Instead of 7am -->
<property name="warn_timeModulate">true</property>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Error level log = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! -- Default directory for storing Error logs -->
<property name="error_fileName">${basePath}/error.log</property>
<! -- Error default path to compress logs. Logs that exceed the specified file size are automatically saved to a folder created by "year" and compressed as an archive -->
<property name="error_filePattern">${basePath}/%d{yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz</property>
<! -- The number of Error logs that can be stored in the same folder by default. If this property is not set, the default value is 7.
<property name="error_max">100</property>
<! -- Log default log type, how often to generate a new log file, this configuration needs to be combined with filePattern; If filePattern is set to 1,filePattern is in %d{YYYY-MM-dd} to day format. If filePattern is set to 12,filePattern is in %d{YYYY-MM-DD-hh} to hour format.
<property name="error_timeInterval">1</property>
<! If this parameter is set to true, the storage time will be adjusted at the boundary of 0 o 'clock. For example, it is 3am in the morning,interval is 4, so the first scroll is at 4am, then 8am, then 12am... Instead of 7am -->
<property name="error_timeModulate">true</property>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = the console display control = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<! -- The lowest log level displayed on the console -->
<property name="console_print_level">DEBUG</property>
</Properties>
<! Define appender -->
<appenders>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = is used to define the output to the console configuration = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<Console name="Console" target="SYSTEM_OUT">
<! -- Set the console to output only messages of level and above (onMatch), and reject other messages directly (onMismatch)-->
<ThresholdFilter level="${console_print_level}" onMatch="ACCEPT" onMismatch="DENY"/>
<! Default :%m%n -->
<PatternLayout pattern="${console_log_pattern}"/>
</Console>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =) specified in the print root level above the level of logging to file = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<RollingFile name="RollingFile" fileName="${rolling_fileName}" filePattern="${rolling_filePattern}">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${rolling_timeInterval}" modulate="${warn_timeModulate}"/>
<SizeBasedTriggeringPolicy size="${every_file_size}"/>
</Policies>
<! -- Set the number of logs that can be stored in the same folder. If this property is not set, 7 files can be stored in the same folder by default.
<DefaultRolloverStrategy max="${rolling_max}" />
</RollingFile>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = print INFO log to file = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<RollingFile name="InfoFile" fileName="${info_fileName}" filePattern="${info_filePattern}">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${info_timeInterval}" modulate="${info_timeModulate}"/>
<SizeBasedTriggeringPolicy size="${every_file_size}"/>
</Policies>
<DefaultRolloverStrategy max="${info_max}" />
<Filters>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingFile>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = print WARN level log to file = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<RollingFile name="WarnFile" fileName="${warn_fileName}" filePattern="${warn_filePattern}">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${warn_timeInterval}" modulate="${warn_timeModulate}"/>
<SizeBasedTriggeringPolicy size="${every_file_size}"/>
</Policies>
<DefaultRolloverStrategy max="${warn_max}" />
<Filters>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingFile>
<! - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = print ERROR level log to file = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -- -- >
<RollingFile name="ErrorFile" fileName="${error_fileName}" filePattern="${error_filePattern}">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${error_timeInterval}" modulate="${error_timeModulate}"/>
<SizeBasedTriggeringPolicy size="${every_file_size}"/>
</Policies>
<DefaultRolloverStrategy max="${error_max}" />
<Filters>
<ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingFile>
</appenders>
<! An appender will only work if logger is defined and appender is appended.
<loggers>
<! -- Set the print SQL statement configuration, the following two use together, can optimize the log output information, reduce some unnecessary information output -->
<! SQL > select 'DEBUG' from 'java.sql' to 'DEBUG';
<logger name="java.sql" level="DEBUG" additivity="false">
<appender-ref ref="Console"/>
</logger>
<! Set org.mybatis. Spring to only print logs of WARN and higher levels.
<logger name="org.mybatis.spring" level="WARN" additivity="false">
<appender-ref ref="Console"/>
</logger>
<! Set org.springframework package to only print logs of WARN and higher levels.
<logger name="org.springframework" level="WARN" additivity="false">
<appender-ref ref="Console"/>
</logger>
<! Com.qfx.workflows. Service specifies logs of WARN and higher levels.
<logger name="com.qfx.workflow.service" level="WARN" additivity="false">
<appender-ref ref="Console"/>
</logger>
<! Print SQL statement config end -->
<! Create a default root logger-->
<root level="${output_log_level}">
<appender-ref ref="RollingFile"/>
<appender-ref ref="Console"/>
<appender-ref ref="InfoFile"/>
<appender-ref ref="WarnFile"/>
<appender-ref ref="ErrorFile"/>
</root>
</loggers>
</configuration>
Copy the code
Reference:
- www.baeldung.com/log4j-2-laz…
- logging.apache.org/log4j/2.x/
- www.iocoder.cn/Spring-Boot…
- Bryantchang. Making. IO / 2018/11/18 /…
- www.cnblogs.com/yeyang/p/79…
- My.oschina.net/u/1584802/b…