Detailed Spring Boot log

log

If you look at the Spring boot log, skip directly to 3

1. Log framework

Case:
Xiao Zhang; develop a large-scale system;
​ 1. System.out.println(""); print key data on the console; remove? write in a file?
​ 2. The framework to record some runtime information of the system; the log framework; zhanglogging.jar
; Asynchronous mode? Automatic filing? xxx? zhanglogging-good.jar?
​ 4. Remove the previous frame love? Change to a new framework and re-modify the previous related API; zhanglogging-prefect.jar?
5. JDBC—database framework;
wrote a unified interface layer; log facade (an abstract layer of logs); logging-abstract.jar
can import specific log implementations into the project; our previous log frameworks are all implemented abstraction layer;

Logging frameworks on the market:
JUL, JCL, Jboss-logging, logback, log4j, log4j2, slf4j…

Log Facade (Abstraction Layer for Logs) log implementation
JCL (Jackrta-Commons-logging) Last updated 2014, less maintenance
SLF4j(Simple Logging Facade for java)
jboss-logging has limited usage scenarios, specific frameworks use
log4j
JUL (java.util.logging) ~~
~~ Log4j2

Logback

Log facade: SLF4j;
Log implementation: Logback;

Spring Boot: The bottom layer is the Spring framework, the Spring framework is JCL by default, commons-logging
Spirng Boot: excludes commons-logging, chooses SLF4j and logback

2. Using SLF4J

1. How to use SLF4j in the system

In the future development, the call of the logging method should not directly call the implementation class of the log, but call the method in the log abstraction layer; import the jar of slf4j and the implementation jar of logback into the system

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

Illustration:

Each log implementation framework has its own configuration file. After using slf4j, the configuration file is still made into the configuration file of the log implementation framework itself.

2. Legacy issues

Case: SLF4j+logback: Spring (commons-logging), hibernate (jboss-logging), Mybatis, xxx
unified logging, even if other frameworks use SLF4j for output together with me?

How to make all logs in the system unified to SLF4j?
1. Exclude other logging frameworks in the system first;
2. Replace the original logging framework with intermediate packages;
3. Import other implementations of slf4j.

3. Spring Boot log relationship

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

Spring Boot uses it for logging:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>

Bottom-level dependencies:

Summary:
1) The bottom layer of SpringBoot also uses slf4j+logback for logging;
2), SpringBoot also replaces other logs with slf4j;
3), intermediate replacement package?

jcl-over-slfj:1.7.25:

public abstract class LogFactory {

    static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";

    static LogFactory logFactory = new SLF4JLogFactory();

4) If we want to introduce other frameworks, we must exclude the default log dependencies of this framework.
The Spring framework uses commons-logging, which has been excluded for us;

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

Spring Boot can automatically adapt to all logs, and the bottom layer uses slf4j+logback to record logs. When introducing other frameworks, you only need to exclude the log framework that this framework depends on.

4. Using Spring Boot logs

1. Default configuration

Spirng Boot configures the log for us by default:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot03LoggingApplicationTests {

    // 记录器
    Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    public void contextLoads() {
        // System.out.println();

        // 日志的级别;
        // 由低到高 trace < debug < info < warn < error
        // 可以调整需要输出的日志级别;日志只会在这个级别和以后的高级别生效

        logger.trace("这是trace日志...");
        logger.debug("这是debug日志...");
        // Springboot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别,root级别
        logger.info("这是info日志...");
        logger.warn("这是warn日志...");
        logger.error("这是error日志...");
    }

}

Spring Boot modifies the default logging configuration:

logging.level.com.atguigu=trace

# logging.path
# 当前项目下生成springboot.log日志
# 可以指定完整的路径;
#logging.file=E:/springboot.log

# 在当前磁盘的根路径下创建spring文件夹和里卖年的log文件夹;使用 spring.log 作为默认文件
logging.path=/spring/log

# 在控制台输出的日志格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} === - %msg%n

log format:

        <!--
        日志输出格式:
            %d表示日期时间,
            %thread表示线程名,
            %-5level:级别从左显示5个字符宽度
            %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
            %msg:日志消息,
            %n是换行符
        -->

2, designated placement

Just put each logging framework's own configuration file in \src\main\resources on the classpath; SpringBoot does not use its default configuration.

logback.xml: It is directly recognized by the logging framework;
logback-spring.xml: The logging framework cannot directly load the log configuration items, and SpringBoot parses the log configuration. SpirngBoot's advanced Profile feature can be used.

<springProfile name="staging">
    可以指定某段配置在某个环境下生效
</springProfile>

Otherwise, an error is reported,

no applicable action for [springProfile]
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="atguigu-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
            %d表示日期时间,
            %thread表示线程名,
            %-5level:级别从左显示5个字符宽度
            %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
            %msg:日志消息,
            %n是换行符
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <springProfile name="dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ----> %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
        </layout>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 
            可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
            且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
            那些为了归档而创建的目录也会被删除。
            -->
            <MaxHistory>365</MaxHistory>
            <!-- 
            当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 日志输出格式: -->     
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 
        logger主要用于存放日志对象,也可以定义日志类型、级别
        name:表示匹配的logger类型前缀,也就是包的前半部分
        level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
        additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
        false:表示只用当前logger的appender-ref,true:
        表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->
    <!-- hibernate logger -->
    <logger name="com.atguigu" level="debug" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>



    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
    -->
    <root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 

5. Switch the log framework (meaningless, slf4j+logback is already the best implementation)

You can switch according to the log of log4j with pictures;
slf4j+log4j:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--排除转换包-->
            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>log4j-over-slf4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--添加slf4j依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

slf4j+log4j2:
pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--排除logging,使用slf4j+log4j2-->
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
            <!--排除转换包,使用slf4j+log4j-->
<!--            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>log4j-over-slf4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>-->
        </dependency>

        <!--添加slf4j依赖,使用slf4j+log4j-->
<!--        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

log4j2-spring.xml

<?xml version="1.0" encoding="utf-8"?>
<!--日志级别:TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出-->
<!--
    status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出
    monitorInterval : Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。此处表示每隔300秒重读一次配置文件
-->
<Configuration status="ERROR" monitorInterval="300">
    <!--<properties>-->
    <!--<property name="LOG_HOME">F:\logs</property>-->
    <!--<property name="ERROR_LOG_FILE_NAME">error</property>-->
    <!--</properties>-->
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT"> <!-- 定义类型为Console的Appender -->
            <PatternLayout pattern="%d{HH:mm:ss} [%level] %c{10} - %msg%n"/> <!-- 定义类型为Pattern的Layout -->
        </Console>
    </Appenders>
    <!--定义logger,只有定义了logger并引入上面的appender,appender才会生效-->
    <Loggers>
        <Root level="error"> <!-- 定义Root Logger -->
            <AppenderRef ref="Console"/> <!-- Root Logger的Appender引用上面定义的Console -->
        </Root>
        <!--定义名字为MainLogger的Logger,其日志级别为info,info以下级别的信息将不会输出 -->
        <Logger name="MainLogger" level="info" additivity="false">
            <AppenderRef ref="Console"/> <!-- Root Logger的Appender引用上面定义的Console -->
        </Logger>
    </Loggers>
</Configuration>

exhibit:

19:16:00 [INFO] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - Started SpringBoot03LoggingApplicationTests in 2.046 seconds (JVM running for 3.655)
19:16:00 [TRACE] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - 这是trace日志...
19:16:00 [DEBUG] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - 这是debug日志...
19:16:00 [INFO] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - 这是info日志...
19:16:00 [WARN] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - 这是warn日志...
19:16:00 [ERROR] com.atguigu.springboot.SpringBoot03LoggingApplicationTests - 这是error日志...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324665361&siteId=291194637