当你使用Spring Boot进行应用程序开发时,良好的日志配置是至关重要的。在Spring Boot中,Logback是一种常用的日志框架,它提供了灵活性和性能优势。在本文中,我们将探讨如何配置Logback日志框架来记录和管理应用程序的日志。
Log4j和Logback都是Java中常用的日志框架,它们有一些共同的历史渊源,但也有一些区别。
-
性能: Logback在性能上相对于Log4j有一些改进。它采用异步日志处理方式,可以提供更高的吞吐量,特别是在高负载环境下。这使得Logback在某些场景下比Log4j更为高效。
-
配置: Logback的配置文件(logback.xml)相对于Log4j的配置更加简洁和灵活。它引入了更直观的配置语法,同时提供了更多的选项和特性,如条件判断、多环境配置等。
-
内建Appender: Logback内建了一些Appender,如SMTPAppender、SocketAppender等,而Log4j可能需要额外的插件或配置。
-
Rolling File Appender: Logback的RollingFileAppender比Log4j的FileAppender更强大,提供了更灵活的日志文件滚动和归档策略。
-
开发活跃度: 随着时间的推移,Logback在一些方面成为了更现代和活跃的选择。它在不断更新和改进,而Log4j一度因为长时间没有更新而有一些停滞的感觉。然而,这方面的状况可能会随时间而变化。
一、添加依赖
在实际开发中,我们可以直接引入spring-boot-starter-web
依赖来简化项目配置。这是因为spring-boot-starter-web
包含了spring-boot-starter
,而后者又包含了spring-boot-starter-logging
。因此,通过引入spring-boot-starter-web
,我们就能够满足对Web应用所需的全部依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
二、logback-spring.xml详解
Spring Boot 官方建议在配置日志时,首选使用带有"-spring"后缀的文件名,例如使用 "logback-spring.xml" 而不是 "logback.xml"。你可以将这个 XML 文件放置在项目的 "src/main/resources" 目录下。
如果愿意使用自定义的文件名,比如 "logback-config.xml",只需在 "application.properties" 文件中添加以下配置即可:
logging.config=classpath:logback-config.xml
三、配置参考
logback-spring.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 从application.yml 中注入变量 -->
<springProperty scope="context" name="LOG_PATH" source="log.home.path" defaultValue="logs"/>
<springProperty scope="context" name="APP_DIR" source="spring.application.name" defaultValue="graceLogs"/>
<springProperty scope="context" name="ROLL_MAXHISTORY" source="log.home.maxHistory" defaultValue="30"/>
<springProperty scope="context" name="ROLL_TOTALSIZECAP" source="log.home.totalSizeCap" defaultValue="20GB"/>
<springProperty scope="context" name="ROLL_MAXFILESIZE" source="log.home.maxFileSize" defaultValue="10MB"/>
<property name="log.dir" value="${LOG_PATH}" />
<property name="app.dir" value="${APP_DIR}"/>
<property name="log.maxHistory" value="${ROLL_MAXHISTORY}"/>
<property name="log.totalSizeCap" value="${ROLL_TOTALSIZECAP}"/>
<property name="log.maxFileSize" value="${ROLL_MAXFILESIZE}"/>
<!-- appender是configuration的子节点,是负责写日志的组件。 -->
<!-- ConsoleAppender:把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 默认情况下,每个日志事件都会立即刷新到基础输出流。 这种默认方法更安全,因为如果应用程序在没有正确关闭appender的情况下退出,则日志事件不会丢失。
但是,为了显着增加日志记录吞吐量,您可能希望将immediateFlush属性设置为false -->
<!--<immediateFlush>true</immediateFlush>-->
<encoder>
<!-- %37():如果字符没有37个字符长度,则左侧用空格补齐 -->
<!-- %-37():如果字符没有37个字符长度,则右侧用空格补齐 -->
<!-- %15.15():如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符 -->
<!-- %-40.40():如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符 -->
<!-- %msg:日志打印详情 -->
<!-- %n:换行符 -->
<!-- %highlight():转换说明符以粗体红色显示其级别为ERROR的事件,红色为WARN,BLUE为INFO,以及其他级别的默认颜色。 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n
</pattern>
<!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- info 日志-->
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是log_info.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名-->
<appender name="info_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>${log.dir}/${app.dir}/log_info.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch><!-- 如果命中ERROR就禁止这条日志 -->
<onMismatch>ACCEPT</onMismatch><!-- 如果没有命中就使用这条规则 -->
</filter>
<!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件,即RollingPolicy:负责执行翻转所需的操作。
RollingFileAppender的第二个子组件,即TriggeringPolicy:将确定是否以及何时发生翻转。 因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候.
作为任何用途,RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:${log.dir}/${app.dir}/info/log-info-2024-01-19.0.log -->
<!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 -->
<fileNamePattern>${log.dir}/${app.dir}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为${log.maxHistory}天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<maxHistory>${log.maxHistory}</maxHistory>
<!-- 每个日志文件到${log.maxFileSize}的时候开始切分,最多保留${log.maxHistory}天,但最大到${log.totalSizeCap},哪怕没到${log.maxHistory}天也要删除多余的日志 -->
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小,默认值是${log.maxFileSize},测试时可改成5KB看效果 -->
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<!--编码器-->
<encoder>
<!-- pattern节点,用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- error 日志-->
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是log_error.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名-->
<appender name="error_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>${log.dir}/${app.dir}/log_error.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<!-- ThresholdFilter过滤低于指定阈值的事件。 对于等于或高于阈值的事件,ThresholdFilter将在调用其decision()方法时响应NEUTRAL。 但是,将拒绝级别低于阈值的事件 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level><!-- 低于ERROR级别的日志(debug,info)将被拒绝,等于或者高于ERROR的级别将相应NEUTRAL -->
</filter>
<!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件,即RollingPolicy:负责执行翻转所需的操作。
RollingFileAppender的第二个子组件,即TriggeringPolicy:将确定是否以及何时发生翻转。 因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候.
作为任何用途,RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:${log.dir}/${app.dir}/error/log-error-2024-01-19.0.log -->
<!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 -->
<fileNamePattern>${log.dir}/${app.dir}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为${log.maxHistory}天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<maxHistory>${log.maxHistory}</maxHistory>
<!-- 每个日志文件到${log.maxFileSize}的时候开始切分,最多保留${log.maxHistory}天,但最大到${log.totalSizeCap},哪怕没到${log.maxHistory}天也要删除多余的日志 -->
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小,默认值是${log.maxFileSize},测试时可改成5KB看效果 -->
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<!--编码器-->
<encoder>
<!-- pattern节点,用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- warn 日志-->
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是log_warn.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名-->
<appender name="warn_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>${log.dir}/${app.dir}/log_warn.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<!-- ThresholdFilter过滤低于指定阈值的事件。 对于等于或高于阈值的事件,ThresholdFilter将在调用其decision()方法时响应NEUTRAL。 但是,将拒绝级别低于阈值的事件 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件,即RollingPolicy:负责执行翻转所需的操作。
RollingFileAppender的第二个子组件,即TriggeringPolicy:将确定是否以及何时发生翻转。 因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候.
作为任何用途,RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:${log.dir}/${app.dir}/warn/log-warn-2024-01-19.0.log -->
<!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 -->
<fileNamePattern>${log.dir}/${app.dir}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为${log.maxHistory}天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<maxHistory>${log.maxHistory}</maxHistory>
<!-- 每个日志文件到${log.maxFileSize}的时候开始切分,最多保留${log.maxHistory}天,但最大到${log.totalSizeCap},哪怕没到${log.maxHistory}天也要删除多余的日志 -->
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小,默认值是${log.maxFileSize},测试时可改成5KB看效果 -->
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<!--编码器-->
<encoder>
<!-- pattern节点,用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--给定记录器的每个启用的日志记录请求都将转发到该记录器中的所有appender以及层次结构中较高的appender(不用在意level值)。
换句话说,appender是从记录器层次结构中附加地继承的。
例如,如果将控制台appender添加到根记录器,则所有启用的日志记录请求将至少在控制台上打印。
如果另外将文件追加器添加到记录器(例如L),则对L和L'子项启用的记录请求将打印在文件和控制台上。
通过将记录器的additivity标志设置为false,可以覆盖此默认行为,以便不再添加appender累积-->
<!-- configuration中最多允许一个root,别的logger如果没有设置级别则从父级别root继承 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="com.nchu.commondevelopmentframework" level="INFO">
<appender-ref ref="info_log"/>
<appender-ref ref="error_log"/>
<appender-ref ref="warn_log"/>
</logger>
</configuration>
application.yml文件:
log:
home:
path: logs
maxHistory: 30
totalSizeCap: 20GB
maxFileSize: 10MB
spring:
application:
name: demo
参考推文:
[1] logback配置详解
[2] logback的使用和logback.xml详解