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 islog4jAn improved version of the new version, and it’s fully implementedslf4j API, you can easily switch to other logging frameworks (e.glog4jorJUL);
  • Logback-access: access modules andServletContainer integration is provided throughHttpTo access the log function, you can easily inlogbackBuild your own modules on top of the core.

logbackRelationships between componentsYou can get a general understanding of the actual combat chapter is easier to understand:

  • LoggerAs the logger of the log, associate it with the corresponding of the applicationcontextThe log is used to store log objects and define log types and levels.
  • AppenderThis can be a console, a file, a remote socket server,MySQL,PostreSQL,OracleAnd other databases,JMSAnd the remoteUNIX SyslogDaemons, etc.
  • LayoutResponsible for converting events into strings, formatted log information output. inlogbackIn theLayoutObjects are encapsulated inencoder;
  • Logger Context: eachloggerThey’re all linked to oneLoggerContextIt is responsible for manufacturingloggerAnd is also responsible for arranging them in a tree structurelogger. All of the otherloggerAlso throughorg.slf4j.LoggerFactoryClass static methodsgetLoggerTo 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

  1. To open the firstRollingFileAppenderYou can see there’s one under himRollingPolicystrategy

2. Click to find that it is an interface, and then look at its implementation class, we findSizeAndTimeBasedRollingPolicyStrategy 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 classTimeBasedRollingPolicyTo view4. It is found that there is this property in itTimeBasedRollingPolicySet beforeFileNamePatternoptions

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 isSpringBootProject words, it is used by defaultslf4jAs a journal facade,logbackLogging as a logging implementation, so we don’t need to introduce any dependencies, the default isinfoLevel.

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;

  1. Copy logback-access.jar and logback-core.jar to $TOMCAT_HOME/lib/.

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

  1. logbackThe default in$TOMCAT_HOME/confLook 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 totrue, 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. whenscanfortrue“, this attribute takes effect. The default interval is 1 minute.
  • Debug: When this property is set totrue, will print outlogbackYou can view internal logs in real timelogbackRunning 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 variable
  • value: is the value defined by the variable

Timestamp: gets the timestamp string, which has two attributes key and datePattern

  • key: identifies thetimestampThe name of;
  • datePattern: Sets the mode to convert the current time (the time to parse the configuration file) to a string, followjava.txt.SimpleDateFormatThe 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.
  • targetString: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 othersFileAppenderIs 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 occursRollingFileAppenderBehavior involving file movement and renaming. attributeclassDefine 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.SimpleDateFormatSpecified time format, for example:%d{yyyy-MM}. If you use it directly%d, the default format isyyyy-MM-dd.
  • RollingFileAppenderthefileChild nodes are optional by settingfile, you can specify different locations for active and archive files, and the current log is always logged tofileThe 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 onfileNamePatternThe 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 totrueIs not supportedFixedWindowRollingPolicy. supportTimeBasedRollingPolicy, but there are two limitations, 1 does not support or allow file compression, 2 cannot be setfileProperty, must be left blank.
  • triggeringPolicy: let us knowRollingFileAppenderProperly 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 value
  • maxIndex: 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.logandmylog2.log. You can also specify file compression options, for example,mylog%i.log.gzOr 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 thisloggerA package of constraints or a specific class;
  • Level: Used to set the print level (log level), case insensitive:TRACE.DEBUG.INFO.WARN.ERROR.ALLOFF, and a special valueINHERITEDOr synonymsNULLTo enforce the superior level. If this property is not set, the currentloggerWill inherit the rank of the superior.
  • Additivity: Whether or not to superiorslogerPass 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.ALLandOFFCannot be set toINHERITEDOr 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!