时间:2022-12-07 09:38:38 | 栏目:JAVA代码 | 点击:次
SpringBoot会默认使用logback作为日志框架,在生成springboot项目的时候可以直接勾选logback,那么就可以直接使用logback了。手动添加的话,建议使用slf4j+logback,后面项目更容易维护:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.7</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version> </dependency>
SLF4J 是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。大概意思是指你只需要按统一的方式写记录日志的代码,而无需关心日志是通过哪个日志系统,以什么风格输出的,因为它们取决于部署项目时绑定的日志系统。
例如,在项目中使用了 SLF4J 记录日志,并且绑定了 Log4j(即导入相应的依赖),则日志会以 Log4j 的风格输出;后期需要改为以 Logback 的风格输出日志,只需要将 Log4j 替换成 Logback 即可,不用修改项目中的代码。
假如我们需要实现这么一个需求:在文件中记录调用接口事件和传参,并在控制台显示。实现起来很简单,三步即可。
第一步,在resource目录下创建一个logback.xml文件,内部写入:
<?xml version='1.0' encoding='UTF-8'?> <!--日志配置--> <configuration> <!--直接定义属性--> <property name="logFile" value="logs/mutest"/> <property name="maxFileSize" value="30MB"/> <!--控制台日志--> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d [%thread] %-5level %logger{50} -[%file:%line]- %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <!--滚动文件日志--> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logFile}.log</file> <encoder> <!--日志输出格式--> <pattern>%d [%thread] %-5level -[%file:%line]- %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>${maxFileSize}</maxFileSize> </rollingPolicy> </appender> <!--创建一个具体的日志输出--> <logger name="com.mutest" level="info" additivity="true"> <!--可以有多个appender-ref,即将日志记录到不同的位置--> <appender-ref ref="STDOUT"/> <appender-ref ref="fileLog"/> </logger> <!--基础的日志输出--> <root level="info"> </root> </configuration>
关于这段xml的详情,第二章节会详细讲解
第二步,在application.yml文件中配置项目要使用的日志配置文件路径:
logging: config: classpath:logback.xml
第三步,在接口添加日志记录:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { // getLogger()的入参是当前类,否则输出日志的类名会是错误的 private final Logger logger = LoggerFactory.getLogger(TestController.class); @RequestMapping(value = "/test", method = RequestMethod.GET) public String logTest(String name, String age) { logger.info("logTest,name:{},age:{}", name, age); return "success"; } }
当然,如果你安装了lombok这个插件,就更简单了: Lombok使用详解
import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class TestController { @RequestMapping(value = "/test", method = RequestMethod.GET) public String logTest(String name, String age) { log.info("logTest,name:{},age:{}", name, age); return "success"; } }
启动项目后调用接口,控制台输出如我们所期望:
同时,项目中增加了一个log目录,生成mutest.log文件,里面记录了日志:
功能是实现了,但我们脑子里还是有很多小问号,不急,接下来就细细讲来。
首先,在resource目录下创建一个文件,命名为logback.xml。现在先向里面写一些固定的内容,就是下面这个样子:
<?xml version='1.0' encoding='UTF-8'?> <!--日志配置--> <configuration> <!--直接定义属性--> <property name="" value=""/> <!--通过配置文件定义属性--> <springProperty name="" source=""/> <!--定义并描述一个日志的输出属性--> <appender name="" class=""> </appender> <!--创建一个具体的日志输出--> <!--name指定包名--> <logger name="" level="" additivity=""> <!--ref值指向appender的name--> <appender-ref ref=""/> </logger> <!--基础的日志输出--> <root level=""> <appender-ref ref=""/> </root> </configuration>
<configuration>是logback.xml这个xml文件的根节点,它包含以下属性:
例如,下面这个configuration:
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 其他配置省略--> </configuration>
这两个节点可以设置全局变量。
property可以直接设置,例如:
<property name="logFile" value="logs/mutest"/>
这样就设置了一个名为logFile的变量,后续通过${logFile}的方式就引用到了其值logs/mutest。
而springProperty则要配合配置文件,例如:
<springProperty name="logFile" source="log.file"/>
也是设置了一个名为logFile的变量,但没有直接赋值,而是通过source指向了配置文件的路径,配置文件中是这样的:
log: file: logs/mutest
root节点,必选节点,用来指定最基础的日志输出级别并指定<appender>,可以理解为根logger。
一个典型的root节点如下:
<root level="debug"> <appender-ref ref="console" /> <appender-ref ref="file" /> </root>
appender节点是非常关键的一个节点,负责格式化一个日志输出节点(也就是描述日志存储类型、位置、滚动规则等属性)。我个人理解,appender作用类似于构造一个日志模板,而logger是真正的日志输出者,使用某个appender作为模板去写日志。
appender有三种类型,分别是ConsoleAppender(控制台日志)、FileAppender(文件日志)、RollingFileAppender(滚动文件日志)。
ConsoleAppender的作用是将日志输出到控制台,一般在本地调试时使用,它的配置非常简单,一个典型的ConsoleAppender如下:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d [%thread] %-5level %logger{50} -[%file:%line]- %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender>
appender 有name和class两个属性:
FileAppender用于把日志添加到文件。一个典型的FileAppender如下:
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>testFile.log</file> <append>true</append> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>
相对于ConsoleAppender,它多了一些子节点,让我们一一来看:
pattern定义了日志的输出格式,我们以<pattern>%d [%thread] %-5level -[%file:%line]- %msg%n</pattern>为例,分解开来:
RollingFileAppender用于滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。一个典型的RollingFileAppender节点如下:
<configuration> <!--直接定义属性--> <property name="logFile" value="logs/mutest"/> <property name="maxFileSize" value="30MB"/> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--日志文件存储路径,来自property设置--> <file>${logFile}.log</file> <encoder> <pattern>%d [%thread] %-5level -[%file:%line]- %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--每天生成一个新的活动日志文件,旧的日志归档,后缀名为2019.08.12这种格式--> <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!--活动日志文件最大值,超过这个值将产生新日志文件--> <maxFileSize>${maxFileSize}</maxFileSize> <!--只保留最近30天的日志--> <maxHistory>30</maxHistory> <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>error</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> </configuration>
另外,RollingFileAppender节点下有一些常用的子节点:
还有几个属性,要根据滚动策略去添加:
logger节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的<appender>(可以把<appender>理解为一个日志模板)。
一个典型的logger节点如下:
<!-- name 属性表示匹配的logger类型前缀 --> <logger name="com.mutest.demo"> <level value="INFO" /> <!-- 引用的appender,类似于spring的ref --> <appender-ref ref="fileLog" /> <appender-ref ref="STDOUT" /> </logger>
logback有5种级别,分别是TRACE < DEBUG < INFO < WARN < ERROR,定义于ch.qos.logback.classic.Level类中。
此外OFF表示关闭全部日志,ALL表示开启全部日志。
那么,在logback中,日志级别如何设置呢?
首先,<root>中可以设置日志级别,如果不设置,root logger默认级别是DEBUG。
<root level="info"></root>
其次,logger中可以设置日志级别,设置后将覆盖<root>的设置,不设置将继承<root>的日志级别
<logger name="com.mutest" level="error" additivity="false"> <appender-ref ref="STDOUT"/> <appender-ref ref="fileLog"/> </logger>
另外,还可以在配置文件中设置更加具体的日志级别,例如将com.mutest.controller包下所有的日志输出级别设置为info,那么即使logger中,设置为error级别,日志仍然输出。
logging: config: classpath:logback.xml level: com.mutest.controller: info
如果不设置日志滚动策略,那么会一直向一个文件中追加日志,日志文件会越来越大,想要查找有用信息会很慢,而且有占满磁盘的风险。所以,我们要设置滚动策略,即满足一定条件,生成一个新文件,而旧日志文件进行归档。
以时间周期为切分条件,<rollingPolicy>的class要设置为ch.qos.logback.core.rolling.TimeBasedRollingPolicy,一个典型示例(每天生成一个日志文件,保存30天的日志文件)如下:
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
以文件大小为切分条件,<rollingPolicy>的class要设置为ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy,一个典型示例(活动日志文件大小超过30M则生成新的活动日志文件)如下:
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <fileNamePattern>logFile.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>30MB</maxFileSize> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
要注意的是,<fileNamePattern>中,%i必须要有,如果同一天产生多个归档日志文件,%i会产生一个后缀加以区分。例如mutest.2019-07-28.0.log 和 mutest.2019-07-28.1.log。
根据日志文件大小和时间周期作为切分条件,满足其中任意一个就要做切分。<rollingPolicy>的class要设置为ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy,一个典型示例如下:
<configuration> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>mutest.log</file> <encoder> <pattern>%d [%thread] %-5level -[%file:%line]- %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>${maxFileSize}</maxFileSize> </rollingPolicy> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
同样,<fileNamePattern>中必须有%i。
首先,了解一下,日志级别从低到高分为:
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
有时候,我们需要对日志进行过滤,logback提供了多种过滤规则的实现。
比如说,日志级别为info以上,但我们不想打印warn类型的日志,那么按照下面的配置做:
<filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>warn</level> <onMatch>DENY</onMatch> <onMismatch>ACCEPT</onMismatch> </filter>
几个参数的含义:
除了 ch.qos.logback.classic.filter.LevelFilter外,还有一种过滤策略:ThresholdFilter。即临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。
比如,设置只打印info级别以上的日志:
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>info</level> </filter>
EvaluatorFilter是求值过滤器,评估、鉴别日志是否符合指定条件。
<filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator> <!-- 默认为 ch.qos.logback.classic.boolex.JaninoEventEvaluator --> <expression>return message.contains("success");</expression> </evaluator> <OnMatch>ACCEPT</OnMatch> <OnMismatch>DENY</OnMismatch> </filter>
属性释义:
Spring Boot项目的配置文件有 application.properties 文件和 application.yml 文件两种,而我个人比较喜欢用 yml 文件。
application.yml 文件中对日志的配置:
logging: config: logback.xml level: com.example.demo.dao: trace