专栏名称: Java知音
专注于Java,推送技术文章,热门开源项目等。致力打造一个有实用,有情怀的Java技术公众号!
目录
相关文章推荐
哈密伊州区微生活  ·  穿袜子和不穿袜子睡觉,哪个睡得更香? ·  昨天  
929南通交通广播  ·  女子追剧险失明?只因一个习惯→ ·  3 天前  
51好读  ›  专栏  ›  Java知音

SpringBoot 项目使用 SLF4J+logback 进行日志记录,来增强可维护性

Java知音  · 公众号  ·  · 2020-11-02 09:33

正文

作者:云深不知处

blog.csdn.net/mu_wind/article/details/99830829

SpringBoot会默认使用logback作为日志框架,在生成springboot项目的时候可以直接勾选logback,那么就可以直接使用logback了。手动添加的话,建议使用slf4j+logback,后面项目更容易维护:

<dependency>
  <groupId>org.slf4jgroupId>
  <artifactId>slf4j-apiartifactId>
  <version>1.7.21version>
dependency>

<dependency>
  <groupId>ch.qos.logbackgroupId>
  <artifactId>logback-coreartifactId>
  <version>1.1.7version>
dependency>

<dependency>
  <groupId>ch.qos.logbackgroupId>
  <artifactId>logback-classicartifactId>
  <version>1.1.7version>
dependency>

SLF4J 是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。大概意思是指你只需要按统一的方式写记录日志的代码,而无需关心日志是通过哪个日志系统,以什么风格输出的,因为它们取决于部署项目时绑定的日志系统。

例如,在项目中使用了 SLF4J 记录日志,并且绑定了 Log4j(即导入相应的依赖),则日志会以 Log4j 的风格输出;后期需要改为以 Logback 的风格输出日志,只需要将 Log4j 替换成 Logback 即可,不用修改项目中的代码。

1 快速实现

假如我们需要实现这么一个需求:在文件中记录调用接口事件和传参,并在控制台显示。实现起来很简单,三步即可。

第一步,在resource目录下创建一个logback.xml文件,内部写入:



<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%npattern>
            <charset>UTF-8charset>
        encoder>
    appender>

 
    <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logFile}.logfile>
        <encoder>
         
            <pattern>%d [%thread] %-5level -[%file:%line]- %msg%npattern>
            <charset>UTF-8charset>
        encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i.logfileNamePattern>
            <maxFileSize>${maxFileSize}maxFileSize>
        rollingPolicy>
    appender>
    
    <logger name="com.mutest" level="info" additivity="true">
     
        <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这个插件,就更简单了:

https://blog.csdn.net/mu_wind/article/details/104844946

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文件,里面记录了日志:


功能是实现了,但我们脑子里还是有很多小问号,不急,接下来就细细讲来。

2 配置xml

首先,在 resource 目录下创建一个文件,命名为 logback.xml 。现在先向里面写一些固定的内容,就是下面这个样子:



<configuration>
    
    <property name="" value=""/>
    
    <springProperty name="" source=""/>
    
    
    <appender name="" class="">

    appender>
    
    <logger name="" level="" additivity="">
        <appender-ref ref=""/>
    logger>

    
    <root level="">
        <appender-ref ref=""/>
    root>
configuration>
在这里插入图片描述

2.1 configuration

是logback.xml这个xml文件的根节点,它包含以下属性:

  1. scan :当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。

  2. scanPeriod :设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。

  3. debug :当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

例如,下面这个configuration:

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
        
configuration>  

2.2 property和springProperty

这两个节点可以设置全局变量。

property可以直接设置,例如:

"logFile" value="logs/mutest"/>

这样就设置了一个名为 logFile 的变量,后续通过 ${logFile} 的方式就引用到了其值 logs/mutest

而springProperty则要配合配置文件,例如:

"logFile" source="log.file"/>

也是设置了一个名为 logFile 的变量,但没有直接赋值,而是通过source指向了配置文件的路径,配置文件中是这样的:

log:
  file: logs/mutest

2.3 root

root 节点,必选节点,用来指定最基础的日志输出级别并指定 ,可以理解为根 logger

一个典型的root节点如下:

"debug">
 "console" />
 "file" />

2.4 appender

appender 节点是非常关键的一个节点,负责格式化一个日志输出节点(也就是描述日志存储类型、位置、滚动规则等属性)。我个人理解,appender作用类似于构造一个日志模板,而logger是真正的日志输出者,使用某个 appender 作为模板去写日志。

appender有三种类型,分别是 ConsoleAppender (控制台日志)、 FileAppender (文件日志)、 RollingFileAppender (滚动文件日志)。

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典 .pdf

2.4.1 ConsoleAppender

ConsoleAppender 的作用是将日志输出到控制台,一般在本地调试时使用,它的配置非常简单,一个典型的 ConsoleAppender 如下:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 <encoder>
        <pattern>%d [%thread] %-5level %logger{50} -[%file:%line]- %msg%npattern>
        <charset>UTF-8charset>
    encoder>
appender>

appender 有name和class两个属性:

  • name appender 节点的名称,在后文中被 logger 节点引用。一个logback配置文件中不能有重复的 appender name

  • class :使用何种日志输出策略,分别是 ConsoleAppender (控制台日志)、 FileAppender (文件日志)、 RollingFileAppender (滚动文件日志)。

2.4.2 FileAppender

FileAppender 用于把日志添加到文件。一个典型的 FileAppender 如下:

<appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
 <file>testFile.logfile> 
 <append>trueappend> 
 <encoder> 
  <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%npattern> 
 encoder>
appender> 

相对于 ConsoleAppender ,它多了一些子节点,让我们一一来看:

  • :被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

  • :如果是 true ,日志被追加到文件结尾,如果是 false ,清空现存文件,默认是 true

  • :对记录事件进行格式化。(具体参数稍后讲解 )

  • :如果是 true ,日志会被安全的写入文件,即使其他的 FileAppender 也在向此文件做写入操作,效率低,默认是 false

  • :日志的输出格式。

pattern 定义了日志的输出格式,我们以 %d [%thread] %-5level -[%file:%line]- %msg%n 为例,分解开来:

  1. %date :表示日期

  2. %thread :表示线程名

  3. %-5level :表示级别从左显示 5 个字符宽度

  4. %logger{50} :表示 Logger 名字最长 50 个字符

  5. %msg :表示日志消息

  6. %n :换行符

2.4.3 RollingFileAppender

RollingFileAppender 用于滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。一个典型的 RollingFileAppender 节点如下:

<configuration>
 
    <property name="logFile" value="logs/mutest"/>
    <property name="maxFileSize" value="30MB"/>

 <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
  
        <file>${logFile}.logfile>
        <encoder>
            <pattern>%d [%thread] %-5level -[%file:%line]- %msg%npattern>
            <charset>UTF-8charset>
        encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
         
            <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i.logfileNamePattern>
            
            <maxFileSize>${maxFileSize}maxFileSize>
            
         <maxHistory>30maxHistory>
         
         <totalSizeCap>1GBtotalSizeCap>
        rollingPolicy>
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>errorlevel>
            <onMatch>ACCEPTonMatch>
            <onMismatch>DENYonMismatch>
        filter>
    appender>
configuration>

另外, RollingFileAppender 节点下有一些常用的子节点:

  • :当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。

  • :日志输出拦截器,可以自定义拦截器也可以用系统一些定义好的拦截器。

  • :当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。属性 class 定义具体的滚动策略类。

  1. SizeAndTimeBasedRollingPolicy :根据日志文件大小和时间周期作为切分条件,满足其中任意一个就要做切分。maxFileSize的值决定了当天的日志文件大小上限,超过这个上限,同一天将会有多个日志文件,因此 ${logFile}.%d{yyyy-MM-dd}.%i 中有一个 %i ,就是为应对同一天生成多个日志文件而写,在日志量很大的情况下,会出现 mutest.log.2020-07-28.0.log、mutest.2020-07-28.1.log 这种情况。

  2. TimeBasedRollingPolicy :只以时间周期为切分条件,在这种策略下,存档日志名称格式设置为 ${logFile}.%d{yyyy-MM-dd}.log 即可。

  3. SizeBasedTriggeringPolicy :只以文件大小为切分条件,在这种策略下, 日志滚动的唯一触发条件。

  • :必要节点。以 ${logFile}.%d{yyyy-MM-dd}.%i.log 为例(mutest.2019-07-28.0.log),有这么几个部分:
  1. ${logFile} :固定文件名称前缀,这里是引用了 中设置的变量。

  2. %d{yyyy-MM} :指定日志名称中间日期的格式,如果只有 %d ,将默认使用 yyyy-MM-dd 格式。

  3. %i :当日志量过大,导致同一天生成两个及以上日志文件时,这个属性将为日志名称加一个索引作为后缀,以加以区分。

  4. .log.zip :指定存档日志文件的压缩格式。

还有几个属性,要根据滚动策略去添加:

  • :这是活动文件的大小, SizeAndTimeBasedRollingPolicy 策略和 SizeBasedTriggeringPolicy 策略下必须有。默认值是10MB。超过这个大小,就要生成新的活动文件了。

  • :可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且 是6,则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删。

  • :可选节点,表示日志文件总大小超过1GB将删除存档日志文件。

2.5 logger

logger 节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的 (可以把 理解为一个日志模板)。

一个典型的 logger 节点如下:

  
<logger name="com.mutest.demo">  
    <level value="INFO" />  
      
    <appender-ref ref="fileLog" />  
    <appender-ref ref="STDOUT" /> 
logger>  
  1. name :必写属性,指定具体包或类,被指定的包或类中的日志输出将遵从该 logger 规定配置。

  2. level :非必写属性,指定日志输出级别,该级别将覆盖 root 配置的输出级别。

  3. addtivity :非必写属性,是否向上级loger传递打印信息。默认是true。

  4. appender-ref :引用的 appender ,引用后将实现 appender 中定义的行为,例如上面示例中引用了 fileLog 这个 appender ,那么 com.mutest.demo 中打印的日志将按 fileLog 的配置进行记录。一个 logger 可以有多个引用,互不影响。

3 更多情形

3.1 日志级别

logback有5种级别,分别是 TRACE < DEBUG < INFO < WARN < ERROR ,定义于ch.qos.logback.classic.Level类中。

  • Trace:是追踪,就是程序推进一下,你就可以写个 trace 输出,所以 trace 应该会特别多,一般不会设置到这个级别。

  • Debug :指出细粒度信息事件对调试应用程序是非常有帮助的。

  • Info :消息在粗粒度级别上突出强调应用程序的运行过程。

  • Warn:输出警告及warn以上级别的日志。

  • Error :输出错误信息日志.

此外OFF表示关闭全部日志,ALL表示开启全部日志。

那么,在logback中,日志级别如何设置呢?

首先, 中可以设置日志级别,如果不设置, root logger 默认级别是 DEBUG

 "info">

其次, logger 中可以设置日志级别,设置后将覆盖 的设置,不设置将继承 的日志级别

<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

3.2 日志滚动

如果不设置日志滚动策略,那么会一直向一个文件中追加日志,日志文件会越来越大,想要查找有用信息会很慢,而且有占满磁盘的风险。所以,我们要设置滚动策略,即满足一定条件,生成一个新文件,而旧日志文件进行归档。

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典 .pdf

3.2.1 时间策略

以时间周期为切分条件, 的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}.logfileNamePattern> 
      <maxHistory>30maxHistory>
    rollingPolicy> 
    <encoder> 
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%npattern






请到「今天看啥」查看全文