Log Series 1 - Log Structure Framework

Catalog

1. Preface

When it comes to logging tools, you must have heard these terms in your daily work or study: log4j, logback, jdk-logging, slf4j, commons-logging, etc. What is the relationship between them and what role do they play in the whole logging system?
The log framework is divided into three categories, including log facets, log adapters, and log libraries.Decouple using a facade design pattern, Facade, to make log usage easier.The log structure framework is as follows

2. Log Face

The facade design pattern is one of the object-oriented design patterns used by the log framework, similar to the JDBC design concept.It only provides a set of interface specifications and is not responsible for the implementation of the logging function. The purpose is to make users not need to pay attention to which log library is responsible for the details of log printer usage.There are two most widely used log facets: slf4j and commons-logging

3. Log Library

The giant has implemented log-related functions, with three major log libraries: log4j, log-jdk, and logback.The earliest Java attempts to log can only be done through System.out or System.err, which is inconvenient.Log4j was proposed to solve this problem. It was the earliest log library.JDK then introduced a log library, java.util.logging.Logger, for short, log-jdk, in version 1.4.As a result, there are two implementations of log functionality on the market, and developers need to focus on the specific details of the log libraries that apply.Logback is the latest to appear, and it is the same author as log4j, an upgraded version of log4j, and implements the interface of slf4j itself.

4. Log adapter

The log adapter is divided into two scenarios:

  1. Log Face Adapter, since the slf4j specification was later proposed, prior log libraries did not implement the interface of slf4j, such as log4j. Therefore, an additional adapter (slf4j+log4j12) is needed to solve the interface incompatibility problem in order to use the slf4j+log4j mode in the project.

  2. Log library adapter. In some older projects, log library APIs were used directly to print logs for the sake of simplicity. Over time, you want to change Moss, which used to call log libraries directly, to an industry-standard facade mode (such as the slf4j+logback combination), but there are too many places in the old project code to print logs, so you need an adapterThe utility routes from APIs of old log libraries to slf4j so that slf4j can be used to unify log management without changing the original code, and subsequent free replacement of specific log libraries is not an issue.

5. Selection of Log Library

If it is a new project, the slf4j+logback mode is recommended, because logback itself implements the interface of slf4j and does not require additional adapters. Logback is an upgraded version of log4j that has more advantages than log4j and can be integrated with the following configurations:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j-api.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${logback-core.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback-classic.version}</version>
</dependency>

If you are an old project, you need to determine the facade adapter based on the log library you are using. Normally, the old project uses log4j, so for example, the log4j log library can be integrated with the following configuration:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j-api.version}</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${slf4j-log4j12.version}</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>${log4j.version}</version>
</dependency>

If the old code directly uses the interface provided by the log4j log library to print logs, you also need to introduce a log library adapter, which is configured as follows:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>${log4j-over-slf4j.version}</version>
</dependency>

This completes the integration of the log framework with a log configuration file (e.g.Logback.xmlorOg4j.xmlAnd so on), loaded at the start of the project, you can print the log.The sample code is as follows:

private static  final Logger logger =LoggerFactory.getLogger(ConfigureQuartz.class);

Note that the logger object is defined as a static variable because it binds to the current class, avoiding the waste of resources and even causing OutOfMemoryError problems by having a new object each time.

When using slf4j+ log library mode, to prevent log library conflicts, log printing may become ineffective once it occurs.For example, a 500 error occurred on a business's website page, but the development engineer did not find any exception logs when he searched through the system's log files.Offline simulation debugging found that when the error occurred, an exception object was thrown and captured by the framework, and the related code for log printing was executed, but it was not actually output to the log file.After thorough investigation by the development engineer, the log library configured in the current project code is log4j, but a jar package on which the project depends indirectly introduces the logback log library, resulting in the logger reference of the print log actually pointing to the ch.qos.logback.classic.Logger object. The conflict between the two causes the problem of log printing failure.

6.logback.xml configuration file

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true">
	<property name="application_name" value="web" />
    <property name="LOG_PATH" value="c:" />
	 <!-- console output -->
        <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
            <encoder charset="UTF-8">
                <pattern>%date %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
                <!-- <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern> -->
            </encoder>
        </appender>
        <!-- Time Roll Output File Log -->
        <appender name="file—debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>debug</level>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_debug.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
                <MaxHistory>100</MaxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10mb</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder charset="UTF-8">
                <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
            </encoder>
        </appender>
    <!-- Time Roll Output File Log -->
    <appender name="file—info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_info.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
            <MaxHistory>100</MaxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10mb</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
        </encoder>
    </appender>
        <!-- Time Scroll Output level by ERROR Journal -->
        <appender name="file—error" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_error.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
                <MaxHistory>100</MaxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10mb</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder charset="UTF-8">
                <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
            </encoder>
        </appender>


    <Logger name="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" level="DEBUG" additivity="false">
        <appender-ref ref="file—debug" />
    </Logger>

    <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
        <!-- Do not lose logs.Default,If Queue 80%already expired,Will discard TRACT,DEBUG,INFO Level Log -->
        <discardingThreshold>0</discardingThreshold>
        <!-- Change the default queue depth,This value can affect performance.Default value is 256 -->
        <queueSize>256</queueSize>
        <!-- Add Additional appender,Only one can be added at most -->
        <appender-ref ref="file—error"/>
    </appender>

        <root level="info">
            <appender-ref ref="stdout" />
            <appender-ref ref="file—info" />
            <appender-ref ref="file—error" />
        </root>
  
</configuration>

Note: See Log Series 2 - Profile Details for more information on configuration files.

Tags: Java log4j JDK xml

Posted on Tue, 12 May 2020 13:52:37 -0400 by ScOrPi