日志框架整合SpringBoot保姆级教程+日志文件拆分(附源码)

目录

介绍

日志概述

日志文件

调试日志

系统日志

日志框架

日志框架的作用

日志框架的价值

流行的日志框架

SLF4J日志门面

介绍

环境搭建简单测试

集成log4j

logback 

Logback简介

Logback中的组件

Logback配置文件

日志输出格式

控制台输出日志

输出日志到指定普通文件

输出日志到html文件

日志文件拆分

过滤日志等级

 异步日志

自定义logger

log4j2 

简介

特征

自动重新加载配置

高级过滤

插件架构

无垃圾机制

案例实现

日志文件拆分

SpringBoot整合

整合logBack实现日志拆分 

 整合log4j2实现日志拆分

​编辑 源码地址


介绍

日志概述

只要程序员投身在实际的学习和生产环境中,就会对日志的重要性有着充分的认知,尤其是对于 Web 以及更高级的应用。在很多情况下,日志可能是我们了解应用如何执行的唯一方式。

但是现实是很多程序员对于日志的记录的认知比较肤浅,认为日志的记录输出是一件很简单而且会自动发生的事情,所以会经常忽略和日志相关的问题。

所以本课程主要就是针对于对于日志概念以及日志的框架不太熟悉的这类开发人群,更加详细且真实的体会日志为我们在开发和生产环境当中所带来的好处。

Java 语言的强大之处就是因为它强大而且成熟的生态体系。其中包括日志框架,就有很多成熟的开源资源可以直接使用。

日志文件

日志文件是用于记录系统操作事件的文件集合。它具有处理历史数据、诊断问题的追踪以及理解系统的活动等重要的作用。

调试日志

在软件开发中,我们要去经常的调试程序,或者做一些状态的输出,便于我们查询程序的运行状况。为了让我们能够更加灵活且方便的控制这些调试信息,我们肯定是需要更加专业的日志技术。我们平时在调试程序的过程中所使用的肯定就是专业开发工具自带的debug功能,可以实时查看程序运行情况,但不能有效保存运行情况的信息。调试日志是能够更加方便的去“重现”这些问题。

系统日志

系统日志是用来记录系统中硬件、软件和系统相关问题的信息。同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找收到攻击是留下的痕迹。

系统日志包括系统日志、应用日志和安全日志这几种分类。

日志框架

日志框架的作用
  • 控制日志输出的内容和格式。
  • 控制日志输出的位置。
  • 日志文件相关的优化,如异步操作、归档、压缩..
  • 日志系统的维护。
  • 面向接口开发 - 日志的门面。
日志框架的价值

因为软件系统发展到了今天非常的复杂,特别是服务器的软件,涉及到的知识和内容问题非常的多。对于日志记录来讲,在某些方面使用别人研发好的成熟的框架,这就相当于让别人帮你完成一些基础的工作。让我们可以有更多的时间去关注、处理我们的业务逻辑问题。

比如事务处理,日志记录等一些安全性的问题,我们使用框架丢做,不会影响业务的开发效率。

同时框架也是在不断升级的,我们可以不断的享受框架为我们带来的好处。

流行的日志框架
  • JUL

java.util.logging JAVA原生日志框架

  • Log4j

Apache的一个开源项目

  • Logback

由Log4j之父做的另一个开源项目,业界称之为log4j后浪,一个可靠、通用且灵活的java日志框架

  • Log4j2

Log4j官方的第二个版本,各个方面都与Logback及其相似,具有插件式结构、配置文件优化等特征。SpringBoot1.4版本以后就不再支持log4j,所以第二个版本——log4j2应运而生。

  • JCL

日志门面

  • SLF4J

日志门面

SLF4J日志门面

介绍

    简单日志门面(Simple Logging Facade For Java)SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如 log4j和 logback等。当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出 SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。

环境搭建简单测试

  引入依赖

        <!--slf4j核心依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!--slf4j自带简单日志实现-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

测试日志

 

 可以看到只打印了info和error信息,因为slf4j的默认日志打印级别就是info级

集成log4j

下面使用log4j实现来进行日志的打印
导入log4j所需依赖,注意要注释掉之前得slf4j自带的简单实现依赖

logback 

Logback简介

Logback 是由 log4j 创始人设计的又一个开源日志组件。

Logback 当前分成三个模块: logback-core,logback-classic和logback-access。

logback-core 是其它两个模块的基础模块。

logback-classic 是 log4j的一个改良版本。此外 logback-classic 完整实现SLF4J API。使你可以很方便地更换成其它日志系统如 log4j或JDK14 Logging。

logback-access 访问模块与 Servlet 容器集成提供通过 Http 来访问日志的功能。

Logback中的组件

  • Logger:日志的记录器,

主要用于存放日志对象,也可以定义日志类型、级别。

  • Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。
  • Layout:负责把事件转换成字符串,格式化的日志信息的输出。在Logback 中Layout 对象被封装在 encoder 中.也就是说我们未来使用的 encoder 其实就是 Layout

Logback配置文件

Logback提供了3种配置文件。

  • logback.groovy
  • logback-test.xml
  • logback.xml

如果都不存在则采用默认的配置。

日志输出格式

标识符及占位符

描述

%-10level

级别,设置10个这符,左对齐

%d{yyyy-MM-dd HH:mm:ss.SSS}

日期时间

%c

当前类全限定名

%M

当前执行日志的方法

%L

行号

%thread

线程名称

%m或者%msg

输出的日志信息

%n

换行

控制台输出日志

引入所需依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

        <!--slf4j日志门面 核心依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
        </dependency>

        <!--
           logback-core是logback-classic的基础模块
           logback-classic已经涵盖了 logback-core,
           Maven有依赖传递性,会自动依赖logback-core
        -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.10</version>
        </dependency>

在资源目录下新建xml配置文件

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>


    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
        <appender-ref ref="consoleAppender"/>
    </root>

</configuration>

测试:

 

输出日志到指定普通文件

我们在部署项目到服务器里通常都是直接通过日志文件进行查看日志的,而这时就需要将日志信息输出到指定位置的指定文件中

添加输出日志文件配置

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!--    日志文件输出路径-->
    <property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!--    保存的日志文件名-->
    <property name="fileName" value="logback.log"></property>
    <!--文件appender,默认是以追加日志的形式进行输出的-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${fileName}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>



    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
        <appender-ref ref="consoleAppender"/>
        <appender-ref ref="fileAppender"/>
    </root>

</configuration>

启动测试:

 

来到xml文件中配置的文件输出位置

 

 可以看到控制台的日志信息已经输出到logback.log文件中了,此时再重启测试,观察日志文件信息的变化:

可以看到日志信息是默认进行追加,不是覆盖

输出日志到html文件

在输出日志时,还可以将日志文件输出为html文件,来进行可读性比较好的阅读

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!--    日志文件输出路径-->
    <property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!--    保存的日志文件名-->
    <property name="fileName" value="logback.log"></property>
    <!--文件appender,默认是以追加日志的形式进行输出的-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${fileName}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <property name="htmlFileName" value="logback.html"></property>
    <property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property>
    <!--HTML文件appender-->
    <appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${htmlFileName}</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>${htmlPattern}</pattern>
            </layout>
        </encoder>
    </appender>
    



    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
        <appender-ref ref="consoleAppender"/>
        <appender-ref ref="fileAppender"/>
        <appender-ref ref="htmlFileAppender"/>
    </root>

</configuration>

启动测试:

 可以看到html版本的日志文件可读性和ui要比普通文件要美观一些,但是html文件比较占用内存,所以在实际开发中,如果项目的日志文件比较多的情况下并不推荐使用html版

日志文件拆分

在实际开发中,项目的日志有时候会非常的多,此时日志文件如果不进行拆分将会导致日志文件过大,有时甚至上G,所以可以对日志进行配置拆分策略来进行解决

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!--    日志文件输出路径-->
    <property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!--    保存的日志文件名-->
    <property name="fileName" value="logback.log"></property>
    <!--文件appender,默认是以追加日志的形式进行输出的-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${fileName}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <property name="htmlFileName" value="logback.html"></property>
    <property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property>
    <!--HTML文件appender-->
    <appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${htmlFileName}</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>${htmlPattern}</pattern>
            </layout>
        </encoder>
    </appender>




    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>



    <!--可拆分归档的appender-->
    <appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <file>${logDir}/roll_logback.log</file>
        <!--指定拆分规则-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--按照时间和压缩格式声明文件名,压缩格式gz-->
            <fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
            <!--按照文件大小进行拆分-->
            <maxFileSize>2KB</maxFileSize>
        </rollingPolicy>
    </appender>
    
    
    
    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
        <appender-ref ref="consoleAppender"/>
        <appender-ref ref="fileAppender"/>
        <appender-ref ref="htmlFileAppender"/>
        <appender-ref ref="rollFileAppender"/>
    </root>

</configuration>

此时在测试中书写一个for循环来进行模拟业务非常多的数据

启动测试:

 

 

查看gz压缩文件

 可以看到日志文件已经进行自动拆分了,当日志文件达到2kb大小时就可以进行正常的拆分

过滤日志等级

还可以通过设置过滤器对日志信息进行等级过滤

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!--    日志文件输出路径-->
    <property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!--    保存的日志文件名-->
    <property name="fileName" value="logback.log"></property>
    <!--文件appender,默认是以追加日志的形式进行输出的-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${fileName}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <property name="htmlFileName" value="logback.html"></property>
    <property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property>
    <!--HTML文件appender-->
    <appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${htmlFileName}</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>${htmlPattern}</pattern>
            </layout>
        </encoder>
    </appender>




    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>



    <!--可拆分归档的appender-->
    <appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <file>${logDir}/roll_logback.log</file>
        <!--指定拆分规则-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--按照时间和压缩格式声明文件名,压缩格式gz-->
            <fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
            <!--按照文件大小进行拆分-->
            <maxFileSize>2KB</maxFileSize>
        </rollingPolicy>
    </appender>


    <!--使用过滤器,进行细粒度控制-->
    <appender name="consoleFilterAppender" class="ch.qos.logback.core.ConsoleAppender">
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <!--高于level中设置的级别,则打印日志-->
            <onMatch>ACCEPT</onMatch>
            <!--低于level中设置的级别,则屏蔽-->
            <onMismatch>DENY</onMismatch>
        </filter>

    </appender>



    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
<!--        <appender-ref ref="consoleAppender"/>-->
<!--        <appender-ref ref="fileAppender"/>-->
<!--        <appender-ref ref="htmlFileAppender"/>-->
<!--        <appender-ref ref="rollFileAppender"/>-->
        <appender-ref ref="consoleFilterAppender"/>
    </root>

</configuration>

启动测试:

可以看到由于过滤器中设置的是过滤出error等级及以上的信息,这里没有比error更高等级的日志信息了,所以只有error等级信息输出

 异步日志

我们将日志appender进行调整回原先的打印appender,然后加入一些测试数据,观察其执行的顺序

 启动测试:

可以看到无论启动多少次,下面的模拟的业务代码1=======这种代码都是在日志信息打印结束后才进行打印,这说明此时的日志是同步执行的

由此得出会出现的问题:
只要是在记录日志,那么系统本身的功能就处于一种停滞的状态当日志记录完毕后,才会执行其他的代码如果日志记录量非常庞大的话,那么我们对于系统本身业务代码的执行效率会非常低
此时可以使用logback提供的异步日志的功能

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

    <!--
        <property name="" value=""></property>
        配置文件通用属性,通过${name}的形式取值
    -->

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!--    日志文件输出路径-->
    <property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!--    保存的日志文件名-->
    <property name="fileName" value="logback.log"></property>
    <!--文件appender,默认是以追加日志的形式进行输出的-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${fileName}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <property name="htmlFileName" value="logback.html"></property>
    <property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property>
    <!--HTML文件appender-->
    <appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender">
        <!--输出文件位置-->
        <file>${logDir}//${htmlFileName}</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>${htmlPattern}</pattern>
            </layout>
        </encoder>
    </appender>




    <!-- 控制台Appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            输出目标的配置,
            System.out:以黑色字体(默认)
            System.err:红色字体
        -->
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>



    <!--可拆分归档的appender-->
    <appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <file>${logDir}/roll_logback.log</file>
        <!--指定拆分规则-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--按照时间和压缩格式声明文件名,压缩格式gz-->
            <fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
            <!--按照文件大小进行拆分-->
            <maxFileSize>2KB</maxFileSize>
        </rollingPolicy>
    </appender>


    <!--使用过滤器,进行细粒度控制-->
    <appender name="consoleFilterAppender" class="ch.qos.logback.core.ConsoleAppender">
        <target>
            System.err
        </target>
        <!-- 日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <!--高于level中设置的级别,则打印日志-->
            <onMatch>ACCEPT</onMatch>
            <!--低于level中设置的级别,则屏蔽-->
            <onMismatch>DENY</onMismatch>
        </filter>

    </appender>
    
<!--    添加异步任务-->
    <appender name="asyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<!--        指定异步任务执行的appender-->
        <appender-ref ref="consoleAppender"/>
    </appender>


    <!--
        日志记录器配置,可以配置多个Appender,进行多方向的日志输出
        root => rootLogger
        level:  表示日志级别
    -->
    <root level="ALL">
        <appender-ref ref="asyncAppender"/>
<!--        <appender-ref ref="consoleAppender"/>-->
<!--        <appender-ref ref="fileAppender"/>-->
<!--        <appender-ref ref="htmlFileAppender"/>-->
<!--        <appender-ref ref="rollFileAppender"/>-->
<!--        <appender-ref ref="consoleFilterAppender"/>-->
    </root>

</configuration>

 启动测试

 此时可以看到业务代码在日志信息中间就执行了,实现了异步任务的功能

自定义logger

在使用中我们还可以使用自定义的logger进行配置

启动测试

 

可以看到只打印了info及以上等级的日志

log4j2 

简介

Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了重大改进,并提供了Logback 中可用的许多改进,同时修复了 Logback 架构中的一些问题。被誉为是目前最优秀的Java日志框架。

特征

Log4j2包含基于LMAX Disruptor 库的下一代异步记录器。在多线程场景中,异步记录器的吞吐量比 Log4j 1.x 和 Logback 高 18 倍,延迟低。

自动重新加载配置

与Logback一样,Log4j2可以在修改时自动重新加载其配置。与 Logback 不同,它会在重新配置发生时不会丢失日志事件。。

高级过滤

与 Logback 一样,Log4j2 支持基于 Log 事件中的上下文数据,标记,正则表达式和其他组件进行过滤。

此外,过滤器还可以与记录器关联。与 Logback 不同,Log4j2 可以在任何这些情况下使用通用的 Filter类。

插件架构

Log4j使用插件模式配置组件。因此,您无需编写代码来创建和配置Appender,Layout,Pattern Converter等。在配置了的情况下,Log4j自动识别插件并使用它们。

无垃圾机制

在稳定日志记录期间,Log4j2 在独立应用程序中是无垃圾的,在 Web 应用程序中是低垃圾。这减少了垃圾收集器的压力,并且可以提供更好的响应性能。目前市面上最主流的日志门面就是 SLF4J,虽然 Log4j2 也是日志门面,因为它的日志实现功能非常强大,性能优越。所以我们一般情况下还是将 Log4j2 看作是日志的实现。SLF4j+ Log4j2 的组合,是市场上最强大的日志功能实现方式,绝对是未来的主流趋势。

案例实现

由于log4j2和前面的logback在很多方面都很相似,这里只简单演示log4j2的主要功能

引入所需依赖

<!--log4j2日志门面-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.0</version>
        </dependency>

        <!--log4j2日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.0</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

启动测试

日志文件拆分

 		<!--slf4j日志门面-->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
        </dependency>


        <!--log4j适配器,因为log4j在slf4j之前就出现了,所以需要引入一个适配器-->
        <!-- 注意这是log4j的适配器,不是log4j2 的适配器,注意版本-->
        <!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
  <!--        <dependency>																-->
  <!--            <groupId>org.slf4j</groupId>						-->
  <!--            <artifactId>slf4j-log4j12</artifactId>	-->
  <!--            <version>1.7.32</version>								-->
  <!--        </dependency>																-->


        <!--log4j2适配器,虽然log4j2自己也有门面实现,但是主流都是使用slf4j的日志门面-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.0</version>
            <scope>test</scope>
        </dependency>

        <!--log4j2日志门面-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.0</version>
        </dependency>

        <!--log4j2日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

添加log4j2.xml文件,书写拆分日志规则

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config"   status="off">

    <Properties>
        <Property name="logDir">D:/javaPro/log/logback/log4j2/log</Property>
        <Property name="fileName">log4j2.log</Property>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n</Property>

        <Property name="rollLogName">roll_log.log</Property>
        <!--
            文件拆分时 存放的位置
            $${date:yyyy-MM-dd} : 根据日期当天,创建一个文件夹,例如:2021-12-26,记录当前的所有日志信息(拆分出来的日志放在这个文件夹中)
            %i:序号 从0开始
         -->
        <Property name="rollFilePattern">$${date:yyyy-MM-dd}//roll_log_%d{yyyy-MM-dd-mm}_%i.log</Property>
    </Properties>

    <Appenders>
        <!-- 控制台appender-->
        <Console name="consoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="${pattern}"/>
        </Console>
        <!-- 文件appender-->
        <File name="fileAppender" fileName="${logDir}//${fileName}">
            <PatternLayout pattern="${pattern}"/>
        </File>

        <!--
            滚动文件appender
按照指定规则来扮日志文件
fileName: 日志文件的名字
filePattern: 日志文件拆分后文件的命名规则
        -->
        <RollingFile name="rollingFileAppender"
                     fileName="${logDir}//${rollLogName}"
                     filePattern="${logDir}//${rollFilePattern}">
            <PatternLayout pattern="${pattern}"/>

            <Policies>
                <!--在系统启动时,触发拆分规则,产生一个日志文件-->
                <OnStartupTriggeringPolicy/>
                <!--按照文件大小拆分,当fileName属性指定的文件超过该大小时,触发拆分事件-->
                <SizeBasedTriggeringPolicy size="10KB"/>
                <!--按照时间节点拆分,拆分规则就是filePattern-->
                <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
            </Policies>
            <!--在同一目录下,文件的个数限制30个,如果超出了设置的规则,则根据时间进行覆盖,新的覆盖旧的-->
            <DefaultRolloverStrategy max="30" />
        </RollingFile>

    </Appenders>

    <!-- 可以配置N多个Logger,包括Root和自定义Logger-->
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="consoleAppender"/>
            <!-- <AppenderRef ref="fileAppender"/> -->
            <AppenderRef ref="rollingFileAppender"/>
        </Root>
    </Loggers>
</Configuration>

模拟日志测试

SpringBoot整合

SpringBoot 是现今市场上最火爆用来简化 spring 开发的框架,springboot 日志也是开发中常用的日志系统。

SpringBoot 默认就是使用SLF4J作为日志门面,Logback作为日志实现来记录日志。

引入所需依赖

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


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

整合logBack实现日志拆分 

新建logback.xml文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L %thread %m%n"></property>
    <property name="logDir" value="D:\\javaPro\\log\\logback\\log4j2\\log\\springbootLog\\logback"></property>

    <!--控制台日志-->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--红色字体打印-->
        <target>
            System.err
        </target>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!--可拆分归档的文件日志-->
    <appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志输出格式-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <!--文件位置-->
        <file>${logDir}//roll_logback.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--按照时间和压缩格式声明文件名,压缩格式gz-->
            <fileNamePattern>${logDir}//roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
            <!-- 按照文件大小拆分,当日志文件达到这个大小时,将该文件以压缩格式归档 -->
            <maxFileSize>1KB</maxFileSize>
        </rollingPolicy>
    </appender>

    <!--自定义logger-->
    <logger name="com.example" level="info" additivity="false">
        <appender-ref ref="consoleAppender"/>
        <appender-ref ref="rollFileAppender"/>
    </logger>

</configuration>

 

启动测试

 

查看指定文件夹下的日志文件是否拆分

 

 整合log4j2实现日志拆分

由于log4j2性能的强大,以及当今市场上越来越多的项目选择使用slf4j+log4j2的组合,springboot默认使用的是slf4j+logback的组合,但我们可以将默认的logback置换为log4j2.

启动器的依赖,间接的依赖logback,所以需要将之前的环境中,logback的依赖去除
 

			
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--排除掉原始日志依赖,达到去除logback依赖的目的-->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency> 
			<!--添加log4j2依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>		

添加log4j2.xml文件

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

<Configuration xmlns="http://logging.apache.org/log4j/2.0/config"   status="off">

    <Properties>
        <Property name="logDir">D:\\javaPro\\log\\logback\\log4j2\\log\\springbootLog\\log4j2</Property>
        <Property name="rollLogName">roll_log.log</Property>
        <Property name="rollFilePattern">$${date:yyyy-MM-dd}//roll_log_%d{yyyy-MM-dd-mm}_%i.log</Property>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n</Property>
    </Properties>

    <Appenders>
        <!-- 控制台appender-->
        <Console name="consoleAppender" target="SYSTEM_ERR">
            <PatternLayout pattern="${pattern}"/>
        </Console>

        <RollingFile name="rollingFileAppender"
                     fileName="${logDir}//${rollLogName}"
                     filePattern="${logDir}//${rollFilePattern}">
            <PatternLayout pattern="${pattern}"/>
            <Policies>
                <OnStartupTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="10KB"/>
                <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
            </Policies>
            <DefaultRolloverStrategy max="30" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="consoleAppender"/>
            <AppenderRef ref="rollingFileAppender"/>
        </Root>
    </Loggers>
</Configuration>

 启动测试

 源码地址

日志源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/569626.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

演示在一台Windows主机上运行两个Mysql服务器(端口号3306 和 3307),安装步骤详解

目录 在一台Windows主机上运行两个Mysql服务器&#xff0c;安装步骤详解因为演示需要两个 MySQL 服务器终端&#xff0c;我只有一个 3306 端口号的 MySQL 服务器&#xff0c;所以需要再创建一个 3307 的。创建一个3307端口号的MySQL服务器1、复制 mysql 的安装目录2、修改my.in…

通过Bedrock Access Gateway解决方案快速访问Amazon Bedrock的多种大语言模型

Bedrock Access Gateway&#xff08;BAG&#xff09;解决方案提供了开箱即用、兼容 OpenAI 的代理功能&#xff0c;帮助用户轻松无缝地从 OpenAI 迁移到 Amazon Bedrock。 1. 概述 亚马逊云科技的 Amazon Bedrock 服务支持一系列领先的基础模型&#xff0c;为客户提供多种选择…

SpringCloud Alibaba--nacos简介和注册中心和登录

目录 一.理论基础 二.nacos 2.1 简介 2.2 安装 三.父项目 三.生产者 3.1 配置依赖 3.2 配置文件 3.3 启动类 3.4 控制类 四.消费者 4.1 配置依赖 4.2 配置文件 4.3 启动类 4.4 feign的接口 五.效果 六.负载均衡--权重算法 6.1重启nacos 6.2 设置权重 6.3 设…

【1431】java学习网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 学习网站系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

【Django】django.core.exceptions.AppRegistryNotReady: Apps aren‘t loaded yet.

其中django后台manage.py入口程序报错&#xff0c;检索很多问题解决方案&#xff0c;这里记录下个人问题原因 1.django启动异常问题详情 django.core.exceptions.AppRegistryNotReady: Apps aren’t loaded yet. 2.问题原因 Python第三方包安装版本不一致或缺少依赖包&…

利用AI知识库,优化医保系统售后信息管理流程

在医疗行业中&#xff0c;传统知识库管理虽能整合医疗行业知识&#xff0c;但搜索和管理效率有限&#xff0c;导致医护人员难以高效利用。特别是面对医保系统等复杂系统时&#xff0c;他们常需依赖人工客服或繁琐的电子产品手册解决问题。而HelpLook AI知识库利用AI技术&#x…

拼多多面试题——力扣版测试用例纠错

最近我看到力扣上这个题目&#xff0c;用了三种方法&#xff0c;结果没有一种正确&#xff0c;我就纳闷儿了&#xff0c;为何总有一个测试用例过不了&#xff0c;结果我发现这个测试用例确实有问题啊。。。。。 题目&#xff1a; 表&#xff1a;Logs ----------------------…

Anon Network:基于 Ator Protocol 的 DePIN 匿名互联网

Anon Network正在以Ator Protocol为基础构建世界上最大的Web3隐私互联网生态&#xff0c;其旨在基于DePIN网络&#xff08;Ator protocol&#xff09;&#xff0c;通过激励体系构建一个自下而上、自我维持且可持续、不依赖于任何三方实体且完全匿名的完备互联体系。在该体系中&…

在html页面中使用Vue3和Element-Plus实现基金成本计算器

背景 周边朋友都说基金亏麻了&#xff0c;有些 “鸡” 到底部了&#xff0c;想要补个仓&#xff0c;但是又不知道要投入多少才能拉低到心里预期的成本&#xff0c;并且每只 “鸡” 都得自己输入计算&#xff0c;很麻烦&#xff0c;所以本着偷懒的原则&#xff0c;做了下面的这个…

机器学习中常见的数据分析,处理方式(以泰坦尼克号为例)

数据分析 读取数据查看数据各个参数信息查看有无空值如何填充空值一些特殊字段如何处理读取数据查看数据中的参数信息实操具体问题具体分析年龄问题 重新划分数据集如何删除含有空白值的行根据条件删除一些行查看特征和标签的相关性 读取数据 查看数据各个参数信息 查看有无空…

【Linux】实现一个进度条

我们之前也学了gcc/vim/make和makefile&#xff0c;那么我们就用它们实现一个进度条。 在实现这个进度条之前&#xff0c;我们要先简单了解一下缓冲区和回车和换行的区别 缓冲区其实就是一块内存空间&#xff0c;我们先看这样一段代码 它的现象是先立马打印&#xff0c;三秒后程…

Java Instrumentation插桩技术

Instrumentation基础 openrasp中用到了Instrumentation技术&#xff0c;它的最大作用&#xff0c;就是类的动态改变和操作。 使用Instrumentation实际上也可以可以开发一个代理来监视jvm的上运行的程序&#xff0c;可以动态的替换类的定义&#xff0c;就可以达到虚拟机级别的…

QA测试开发工程师面试题满分问答20: 软件的安全性应从哪几个方面去测试?

软件的安全性测试应从多个方面进行&#xff0c;并确保覆盖以下关键方面&#xff1a; 当回答问题时&#xff0c;可以根据自己的经验和知识&#xff0c;从上述要点中选择适合的方面进行详细说明。强调测试的综合性、全面性和持续性&#xff0c;并强调测试的重要性以及如何与开发团…

亚信安全深度参与撰写《金融行业云原生安全体系研究报告》引领云原生安全 !

近日&#xff0c;北京金融科技产业联盟正式发布《金融行业云原生安全体系研究报告》&#xff08;以下简称《报告》&#xff09;。报告由中国银联等单位牵头&#xff0c;亚信安全受邀作为联合牵头单位全程参与《报告》的讨论和撰写工作。亚信安全依托突出的云原生安全实践经验以…

windows安装nssm并将jar打包为服务

一、nssm 下载地址 二、安装nssm服务 将下载的压缩包复制到安装目录进行解压&#xff0c;解压后有两个版本 win32 和 win64&#xff0c;根据系统选择。打开系统 powershell 命令窗口&#xff0c;进入安装目录指定版本目录&#xff0c;就可以使用nssm服务了。 # 安装服务&…

揭开ChatGPT面纱(2):OpenAI主类源码概览

文章目录 〇、使用OpenAI的两个步骤一、初始化方法__init__()1.源码2.参数解析 二、提供的接口1.源码2.接口说明主要接口说明 OpenAI版本1.6.1 〇、使用OpenAI的两个步骤 在上一篇博客中&#xff0c;我实现并运行了一个OpenAI的demo&#xff0c;我们可以发现&#xff0c;想要使…

自定义mybatis插件实现读写分离

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 自定义mybatis插件实现读写分离 前言场景分析前置配置讲解数据源切换实现代码实现(插件)说明 注意实现效果 有时候我更想看到的是bug&#xff0c;比如做这个插件的时候 前言 在数据库的世界里&#x…

力扣HOT100 - 230. 二叉搜索树中第K小的元素

解题思路&#xff1a; class Solution {List<Integer> list new ArrayList<>();public int kthSmallest(TreeNode root, int k) {dfs(root);return list.get(k - 1);}public void dfs(TreeNode root) {if (root null) return;dfs(root.left);list.add(root.val)…

一个联合均值与方差模型的R包——dglm

目录 一、引言二、包的安装与载入三、模拟例子3.1 数据生成3.2 数据查看3.3 模型估计参数 一、引言 在 R 语言中&#xff0c;dglm 包是用于拟合双参数广义线性模型&#xff08;Double Generalized Linear Models&#xff0c;简称 DGLMs&#xff09;的一个工具。这类模型允许同…

使用STM32F103驱动读取MAX30102时的调试问题记录

1、数据FIFO寄存器&#xff0c;也就是地址为0x07的FIFO DATA寄存器&#xff0c;必须一次性将采样数据全部读出&#xff0c;也就是IIC起始信号发出后&#xff0c;必须连续读取FIFO中所有数据&#xff0c;如果一个字节一个字节读的话&#xff0c;实测FIFO的读写指针不会变化&…