Stories are late, but he is never absent. Today’s story begins. Are you ready?
A prelude to
A brief introduction to my wife: a li, a woman of wisdom and beauty, said, “We have a heart in sync, don’t we?” Let me instantly “fall”.
Q: Wife, do you still remember what gifts I gave you during the holidays in previous years?
Ali: Of course I remember: on children’s Day, I sent a row of Wang Zai milk and a big bag of snacks. 5·20 sent a perfume I like; Goddess festival bought me a super nice bag……
Q: These are all from this year. Do you still remember last year’s?
Ali: Let me see: last Christmas I bought a Santa Claus cake and a pair of beautiful high heels; Birthday time sent a bunch of flowers and a big red envelope; HMM…
A Q: see, see can’t remember, I know time long remember, I will give you say once: bala Bala (show satisfied expression).
Ali: Wow, you’re good. How did you do that?
Ah Q: Ha ha, this has to say I used the log, you can listen well.
To the chase
Introduction of LogBack
Q: The log I’m talking about is the same as the diary we wrote before, but it is a collection of files used to record operating system events. Common logging frameworks include the following:
- Java Util Logging
- Logback
- Log4j
- Log4j2
- JCL (Jakarta Commons Logging)
- Slf4j (Simple Logging Facade For Java)
Ali: So many frames, which one should I use?
Q: Logback is my first choice. First, it is easy to configure and use. Secondly, the configuration is flexible and can meet the needs of most projects; Finally, the performance is better and logs can be stored asynchronously. I think that’s why it’s so popular in the market and used so much in projects.
Ali: Uh-oh, I’ll pick it.
Q: Logback is a log system built by slF4J’s log facade. The relationship between facade and implementation is understood.
Here is the official website, which is divided into the following three modules:
- Logback-core: the base module of the other two modules;
- Logback – classic: it is
log4j
An improved version of the new version, and it’s fully implementedslf4j API
, you can easily switch to other logging frameworks (e.glog4j
orJUL
); - Logback-access: access modules and
Servlet
Container integration is provided throughHttp
To access the log function, you can easily inlogback
Build your own modules on top of the core.
logback
Relationships between componentsYou can get a general understanding of the actual combat chapter is easier to understand:
Logger
As the logger of the log, associate it with the corresponding of the applicationcontext
The log is used to store log objects and define log types and levels.Appender
This can be a console, a file, a remote socket server,MySQL
,PostreSQL
,Oracle
And other databases,JMS
And the remoteUNIX Syslog
Daemons, etc.Layout
Responsible for converting events into strings, formatted log information output. inlogback
In theLayout
Objects are encapsulated inencoder
;Logger Context
: eachlogger
They’re all linked to oneLoggerContext
It is responsible for manufacturinglogger
And is also responsible for arranging them in a tree structurelogger
. All of the otherlogger
Also throughorg.slf4j.LoggerFactory
Class static methodsgetLogger
To obtain.
Logger can be assigned Level including: TRACE, DEBUG, INFO, WARN, and the ERROR definition in ch. Qos. Logback. Classic. Level class. If logger is not assigned a level, it inherits the level from the nearest ancestor that has the assigned level. The default logger level is DEBUG.
The levels are in the following order: TRACE < DEBUG < INFO < WARN < ERROR
The project of actual combat
Ali: Too wordy. Let’s get into the real world.
Q: OK, if you are creating a regular Maven project, you need to import poM files:
<! Slf4j </groupId> <artifactId> slf4J-api </artifactId> <version>1.730.</version> </dependency> <! --> <dependency> <groupId>ch.qos. Logback </groupId> <artifactId>logback-classic</artifactId> <version>1.23.</version>
</dependency>
Copy the code
Logback reads the following configuration files from the classpath:
- logback.groovy
- logback-test.xml
- logback.xml
If none of the files exist, LogBack automatically configates itself with a BasicConfigurator, which results in records being output to the console.
Basic Information Configuration
Code test samples are attached:
public class TestLogBack {
private static final Logger logger = LoggerFactory.getLogger(TestLogBack.class);
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace"); }}}Copy the code
First we create logback.xml under Resources and then configure it
<configuration>
<! ${name} --> ${name} -->
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n"/>
<! -- Log output format: %d{YYYY-MM-DD HH: MM :ss.SSS} Time % FULL name of class C %M Method %L Line number % Thread Thread name %M or % MSG information %n newline -->
<! Appender for console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<! -- Control output stream object default system. out we can change to system. err for testing purposes -->
<target>System.err</target>
<! -- Log message format configuration -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<! -- Define log file save path attribute -->
<property name="log_dir" value="/logs"/>
<! Appender for log file output
<appender name="file" class="ch.qos.logback.core.FileAppender">
<! -- Log file save path -->
<file>${log_dir}/logback.log</file>
<! -- Log message format configuration -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<! Appender for HTML file output -->
<appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
<! -- Log file save path -->
<file>${log_dir}/logback.html</file>
<! -- HTML message format configuration -->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<! -- <pattern>${pattern}</pattern>-->
<pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%m</pattern>
</layout>
</encoder>
</appender>
<! -- Root Logger configuration -->
<root level="ALL">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
<appender-ref ref="htmlFile"/>
</root>
</configuration>
Copy the code
Log and logback. HTML are two log files in /log file. Generally, only logs ending in. Log are used in projects.
Ali: Oh, you found it through this file, didn’t it take too much effort to find it with so many lines of log generated every day? Besides, the file is too big to open.
Ah Q: Of course, please keep reading
<! Appender for log splitting and archive compression
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<! -- Log file save path -->
<file>${log_dir}/roll_logback.log</file>
<! -- Log message format configuration -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<! -- Specify split rule -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<! %d{yyyY-MM-dd} --> %d{yyyY-MM-dd} -->
<! Split by file size -->
<maxFileSize>1MB</maxFileSize>
<! Declare split filename according to time and compression format -->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-mm-ss}.log%i.gz</fileNamePattern>
</rollingPolicy>
</appender>
Copy the code
At this point, we apply a for loop to the test program, which loops 1W times and generates new files per second or every time it exceeds 1M. You can also add a filter under appender to filter the desired log level.
<! -- Log level filter -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<! -- Log filtering rules -->
<level>ERROR</level>
<! Receive (record) -->
<onMatch>ACCEPT</onMatch>
<! Reject (no record) -->
<onMismatch>DENY</onMismatch>
</filter>
Copy the code
Ali: That makes it much clearer. How did you discover the strategy of dividing files you mentioned above? Can you tell me what your evidence is?
Ah Q: Ok, let’s have a few pictures to feel it
- To open the first
RollingFileAppender
You can see there’s one under himRollingPolicy
strategy
2. Click to find that it is an interface, and then look at its implementation class, we findSizeAndTimeBasedRollingPolicy
Strategy let’s see3. Find the file size property in this classmaxFileSize
, but without finding the properties of the file according to time, we enter its parent classTimeBasedRollingPolicy
To view4. It is found that there is this property in itTimeBasedRollingPolicy
Set beforeFileNamePattern
options
Ali: I have another question. The system needs to print logs during execution. Is it inefficient?
Q: No, to improve performance, it also supports asynchronous log output, which can greatly improve performance.
<! -- Asynchronous log -->
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
<! Specify a specific appender -->
<appender-ref ref="rollFile"/>
</appender>
Copy the code
In addition to root, custom loggers are also supported.
<! Additivity ="false" -- custom logger object additivity="false" -- custom logger object additivity="false" -- custom logger object additivity="false"
<logger name="com.aq.logback" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
Copy the code
SpringBoot used in
Ali: Now that I think of it, you are talking about regular Maven projects. Is the common SpringBoot project also used in this way?
Q:If it isSpringBoot
Project words, it is used by defaultslf4j
As a journal facade,logback
Logging as a logging implementation, so we don’t need to introduce any dependencies, the default isinfo
Level.
We can also use the @slf4J annotation directly instead of the above
private static final Logger logger = LoggerFactory.getLogger(TestLogBack.class);
Copy the code
The reference is to use log.info(“info”); To implement. Its default loading order is logback-spring. XML ->logback.xml
This can be easily configured in application.properties
# specify the logging level of the custom Logger object
logging.level.com.itzyq.sblogback=trace
Specifies the console output message format
logging.pattern.console=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread] ===== %m %n
# specify where to store log files (deprecated)
#logging.file=/logs/springboot.log
The default directory for storing log files is spring.log
logging.file.path=/logs/springboot/
# specify the message format for the log file
logging.pattern.file=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread] ===== %m %n
Copy the code
Since the configuration capabilities in properties are limited, we will use the logback.xml configuration described above.
Ali: Ai, why not use logback-spring.xml?
Q: Logback-spring. XML is recommended for SpringBoot, because it is a normal Maven project.
Logback-spring. XML only works when the Spring application is running, that is, when the class with the @SpringBootApplication annotation is started. We can definitely use it here.
It also has a special feature that can be used to resolve the log configuration.
<configuration>
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n"/>
<! -- Define log file save path attribute -->
<property name="log_dir" value="/logs"/>
<! Appender for log file output
<appender name="file" class="ch.qos.logback.core.FileAppender">
<! -- Log file save path -->
<file>${log_dir}/logback.log</file>
<! -- Log message format configuration -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<springProfile name="dev">
<pattern>${pattern}</pattern>
</springProfile>
<springProfile name="pro">
<pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %m%n</pattern>
</springProfile>
</encoder>
</appender>
<root level="info">
<appender-ref ref="file"/>
</root>
</configuration>
Copy the code
Add Spring.profiles. Active =dev or pro to application.properties to switch between test and formal environments.
Logback-access
Ali: It is, and while we’re at it, can you say something about logback-access?
Q: Ok, let me outline its configuration and use: the Logback-Access module integrates with Servlet containers (such as Tomcat and Jetty) and provides HTTP access logging. We can use the logback-access module to replace the Tomcat access log;
-
Copy logback-access.jar and logback-core.jar to $TOMCAT_HOME/lib/.
-
Modify the Host element in $TOMCAT_HOME/conf/server. XML to add:
<Value className="ch.qos.logback.access.tomcat.LogbackValue" />
Copy the code
This line is usually nested within an
or
element.
logback
The default in$TOMCAT_HOME/conf
Look up the filelogback-access.xml
, the official address of the configuration:http://logback.qos.ch/access.html#configuration
<configuration>
<! -- always a good activate OnConsoleStatusListener -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>access.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<! -- Log message expression format -->
<pattern>% % h % l % u [t] "% r" % s % b "% {Referer}" I "% I {the user-agent}"</pattern>
<pattern>combined</pattern>
</encoder>
</appender>
<appender-ref ref="FILE" />
</configuration>
Copy the code
Configuration Information Supplement
Ali: Is that the end?
Q: Because it is difficult to display all the logback configuration information in the previous section, the specific configuration information is listed here for your reference.
(1) The root node configuration, which contains the following three properties:
- Scan: When this property is set to
true
, the configuration file will be reloaded if it changes. The default value istrue
. - ScanPeriod: indicates the interval for checking whether the configuration file has been modified. If no time unit is given, the default unit is milliseconds. when
scan
fortrue
“, this attribute takes effect. The default interval is 1 minute. - Debug: When this property is set to
true
, will print outlogback
You can view internal logs in real timelogback
Running status. The default value isfalse
.
<configuration scan="true" scanPeriod="60 seconds" debug="false"> </configuration>Copy the code
(2) contextName: used to set the contextName. Each logger is associated with the logger context. The default contextName is default. However, the contextName can be set to a different name to distinguish between records for different applications. Once set, it cannot be modified.
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>myAppName</contextName>
</configuration>
Copy the code
(3) Property: used to define variable values. It has two properties, name and value. The value defined by property is inserted into the logger context and can be used by “${}”.
name
: The name of the variablevalue
: is the value defined by the variable
Timestamp: gets the timestamp string, which has two attributes key and datePattern
key
: identifies thetimestamp
The name of;datePattern
: Sets the mode to convert the current time (the time to parse the configuration file) to a string, followjava.txt.SimpleDateFormat
The format.
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
</configuration>
Copy the code
(5) Appender: A component that writes logs and has two required properties name and class. Name specifies the name of the appender, and class specifies the fully qualified name of the appender
5.1. ConsoleAppender outputs logs to the console with the following subnodes:
encoder
: Formats logs.target
String:System.out
(Default) orSystem.err
5.2. FileAppender: To add logs to a file.
file
: Indicates the name of the file to be written to. It can be a relative or absolute directory. If the upper-level directory does not exist, the system automatically creates the file and has no default value.append
: if it istrue
, the log is appended to the end of the file, if yesfalse
, empty existing files, default istrue
.encoder
: Formats recorded events.prudent
: if it istrue
, logs will be safely written to files, even if othersFileAppender
Is also writing to this file, inefficient, default isfalse
.
5.3. RollingFileAppender: Logs are rolled to a specified file and to another file when a condition is met. Have the following sub-nodes:
file
: Indicates the name of the file to be written to. It can be a relative or absolute directory. If the upper-level directory does not exist, the system automatically creates the file and has no default value.append
: if it istrue
, the log is appended to the end of the file, if yesfalse
, empty existing files, default istrue
.rollingPolicy
: Determines when a roll occursRollingFileAppender
Behavior involving file movement and renaming. attributeclass
Define a concrete rolling policy class.
5.4, strategy: class = “ch. Qos. Logback. Core. Rolling. TimeBasedRollingPolicy” : the most commonly used rolling strategy, it according to time to make the rolling strategy, is responsible for rolling is also responsible for triggering the scroll. Have the following sub-nodes:
fileNamePattern
: required node, including filename and ‘%d’ conversion,"% d"
Can contain ajava.text.SimpleDateFormat
Specified time format, for example:%d{yyyy-MM}
. If you use it directly%d
, the default format isyyyy-MM-dd
.RollingFileAppender
thefile
Child nodes are optional by settingfile
, you can specify different locations for active and archive files, and the current log is always logged tofile
The specified file (active file), the name of the active file will not change; If it’s not setfile
, the active file name will be based onfileNamePattern
The value of, changes at regular intervals. “/” or “\” are used as directory separators.maxHistory
: Optional node that controls the maximum number of archived files that can be retained. If the number exceeds the maximum number, old files will be deleted.
If scrolling is set to 6 per month, only files in the last 6 months are saved and old files in the previous 6 months are deleted. Note that when old files are deleted, directories that were created for archiving are also deleted.
Class = “ch. Qos. Logback. Core. Rolling. SizeBasedTriggeringPolicy” : the size of the file to view the current activity, if more than a specified size will inform RollingFileAppender trigger scroll the current active file. Only one node:
maxFileSize
: This is the size of the active file. The default is10MB
.prudent
: when totrue
Is not supportedFixedWindowRollingPolicy
. supportTimeBasedRollingPolicy
, but there are two limitations, 1 does not support or allow file compression, 2 cannot be setfile
Property, must be left blank.triggeringPolicy
: let us knowRollingFileAppender
Properly enable scrolling.
Class = “ch. Qos. Logback. Core. Rolling. FixedWindowRollingPolicy” renaming files according to the fixed window algorithm of rolling strategy. Have the following sub-nodes:
minIndex
: Minimum window index valuemaxIndex
: Maximum window index. If the specified window is too large, the window is automatically set to 12.fileNamePattern
: Must contain"% I '
For example, assume that the minimum and maximum values are 1 and 2, respectively, and the naming pattern ismylog%i.log
, produces an archive filemylog1.log
andmylog2.log
. You can also specify file compression options, for example,mylog%i.log.gz
Or nolog%i.log.zip
<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> // The above configuration means that a log FILE is generated every day and stored for 30 days.Copy the code
<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> Generate a new log file. The window size is 1 to 3, and when three archives are saved, the earliest log is overwritten.Copy the code
Encoder: Formats recorded events. It is responsible for converting log information into byte arrays and writing byte arrays to the output stream.
PatternLayoutEncoder is the only useful and default encoder with a Pattern node that sets the input format for the log. Use “%” plus “conversion”. If you want to print “%”, you must escape “\%” with “\”.
(6) Child node Logger: used to set the log printing level of a package or a specific class and specify appenders. There is only a name attribute, an optional level attribute, and an optional additivity attribute. It can contain zero or more elements that indicate that the appender will be added to the logger
- Name: used to specify this
logger
A package of constraints or a specific class; - Level: Used to set the print level (log level), case insensitive:
TRACE
.DEBUG
.INFO
.WARN
.ERROR
.ALL
和OFF
, and a special valueINHERITED
Or synonymsNULL
To enforce the superior level. If this property is not set, the currentlogger
Will inherit the rank of the superior. - Additivity: Whether or not to superiors
loger
Pass print information. The default istrue
.
(7) Child node root: It is also a Logger element, but it is the root Logger and the parent of all Loggers. There is only one level attribute, because name is already named “root” and is already the highest level. As with logger, you can have zero or more appender-ref elements that indicate that the appender will be added to the logger.
level
: Used to set the print level, case insensitive:TRACE
.DEBUG
.INFO
.WARN
.ERROR
.ALL
andOFF
Cannot be set toINHERITED
Or synonymsNULL
. The default isDEBUG
Common Logger Configuration
<! - show the parameters for SQL for hibernate hibernate custom - > < logger name = ". Org. Hibernate. The 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"/>Copy the code
Ali: Honey, you are so considerate. I also want to use it to record my wonderful life!
If you have different ideas or better ideas, please feel free to contact Ah Q: follow GZH “Ah Q said code”, or add your friend Qingqing-4132, Ah Q is looking forward to your arrival!