关于Java中常用的日志框架的详细介绍:Java常用日志框架介绍

一、Log日志概述

1.1、Log能干什么

日志能干的事情很多,对于学习程序,测试的工程师来说,日志能够定位问题,解决问题,是最大的功能点。

  • 记录一切:日志帮助我们记录程序功能都干了什么,无论是正常的输入输出还是出现异常,都可以用日志记录
  • 定位问题:日志可以帮助程序员调试问题,帮助测试人员定位问题
  • 记录分析用户行为:统计分析师用来记录用户的一起行为,用于分析用户的习惯和商业价值
  • 备份和还原实时数据:数据库工程师用来作为一种特殊的数据库

image.png

1.2、日志的级别 Log Level

日志级别是对日志记录信息的轻重缓急的划分。通常从轻到重划分为:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR

通常当我们指定日志级别为 INFO 级别,那么 TRACE、DEBUG 级别的日志就不会被输出打印,同理如果指定日志级别为 ERROR,那么其他类型的日志将不会被打印

1.3、日志的输出

通常日志以文本流的形式存储在磁盘,也可以把日志存储在关系型数据库中或 No Sql 中

  • 文本
  • 关系型数据库
  • No Sql
  • Console 控制台

一般日志组件都可以自定义输出格式。

1.4、Spring Boot 日志组件 Log Plugin

当然自己开发日志组件也是可以的,实际上也不是很难,在一些特殊场景,很多公司都是用自己开发的日志组件,但是对于大多数应用来说,我们使用标准的日志组件就可以解决我们的问题。
Spring Boot 日志组件最为常见的包括了

  • Logback
  • log4j
  • log4j2
  • slf4j
  • JUL

大家请先简单看下这篇英文的官方文档:SpringBoot Logging官方文档
image.png
文中有说 SpringBoot 内部日志系统使用的是 Commons Logging 并且 SpringBootJDKLogging , Log4j2(Log4j也是支持的) , Logback 都提供了默认配置,并且如果使用了 Starters ,那么默认使用 Logback 。那么什么是这个这个 Starters 呢?大家请看我的pom文件:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.projectlombok</groupId>
  12. <artifactId>lombok</artifactId>
  13. <version>1.16.18</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>com.alibaba</groupId>
  17. <artifactId>fastjson</artifactId>
  18. <version>1.2.40</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. <scope>test</scope>
  24. </dependency>
  25. </dependencies>

简单的说,只要你的 pom 文件中使用了 spring-boot-starter 就代表着你使用了 SpringBootStarters 。相信各位玩 SpringBoot 的朋友肯定是看到了自己的 pom 文件中有这个了,因为,Starters(启动器)SpringBoot 最核心的部件之一,没有了启动器, SpringBoot 就几乎废掉了。

二、SpringBoot使用

SpringBoot 招人喜欢的一大特点就是配置方便,配置日志的相关参数也只需要写在 application.properties 中就可以了,当然,这仅仅是基本的配置,如果需要高级的配置,还是需要添加依赖所选择日志系统的配置文件

SpringBoot支持的日志级别
官方文档中有提到, SpringBootLogging 配置的级别有7个:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • OFF

image.png

2.1、控制台输出(默认)

SpringBoot的默认日志输出到控制台,默认日志级别为 INFO ,可通过:logging.level.root 设置日志级别,
application.properties配置:

# 控制彩色中断输出
spring.output.ansi.enabled=ALWAYS

# springboot 日志等级配置,输出到控制台,默认为:INFO
logging.level.root=info
# 设置控制台日志输出格式(设置了格式,彩色输出会不起作用)
logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n

示例:
ConsoleLoggerController.java
image.png

2.2、文件输出

官方文档如下:
image.png
文档中对 SpringBoot 日志的文件输出有明确的说明,上面说到:
在默认情况下,SpringBoot仅仅在控制台打印log信息的,如果我们需要将log信息记录到文件,那么就需要在 application.properties 中配置 logging.file 或者 logging.path注意啊,是或者,不是并且!
而且官方文档有明确说明,配置 logging.file 的话是可以定位到自定义的文件的,使用 logging.path 的话,日志文件将使用 spring.log 来命名。
而且日志文件会在10Mb大小的时候被截断,产生新的日志文件,默认级别为:ERROR、WARN、INFO

application.properties配置

# SpringBoot默认日志文件输出
logging.file=./logs/default.log
# 设置文件日志输出格式
logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n

示例:
FileLoggerController.java
image.png

注意:设置了文件输出后,控制台同时也会输出

2.3、自定义日志配置( 一般用于生产环境 )

生产环境中,日志往往要以文件形式存放到本地,并且根据日志级别或者业务区分,输出到不同的文件中;
因为SpringBoot默认的控制台输出、文件输出,都会将所有日志输出到一个文件或者控制台中,而生产环境,会根据不同的日志级别或者业务输出到不同的日志文件中;

官方文档:Custom Log Configuration
image.png

使用Logback的指定配置文件实现更高级的日志配置

如果我们的确要使用 Logback 的指定配置文件的话,那么说明 application.properties 中的配置功能已经不满足我们需求了,所以 application.properties 中关于日志记录的可以不要了,因为我们启用了 Logback 自己的配置文件,启用的方式很简单,在 classpathresources 下新建 logback.xml 文件。这样就可以了。 使用了自定义日志配置方式的话,原有的 application.properties 中的配置就失效了,控制台不再输出日志;如果需要继续输出,那么需要在 logback.xml 中显示声明 ,如下:
具体配置和说明这里有个简单的介绍:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 引入配置文件,在xml可用 ${变量名} 获取value -->
    <!-- <property file="${user.dir}/config/config.properties"/>-->

    <!-- 控制台日志 -->
    <appender name="stdout-appender" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </layout>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="logback-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>./logs/logback_%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>100</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="logback-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <!-- <queueSize>${log.async.queue:-200000}</queueSize>-->
        <queueSize>200000</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="logback-appender"/>
    </appender>

    <!-- 文件保存日志的相关配置 -->
    <appender name="bus-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 保存日志文件的路径 -->
        <file>./logs/log-bus.log</file>
        <!-- 日志格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
        </encoder>
        <!-- 日志级别过滤器 -->
        <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-bus.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 最大保存时间:30天-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <appender name="bi-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 保存日志文件的路径 -->
        <file>./logs/log-bi.log</file>
        <!-- 日志格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
        </encoder>
        <!-- 日志级别过滤器 -->
        <!--                <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
        <!--                    &lt;!&ndash; 过滤的级别 &ndash;&gt;-->
        <!--                    <level>ERROR</level>-->
        <!--                    &lt;!&ndash; 匹配时的操作:接收(记录) &ndash;&gt;-->
        <!--                    <onMatch>ACCEPT</onMatch>-->
        <!--                    &lt;!&ndash; 不匹配时的操作:拒绝(不记录) &ndash;&gt;-->
        <!--                    <onMismatch>DENY</onMismatch>-->
        <!--                </filter>-->
        <!-- 循环政策:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>log-bi.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 最大保存时间:30天-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- 指定 Logger loggerBus = LoggerFactory.getLogger("log-bus"); 文件输出 -->
    <!-- 基于dubug处理日志:具体控制台或者文件对日志级别的处理还要看所在appender配置的filter,如果没有配置filter,则使用root配置 -->
    <logger name="log-bus" level="info">
        <appender-ref ref="bus-appender"/>
    </logger>

    <logger name="log-bi" level="info">
        <appender-ref ref="bi-appender"/>
    </logger>

    <!-- 控制root日志输出: springboot 控制台、文件日志输出 -->
    <root level="${logback-log-level:-info}">
        <appender-ref ref="stdout-appender"/>
        <appender-ref ref="logback-async-appender"/>
    </root>
</configuration>

示例:
CustomerLoggerController.java
image.png
image.png

三、拓展

3.1、logback详细配置

可参考:logback 配置

3.2、公用日志框架封装

一般来说,公用的日志框架引入就行了,不需要每个开发人员都配置,因此封装为一个jar包,例如:
logback.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <!--配置项-->
    <property file="${user.dir}/config/config.properties"/>

    <!-- 控制台日志 -->
    <appender name="stdout-appender" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </layout>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="logback-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${log.dir}/logback_%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>100</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="logback-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="logback-appender"/>
    </appender>

    <appender name="redis-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/redis-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="redis-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="redis-appender"/>
    </appender>

    <appender name="gcf-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/gcf-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="gcf-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="gcf-appender"/>
    </appender>

    <appender name="all-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/all-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="all-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="all-appender"/>
    </appender>

    <!-- SCP-SDK相关输出 -->
    <appender name="scp-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir}/scp-%d{yyyyMMdd}-%i.log
            </fileNamePattern>
            <maxHistory>1</maxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="scp-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="scp-appender"/>
    </appender>

    <appender name="rp-bi-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-bi-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-bi-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-bi-appender"/>
    </appender>

    <appender name="rp-default-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%thread|%d{yyyy-MM-dd HH:mm:ss.SSS}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-default-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <!--  异步输出,异步的log片段必须在同步段后面,否则不起作用  -->
    <appender name="rp-default-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-default-appender"/>
    </appender>

    <appender name="rp-command-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-command-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-command-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-command-appender"/>
    </appender>

    <appender name="rp-message-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-message-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-message-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-message-appender"/>
    </appender>

    <appender name="rp-broadcasting-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-broadcasting-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-broadcasting-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-broadcasting-appender"/>
    </appender>

    <appender name="rp-logout-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-logout-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-logout-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-logout-appender"/>
    </appender>

    <appender name="rp-login-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-login-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-login-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-login-appender"/>
    </appender>

    <appender name="rp-exception-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-exception-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-exception-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-exception-appender"/>
    </appender>

    <appender name="rp-slow-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<Encoding>UTF-8</Encoding>-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss}|%msg%n</pattern>
        </layout>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.dir}/rp-slow-%d{yyyyMMdd}-%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <appender name="rp-slow-async-appender" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为200000 -->
        <queueSize>${log.async.queue:-200000}</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="rp-slow-appender"/>
    </appender>

    <!--*****************************************LOGGER***********************************-->

    <logger name="rp-slow" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-slow-async-appender"/>
    </logger>

    <logger name="com.jedis" additivity="false">
        <level value="info"/>
        <appender-ref ref="redis-async-appender"/>
    </logger>

    <logger name="org.summercool.hsf" additivity="false">
        <level value="info"/>
        <appender-ref ref="gcf-async-appender"/>
    </logger>

    <logger name="com.wells" additivity="false">
        <level value="info"/>
        <appender-ref ref="all-async-appender"/>
    </logger>

    <logger name="com.platform.scp.sdk" additivity="false">
        <level value="INFO"/>
        <appender-ref ref="scp-async-appender"/>
    </logger>

    <logger name="rp-bi" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-bi-async-appender"/>
    </logger>

    <logger name="rp-default" additivity="false">
        <level value="${default-log-level:-info}"/>
        <appender-ref ref="rp-default-async-appender"/>
    </logger>

    <logger name="rp-command" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-command-async-appender"/>
    </logger>

    <logger name="rp-message" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-message-async-appender"/>
    </logger>

    <logger name="rp-broadcasting" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-broadcasting-async-appender"/>
    </logger>

    <logger name="rp-logout" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-logout-async-appender"/>
    </logger>
    <logger name="rp-login" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-login-async-appender"/>
    </logger>

    <logger name="rp-exception" additivity="false">
        <level value="info"/>
        <appender-ref ref="rp-exception-async-appender"/>
    </logger>

    <root level="${logback-log-level:-info}">
        <appender-ref ref="stdout-appender"/>
        <appender-ref ref="logback-async-appender"/>
    </root>
</included>

LogUtil配置:

package com.wells.rp.base.log;

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

public abstract class Log0 {

    static {
        LoggerContext.getInstance().init();
    }

    protected static final Logger logger = LoggerFactory.getLogger("rp-default");

    protected static final Logger bilogger = LoggerFactory.getLogger("rp-bi");

    protected static final Logger login = LoggerFactory.getLogger("rp-login");

    protected static final Logger logout = LoggerFactory.getLogger("rp-logout");

    protected static final Logger message = LoggerFactory.getLogger("rp-message");
    // Adapter 指令日志
    protected static final Logger command = LoggerFactory.getLogger("rp-command");
    // 广播日志
    protected static final Logger broadcasting = LoggerFactory.getLogger("rp-broadcasting");
    //增加exception日志
    protected static final Logger exception = LoggerFactory.getLogger("rp-exception");
    //增加slow日志
    protected static final Logger slow = LoggerFactory.getLogger("rp-slow");

    /*****************************************************************************************/
    // 提供新接口
    // 主要 提供占位符方式.避免 字符串 消耗额外CPU.
    public static void debug(String format, Object... arguments) {
        logger.debug(format, arguments);
    }
}

此处封装不支持占位符,可以增加占位符的输出

package com.wells.rp.base.log;

import java.io.PrintWriter;
import java.io.StringWriter;

public class Log extends Log0 {

    public static void error(Throwable e) {
        logger.error("",e);
    }

    public static void error(String msg) {
        logger.error(msg);
    }

    public static void error(String string, Exception e) {
        logger.error(string, e);
    }

    public static void warn(Throwable e) {
        logger.warn("",e);
    }

    public static void warn(String msg) {
        logger.warn(msg);
    }

    public static void warn(String string, Exception e) {
        logger.warn(string, e);
    }

    public static void info(String msg) {
        logger.info(msg);
    }

    @Deprecated
    public static void debug(String msg) {
        logger.debug(msg);
    }

    public static void bi(String msg) {
        bilogger.info(msg);
    }

    public static void login(String msg) {
        login.info(msg);
    }

    public static void logout(String msg) {
        logout.info(msg);
    }

    public static void message(String msg) {
        message.info(msg);
    }

    public static void command(String msg) {
        command.info(msg);
    }

    public static void broadcasting(String msg) {
        broadcasting.info(msg);
    }

    public static void exception(String msg) {
        exception.info(msg);
    }

    public static void slow(String msg) {
        slow.info(msg);
    }

    public static boolean errorEnable() {
        return logger.isErrorEnabled();
    }

    public static boolean warnEnable() {
        return logger.isWarnEnabled();
    }

    public static boolean infoEnable() {
        return logger.isInfoEnabled();
    }

    public static boolean debugEnable() {
        return logger.isDebugEnabled();
    }

    public static String getStackTrace(Throwable exception) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            exception.printStackTrace(pw);
            return sw.toString();
        } finally {
            if (pw != null) {
                pw.close();
            }
        }
    }
}

调用:

Log.bi("test logger");

3.3、指定Controller、Service、package日志输出

主要配置在 中的name,可以指定单个 Controller的路径、Service的路径、package的路径

<appender name="bi-appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <!-- 保存日志文件的路径 -->
  <file>./logs/log-bi.log</file>
  <!-- 日志格式 -->
  <encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
  </encoder>

  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <!-- 日志文件名格式 -->
    <fileNamePattern>log-bi.%d{yyyy-MM-dd}.log</fileNamePattern>
    <!-- 最大保存时间:30天-->
    <maxHistory>30</maxHistory>
  </rollingPolicy>
</appender>

<!-- 主要配置在这里 -->
<logger name="可指定多种类型" level="info">
  <appender-ref ref="bi-appender"/>
</logger>

3.4、JMX配置器

JMXConfigurator 允许通过 JMX 来配置 logback。简单来说就是,它允许你从默认配置文件,指定的文件或者 URL 重新配置 logback,列出 logger 以及修改 logger 级别。
image.png

参考

官网:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-logging