Learn log4j2 file configuration notes

Posted by acallahan on Tue, 04 Jan 2022 03:39:31 +0100

Zero. Preface

Recently, I thought of using log to print and output in class design, so I thought of log4j2, a log implementation, although a big loophole has been revealed in this log recently. I use slf4j as the facade and log4j2 as the log implementation. This article is just a note I took after learning it briefly. If there are errors, I can point them out in the comment area. If I see them, I will modify them.




1, Profile node resolution

Source: https://www.cnblogs.com/hafiz/p/6170702.html

The root node Configuration has two properties:

  • status attribute: used to specify the print log level of log4j itself. (that is, the level of logs that log4j itself can output)
    • Log level sorting: <-- Log level and priority: off > fat > error > warn > info > debug > trace > all -- >
  • monitorinterval attribute: used to specify the monitoring interval for log4j automatic reconfiguration. The unit is s and the minimum is 5s. (I haven't used this attribute)

There are two nodes in the root node Configuration:

  • Appenders node:

    • My understanding is that filtering and log output format can be achieved by setting an Appender node. For example, the following is an Appender I wrote and output to the console:

      •     <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="[%highlight{%p}{error=red}] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
                <!-- be careful, The filtering here will not affect others appender -->
                <Filters>
                    <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
                </Filters>
            </Console>
        
    • There are three common sub nodes: Console, RollingFile, and File.

      • The Console node is used to define the Appender output to the Console:

        • Name attribute: Specifies the name of the Appender.

        • target attribute: SYSTEM_OUT or SYSTEM_ERR, generally only set the default: SYSTEM_OUT.

        • PatternLayout node: output format, not set. Default is:% m%n.

          • Following sources https://blog.csdn.net/manmanxiaohui/article/details/79922546:
          •     <!-- ========================== Custom output format description================================ -->
                  <!-- %p Output priority, i.e DEBUG,INFO,WARN,ERROR,FATAL -->
                  <!-- %r Output from application startup to output log The number of milliseconds the message took  -->
                  <!-- %c The category to which the output belongs is usually the full name of the class -->
                  <!-- %t Output the name of the thread that generated the log event -->
                  <!-- %m Indicates the log information to print -->
                  <!-- %n Output a carriage return line feed, Windows Platform is“/r/n",Unix Platform is“/n" -->
                  <!-- %d Output the date or time of the log time point. The default format is ISO8601,You can also specify a format after it, such as:%d{yyy MMM dd HH:mm:ss,SSS},Output similar: October 18, 2002 22:10:28921  -->
                  <!-- %l Output the location where the log event occurred, including the category name, the thread that occurred, and the number of lines in the code. give an example: Testlo4.main(TestLog4.java:10)  -->
                  <!-- ========================================================================== -->
            
      • The File node is used to define the Appender of the File exported to the specified location:

        • Name attribute: Specifies the name of the Appender.
        • fileName property: Specifies the destination file of the output log, and the file name with full path.
        • PatternLayout node: output format, not set. Default is:% m%n.
      • The RollingFile node is used to define that if the specified size is exceeded, the old will be automatically deleted and a new Appender will be created (I don't use this for the time being):

        • Name attribute: Specifies the name of the Appender

        • fileName property: Specifies the destination file of the output log, and the file name with full path.

        • PatternLayout node: output format, not set. Default is:% m%n.

        • filePattern property: Specifies the name format of the new log file.

        • Policies node: Specifies the policy of rolling logs, that is, when to create new log files and output logs

          • Timebasedtriggingpolicy node: a child node of Policies. It is a time-based scrolling policy. The interval attribute is used to specify how often to scroll. The default value is 1 hour. modulate=true is used to adjust the time: for example, if it is 3am in the morning and the interval is 4, then the first scroll is 4am, followed by 8am, 12am... Instead of 7am.

          • Sizebasedtriggingpolicy node: the Policies sub node. It is based on the rolling policy of the specified file size. The size attribute is used to define the size of each log file.

        • DefaultRolloverStrategy node: used to specify that when there are at most several log files in the same folder, the oldest one will be deleted and a new one will be created (through the max attribute).

  • Loggers node:

    • There are two common: Root and Logger.
    • Root node:
      • It is used to specify the Root log of the project. If no Logger is specified separately, the Root log output will be used by default.
      • Level attribute: log output level. There are 8 levels, from low to high: all < trace < debug < info < warn < error < fatal < off.
      • AppenderRef node: the child node of Root, which is used to specify the Appender to which the log is output.
    • Logger node:
      • It is used to specify the log form separately, such as specifying different log levels for the class under the specified package.
      • Level attribute: log output level. There are 8 levels, from low to high: all < trace < debug < info < warn < error < fatal < off.
      • name attribute: used to specify the class to which the Logger applies or the full path of the package where the class is located, inherited from the Root node.
      • AppenderRef node: the child node of Logger, which is used to specify the Appender to which the log is output. If it is not specified, it will inherit from Root by default. If it is specified, it will be output in both the specified Appender and the Appender of the Root. At this time, we can set the additivity="false" of the Logger to output only in the customized Appender.




2, Log filtering

Source: https://blog.csdn.net/qq_36066039/article/details/100584785?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.pc_relevant_paycolumn_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.pc_relevant_paycolumn_v2&utm_relevant_index=6

  • Log level:

    • <!-- ALL < TRANCE < DEBUG < INFO < WARN < ERROR < FATAL < OFF-->
    • <ThresholdFilter level="INFO" onMatch="" onMismatch=""/>
      • onMatch: it means how to deal with the current level and above: ACCEPT, NEUTRAL go back, DENY reject
      • onMismatch: it means what should be done below the current level (excluding the current level): ACCEPT, NEUTRAL, go back, DENY, reject
      • (summary: onMatch is > = current level, onMismatch is < current level)
  • Scenario 1: if we want the output from INFO level to ERROR level to the console, others will be ignored. The idea is analyzed as follows.

<!-- After analysis, that is greater than or equal to INFO Level logs go back NEUTRAL Go to the next filter and reject others DENY. Then in the next filter, I let greater than or equal to FATAL Rejection of DENY,Acceptance less than ACCEPT. -->
<Filters>
  <ThresholdFilter level="INFO" onMatch="NEUTRAL " onMismatch="DENY"/>
  <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>

The second way: let those less than FATAL go back, reject others, and then enter the next filter. In the next filter, let those greater than or equal to INFO accept other rejections.

<Filters>
  <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
  <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
  • Scenario 2: I need logs after info and ignore logs lower than info level.
    • This is simpler. It is directly greater than or equal to the acceptance of info and less than the rejection of info.
    • Greater than or equal to: onMath = "ACCEPT" less than onMismatch = "DENY"
<ThresholdFilter level="FATAL" onMatch="ACCEPT" onMismatch="DENY"/>

As long as you don't intercept a log level range, one filter is enough. You don't need to flow NEUTRAL to the second filter. Two filters are required only when the interception log level is greater than a certain level and less than a certain level. The implementation method is described in scenario 1. After reading this article, I believe you can master it thoroughly.

  • To sum up: don't deliberately care about the meaning of ACCEPT NEUTRAL DENY. The core of understanding is: onMatch is how to match logs that are up to and greater than the current level. onMismatch is a log below the current level. It does not contain the current level. What do you want to do. Both onMatch and onMismatch have three values. Whether to flow back to NEUTRAL or ACCEPT accept or DENY.

  • Finally, the complete use is to add it to the Appender:

    •         <Console name="Console" target="SYSTEM_OUT">
                  <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
                  <!-- be careful, The filtering here will not affect others appender -->
                  <Filters>
                      <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
                  </Filters>
              </Console>
      

3, About log levels

Source: https://www.cnblogs.com/hafiz/p/6170702.html

About log level. There are 8 levels in total, from low to high: all < trace < debug < info < warn < error < fatal < off

  • All: the lowest level, which is used to open all log records.
  • Trace: it's trace, that is, when the program advances, you can write trace output, so there should be a lot of trace, but it doesn't matter. We can set the minimum log level to prevent it from being output.
  • Debug: pointing out fine-grained information events is very helpful for debugging applications.
  • Info: messages highlight the running process of the application at a coarse-grained level.
  • Warn: output warning and log below warn level.
  • Error: output the error information log.
  • Fatal: output the log that each serious error event will cause the exit of the application.
  • OFF: the highest level, used to turn OFF all logging.




4, My configuration

  • I use slf4j as the facade here, and then use log4j2 as the implementation:
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.1</version>
            <!-- <scope>test</scope> -->
        </dependency>
  • log4j configuration file, a simple configuration I currently write:
<?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 Internal information output, Can not be set, When set to trace Time, You'll see log4j2 Various internal detailed outputs -->
<Configuration status="OFF">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- be careful, The filtering here will not affect others appender -->
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
            </Filters>
        </Console>
        <!-- Output to fileName One of the files appender -->
        <File name="WarnFile" fileName="./src/main/java/com/jie/log/warn.log" append="true">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- admit of only interpretation warn -->
            <Filters>
                <!-- WARN And above, go to the next filter, All the following are forbidden -->
                <ThresholdFilter level="WARN" onMatch="NEUTRAL" onMismatch="DENY" />
                <!-- ERROR And above are prohibited, All the following are released -->
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT" />
            </Filters>
        </File>
        <File name="ErrorFile" fileName="./src/main/java/com/jie/log/error.log" append="true">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- Receive only error And above -->
            <Filters>
                <ThresholdFilter level="ERROR" onMatch="NEUTRAL" onMismatch="DENY" />
                <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT" />
            </Filters>
        </File>
    </Appenders>
    <Loggers>
        <!-- default root of logger -->
        <!-- there level If the current level includes above, use the following appender -->
        <Root level="all">
            <!-- Input to console appender Use the following one -->
            <AppenderRef ref="Console" />
            <!-- take warn Input to warn.log -->
            <AppenderRef ref="WarnFile" />
            <!-- take error Input to error.log -->
            <AppenderRef ref="ErrorFile" />
        </Root>
    </Loggers>
</Configuration>
  • log4j2 only supports xml format. (log4j supports the properties format)
  • Configuration of others, source: https://www.cnblogs.com/hafiz/p/6170702.html :
<?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>




5, Reason for getLogger(x.class)

  • For public static final logger, logger = loggerfactory getLogger(x.class);, My suggestion is to use this logger only in X, because if I use this logger in Class Y, if I want to block the logs of class X, I will block the logs of class y.

  • For example:

    • public class ServerApplication {
      
          /**
           * The incoming class is used to filter the logs of this class
           */
          public static final Logger logger = LoggerFactory.getLogger(ServerApplication.class);
      
          public static void main(String[] args) {
              logger.info("Server startup.");
              logger.info("Server shutdown.");
          }
      
      }
      
    • public class Other {
      
          private static final Logger logger = LoggerFactory.getLogger(Other.class);
      
          public static void main(String[] args) {
              ServerApplication.logger.warn("Ha ha ha 1");
              logger.warn("Hahaha 2");
          }
      
      }
      
    •         <Logger name="com.jie.server.ServerApplication" level="ERROR" additivity="false">
                  <AppenderRef ref="Console" />
              </Logger>
      
    • I just want to block the logs of the ServerApplication class, but run other After main, I found that only ha ha 2 is output, so I don't recommend using other types of loggers.

Topics: Java