学习日志管理的时候,网上查找了很多的博客,但是大多数说的都不是我想搞懂的东西,最后我找了B站尚硅谷雷神的视频看的。就比较完整且系统的了解了一下。如果需要可以自行去B站搜索springboot教程1的。

看完之后,我还是去找了别的博客看了,才终于搞懂搞明白了。在这做一个记录

正文开始

导包

我们使用的logback不需要特定的包,springboot已经帮我们自动依赖了 只需要导入web包,和一个lombok包

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

导入配置

需要在我们的classpath下新建一个文件,名字:logback-spring.xml,或者logback.xml,推荐使用第一个logback-spring.xml,原因请看雷神视频。

配置内容如下重点:

<?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="./logs" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="[自己定义名字]"></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.fang" level="warn" />
    <!-- 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>

里面有很多的注释,基本看了就懂 但是有几个还是要说明一下:

1、前面两个配置目录和日志名字的:目录可以指定绝对路径,也可以写相对目录,比如我上面的写法就表示在当前项目的根目录下的logs目录下,名字自己定义

2、中间那个appender 名字为name="stdout"的基本可以不需要动,除非你要自己过滤一下级别的信息。下面讲。

3、第二个appender 名字为name="appLogAppender"的是表示输出到文件的。每次滚动的时长和每个文件的大小自己定义,我上面定义了一年,也就是我的日志文件会保留过去一年以内的日志。每个日志大小maxFileSize我一般设置在10M,而每天的日志是会自动区分的,而且会按照日期命名保存。

4、logger标签,用来设置某一个包或者具体的某一个类的日志打印级别,这里可以规定一些更细的记录,比如springframework的包打印info级别的日志。然后我自己写的包fang,只打印WARN级别以上的日志。

name:用来指定受此loger约束的某一个包或者具体的某一个类。 level:用来设置打印级别(日志级别),大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。 addtivity:是否向上级loger传递打印信息。默认是true。

5、最后的root标签。上面有多少个appender,标签中就得写多少个。root的llevel属性,就是定义打印日志的等级。等级在注释中有。

如果没有别的高级需求,以上的配置就可以直接用了

使用如下:

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Bernie_xin
 * @create 2021/1/8 20:01
 **/
@RestController
@RequestMapping("/mytest")
@Slf4j
public class TestController {

    @GetMapping("/test")
    public String test(){
        log.trace("登录认证异常-------------->{}", "trace");
        log.debug("登录认证异常-------------->{}", "debug");
        log.info("登录认证异常-------------->{}", "info");
        log.warn("登录认证异常-------------->{}", "warn");
        log.error("登录认证异常-------------->{}", "error");
        return "成功";
    }
}

尝试看看你配置的级别还能打印吗

在控制台输出info级别,在文件输出WARN级别

找了这位老哥的博客 http://www.manongjc.com/detail/6-tazecgsjdageavt.html 在文件输错的标签下加入

<filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印INFO及其以上的日志 -->
	<!-- 在日志配置级别的基础上过滤掉WARN级别以下的日志 -->
	<level>WARN</level>
</filter>

2021-11-16新修改添加过滤配置 完整配置如下:在控制台打印debug及其以上的级别,在日志文件打印info及其以上的级别

<?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="./logs" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="[自己定义名字]"></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>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印INFO及其以上的日志 -->
            <!-- 在日志配置级别的基础上过滤掉WARN级别以下的日志 -->
            <level>TRACE</level>
        </filter>
    </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>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印INFO及其以上的日志 -->
            <!-- 在日志配置级别的基础上过滤掉WARN级别以下的日志 -->
            <level>INFO</level>
        </filter>
    </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.fang" level="warn" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>



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

效果:

springboot3 logback不打日志_spring boot

springboot3 logback不打日志_spring_02

还有一些高级的玩法,比如级别info的输入到一个文件,级别ERROR输出到另一个文件等,等我后面学写了再写博客吧。

2021-11-16更新

高级玩法来了

需求:控制台输出debug及其以上的日志,文件输入info及其以上的日志,error日志再单独输出到另一个文件

参考:,

个人整合的配置如下:可以直接复制使用,简单改一个名字就好

出了个小插曲,error的滚动策略写%i就报错,就算是复制上面的都不行,一直提示去掉他。我尝试了很多次,最后无奈只能去掉。

<?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="./logs" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="test"></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>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印INFO及其以上的日志 -->
            <!-- 在日志配置级别的基础上过滤掉WARN级别以下的日志 -->
            <level>TRACE</level>
        </filter>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印INFO及其以上的日志 -->
            <!-- 在日志配置级别的基础上过滤掉WARN级别以下的日志 -->
            <level>INFO</level>
        </filter>
        <!--只输出INFO-->
<!--        <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--            <!–过滤 INFO–>-->
<!--            <level>INFO</level>-->
<!--            <!–匹配到就禁止–>-->
<!--            <onMatch>ACCEPT</onMatch>-->
<!--            <!–没有匹配到就允许–>-->
<!--            <onMismatch>DENY</onMismatch>-->
<!--        </filter>-->
        <!--
        当发生滚动时,决定 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>

    <!-- error日志 -->
    <appender name="appErrorLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤日志,只输出error -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>

        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </encoder>
        <!-- 滚动策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-error.log</fileNamePattern>
        </rollingPolicy>
    </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.fang" level="warn" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>

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

</configuration>

效果:

springboot3 logback不打日志_java_03

springboot3 logback不打日志_java_04

springboot3 logback不打日志_java_05

看完博客别忘了点个赞。

2021-12-08最后一更 参考 配置又全又详细

<?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="./logs" />
    <!-- 定义日志文件名称 -->
    <property name="debug" value="manager-codekiller-debug"></property>
    <property name="info" value="manager-codekiller-info"></property>
    <property name="error" value="manager-codekiller-error"></property>
    <property name="warn" value="manager-codekiller-warn"></property>
    <property name="job" value="manager-codekiller-job"></property>
    <property name="fileName" value="logback"></property>


    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
			%d表示日期时间,
			%thread表示线程名,
			%-5level:级别从左显示5个字符宽度
			%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
			%msg:日志消息,
			%n是换行符
			%-15.15():如果记录的线程字符长度小于15(第一个)则用空格在右侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符
			%-50.50():如果记录的logger字符长度小于50(第一个)则用空格在右侧补齐,如果字符长度大于50(第二个),则从开头开始截断多余的字符
			%highlight():颜色,info为蓝色,warn为浅红,error为加粗红,debug为黑色
			%boldMagenta:粗红
			%magenta:洋红
			$cyan:青色
			%white:白色
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <springProfile name="dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n</pattern>
            </springProfile>
        </layout>
    </appender>

    <!--控制台打印警告信息的单独处理-->
    <appender name="consoleWarn" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <springProfile name="dev">
                <pattern>%magenta(%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n)</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%magenta(%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n)</pattern>
            </springProfile>
        </layout>
    </appender>

    <!--控制台打印错误信息的单独处理-->
    <appender name="consoleError" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <springProfile name="dev">
                <pattern>%boldMagenta(%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n)</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%boldMagenta(%d{yyyy-MM-dd HH:mm:ss.SSS}  %highlight(%-5level) %magenta([%-15.15(%thread)])  %cyan( %-50.50(%logger{50} )) : %msg%n)</pattern>
            </springProfile>
        </layout>
    </appender>

    <!--debug日志存储-->
    <appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${debug}/${fileName}.log</file>

        <!--过滤,只存储DEBUG级别的日志-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--
       当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
       TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
       -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
                滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
                %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${debug}/${fileName}-%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}  %-5level  [%-15.15(%thread)]  %-50.50(%logger{50}) :  %msg%n</pattern>
        </layout>
    </appender>

    <!--info日志存储-->
    <appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${info}/${fileName}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/${info}/${fileName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <MaxHistory>365</MaxHistory>
            <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}  %-5level  [%-15.15(%thread)]  %-50.50(%logger{50}) :  %msg%n</pattern>
        </layout>
    </appender>

    <!--warn日志存储-->
    <appender name="warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${warn}/${fileName}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/${warn}/${fileName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <MaxHistory>365</MaxHistory>
            <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}  %-5level  [%-15.15(%thread)]  %-50.50(%logger{50}) :  %msg%n</pattern>
        </layout>
    </appender>

    <!--error日志存储-->
    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${error}/${fileName}.log</file>
        <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_HOME}/${error}/${fileName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <MaxHistory>365</MaxHistory>
            <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}  %-5level  [%-15.15(%thread)]  %-50.50(%logger{50}) :  %msg%n</pattern>
        </layout>
    </appender>

<!--    <!–job日志存储–>-->
<!--    <appender name="job" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <!– 指定日志文件的名称 –>-->
<!--        <file>${LOG_HOME}/${job}/${fileName}.log</file>-->

<!--        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
<!--            <fileNamePattern>${LOG_HOME}/${job}/${fileName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>-->

<!--            <MaxHistory>365</MaxHistory>-->

<!--            <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}  %-5level  [%-15.15(%thread)]  %-50.50(%logger{50}) :  %msg%n</pattern>-->
<!--        </layout>-->
<!--    </appender>-->

    <!--job包的单独输出-->
<!--    <logger name="top.codekiller.manager.examination.job"  level="debug"   additivity="false">-->
<!--        <appender-ref ref="job"></appender-ref>-->
<!--        <appender-ref ref="console"></appender-ref>-->
<!--    </logger>-->

    <!--
		logger主要用于存放日志对象,也可以定义日志类型、级别,并且会先执行。
		name:表示匹配的logger类型前缀,也就是包的前半部分
		level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
		additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,即是否将信息提交给root
        false:表示只用当前logger的appender-ref,
        true:表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->

    <!--mapper包的单独输出(输出sql信息,至关重要)-->
    <logger name="mapper"  level="debug"   additivity="false">
        <appender-ref ref="console"></appender-ref>
    </logger>

    <!--debug的单独输出-->
    <logger name="log-debug"  level="debug"   additivity="false">
        <appender-ref ref="console"/>
        <appender-ref ref="debug" />
    </logger>

    <!--warn的单独输出-->
    <logger name="log-warn"  level="warn"   additivity="false">
        <appender-ref ref="consoleWarn"/>
        <appender-ref ref="warn" />
    </logger>


    <!--error的单独输出-->
    <logger name="log-error"  level="error"   additivity="false">
        <appender-ref ref="consoleError"/>
        <appender-ref ref="error"/>
    </logger>

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

</configuration>