关于springboot:Spring-Boot-日志各种使用姿势是时候捋清楚了

35次阅读

共计 8026 个字符,预计需要花费 21 分钟才能阅读完成。

@[toc]
之前录过一个视频和大家分享 Spring Boot 日志问题,然而总感觉差点意思,因而松哥打算再通过一篇文章来和大家捋一捋 Java 中的日志问题,顺便咱们把 Spring Boot 中的日志问题也说分明。

1. Java 日志概览

说到 Java 日志,很多初学者可能都比拟懵,因为这里波及到太多货色了:Apache Commons LoggingSlf4jLog4jLog4j2LogbackJava Util Logging 等等,这些框架各自有什么作用?他们之间有什么区别?

1.1 总体概览

上面这张图很好的展现了 Java 中的日志体系:

能够看到,Java 中的日志框架次要分为两大类:日志门面 日志实现

日志门面

日志门面定义了一组日志的接口标准,它并不提供底层具体的实现逻辑。Apache Commons LoggingSlf4j 就属于这一类。

日志实现

日志实现则是日志具体的实现,包含日志级别管制、日志打印格局、日志输入模式(输入到数据库、输入到文件、输入到控制台等)。Log4jLog4j2Logback 以及 Java Util Logging 则属于这一类。

将日志门面和日志实现拆散其实是一种典型的门面模式,这种形式能够让具体业务在不同的日志实现框架之间自在切换,而不须要改变任何代码,开发者只须要把握日志门面的 API 即可。

日志门面是不能独自应用的,它必须和一种具体的日志实现框架相结合应用。

那么日志框架是否能够独自应用呢?

技术上来说当然没问题,然而咱们个别不会这样做,因为这样做可维护性很差,而且前期扩大不易。例如 A 开发了一个工具包应用 Log4j 打印日志,B 援用了这个工具包,然而 B 喜爱应用 Logback 打印日志,此时就会呈现一个业务应用两个甚至多个日志框架,开发者也须要保护多个日志的配置文件。因而咱们都是用日志门面打印日志。

1.2 日志级别

应用日志级别的益处在于,调整级别,就能够屏蔽掉很多调试相干的日志输入。不同的日志实现定义的日志级别不太一样,不过也都大同小异。

Java Util Logging

Java Util Logging 定义了 7 个日志级别,从重大到一般顺次是:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

因为默认级别是 INFO,因而 INFO 级别以下的日志,不会被打印进去。

Log4j

Log4j 定义了 8 个日志级别(除去 OFF 和 ALL,能够说分为 6 个级别),从重大到一般顺次是:

  • OFF:最高等级的,用于敞开所有日志记录。
  • FATAL:重大谬误,这种级别能够间接进行程序了。
  • ERROR:打印谬误和异样信息,如果不想输入太多的日志,能够应用这个级别。
  • WARN:正告提醒。
  • INFO:用于生产环境中输入程序运行的一些重要信息,不能滥用。
  • DEBUG:用于开发过程中打印一些运行信息。
  • TRACE
  • ALL 最低等级的,用于关上所有日志记录。

Logback

Logback 日志级别比较简单,从重大到一般顺次是:

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

1.3 综合比照

Java Util Logging 零碎在 JVM 启动时读取配置文件并实现初始化,一旦应用程序开始运行,就无奈批改配置。另外,这种日志实现配置也不太不便,只能在 JVM 启动时传递参数,像上面这样:

-Djava.util.logging.config.file=<config-file-name>。

因为这些局限性,导致 Java Util Logging 并未宽泛应用。

Log4j 尽管配置繁琐,然而一旦配置实现,应用起来就十分不便,只须要将相干的配置文件放到 classpath 下即可。在很多状况下,Log4j 的配置文件咱们能够在不同的我的项目中重复应用。

Log4j 能够和 Apache Commons Logging 搭配应用,Apache Commons Logging 会主动搜寻并应用 Log4j,如果没有找到 Log4j,再应用 Java Util Logging

Log4j + Apache Commons Logging 组合更得人心的是 Slf4j + Logback 组合。

LogbackSlf4j 的原生实现框架,它也出自 Log4j 作者(Ceki Gülcü)之手,然而相比 Log4j,它领有更多的长处、个性以及更强的性能。

1.4 最佳实际

  • 如果不想增加任何依赖,应用 Java Util Logging 或框架容器曾经提供的日志接口。
  • 如果比拟在意性能,举荐:Slf4j + Logback
  • 如果我的项目中曾经应用了 Log4j 且没有发现性能问题,举荐组合为:Slf4j + Log4j2

2. Spring Boot 日志实现

Spring Boot 应用 Apache Commons Logging 作为外部的日志框架门面,它只是一个日志接口,在理论利用中须要为该接口来指定相应的日志实现。

Spring Boot 默认的日志实现是 Logback。这个很好查看:轻易启动一个 Spring Boot 我的项目,从控制台找一行日志,例如上面这样:

思考到最初的 prod 是一个能够变动的字符,咱们在我的项目中全局搜寻:The following profiles are active,后果如下:

在日志输入的那一行 debug。而后再次启动我的项目,如下图:

此时咱们就能够看到真正的日志实现是 Logback

其余的诸如 Java Util LoggingLog4j 等框架,Spring Boot 也有很好的反对。

在 Spring Boot 我的项目中,只有增加了如下 web 依赖,日志依赖就主动增加进来了:

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

2.1 Spring Boot 日志配置

Spring Boot 的日志零碎会主动依据 classpath 下的内容抉择适合的日志配置,在这个过程中首选 Logback。

如果开发者须要批改日志级别,只须要在 application.properties 文件中通过 logging.level 前缀 + 包名 的模式进行配置即可,例如上面这样:

logging.level.org.springframework.web=debug
logging.level.org.hibernate=error

如果你想将日志输入到文件,能够通过如下配置指定日志文件名:

logging.file.name=javaboy.log

logging.file.name 能够只指定日志文件名,也能够指定日志文件全门路,例如上面这样:

logging.file.name=/Users/sang/Documents/javaboy/javaboy.log

如果你只是想从新定义输入日志文件的门路,也能够应用 logging.file.path 属性,如下:

logging.file.path=/Users/sang/Documents/javaboy

如果想对输入到文件中的日志进行精细化治理,还有如下一些属性能够配置:

  • logging.logback.rollingpolicy.file-name-pattern:日志归档的文件名,日志文件达到肯定大小之后,主动进行压缩归档。
  • logging.logback.rollingpolicy.clean-history-on-start:是否在利用启动时进行归档治理。
  • logging.logback.rollingpolicy.max-file-size:日志文件大小下限,达到该下限后,会主动压缩。
  • logging.logback.rollingpolicy.total-size-cap:日志文件被删除之前,能够包容的最大大小。
  • logging.logback.rollingpolicy.max-history:日志文件保留的天数。

日志文件归档这块,小伙伴们感兴趣能够本人试下,能够首先将 max-file-size 属性调小,这样不便看到成果:

logging.logback.rollingpolicy.max-file-size=1MB

而后增加如下接口:

@RestController
public class HelloController {private static final Logger logger = getLogger(HelloController.class);
    @GetMapping("/hello")
    public void hello() {for (int i = 0; i < 100000; i++) {logger.info("hello javaboy");
        }
    }
}

拜访该接口,能够看到最终生成的日志文件被主动压缩了:

application.properties 中还能够配置日志分组。

日志分组可能把相干的 logger 放到一个组对立治理。

例如咱们能够定义一个 tomcat 组:

logging.group.tomcat=org.apache.catalina,org.apache.coyote, org.apache.tomcat

而后对立治理 tomcat 组中的所有 logger:

logging.level.tomcat=TRACE

Spring Boot 中还预约义了两个日志分组 web 和 sql,如下:

不过在 application.properties 中只能实现对日志一些非常简单的配置,如果想实现更加细粒度的日志配置,那就须要应用日志实现的原生配置,例如 Logbackclasspath:logback.xmlLog4jclasspath:log4j.xml 等。如果这些日志配置文件存在于 classpath 下,那么默认状况下,Spring Boot 就会主动加载这些配置文件。

2.2 Logback 配置

2.2.1 根本配置

默认的 Logback 配置文件名有两种:

  • logback.xml:这种配置文件会间接被日志框架加载。
  • logback-spring.xml:这种配置文件不会被日志框架间接加载,而是由 Spring Boot 去解析日志配置,能够应用 Spring Boot 的高级 Profile 性能。

Spring Boot 中为 Logback 提供了四个默认的配置文件,地位在 org/springframework/boot/logging/logback/,别离是:

  • defaults.xml:提供了公共的日志配置,日志输入规定等。
  • console-appender.xml:应用 CONSOLE_LOG_PATTERN 增加一个 ConsoleAppender。
  • file-appender.xml:增加一个 RollingFileAppender。
  • base.xml:为了兼容旧版 Spring Boot 而提供的。

如果须要自定义 logback.xml 文件,能够在自定义时应用这些默认的配置文件,也能够不应用。一个典型的 logback.xml 文件如下(resources/logback.xml):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

能够通过 include 引入 Spring Boot 曾经提供的配置文件,也能够自定义。

2.2.2 输入到文件

如果想禁止控制台的日志输入,转而将日志内容输入到一个文件,咱们能够自定义一个 logback-spring.xml 文件,并引入后面所说的 file-appender.xml 文件。

像上面这样(resources/logback-spring.xml):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>

2.3 Log4j 配置

如果 classpath 下存在 Log4j2 的依赖,Spring Boot 会主动进行配置。

默认状况下 classpath 下当然不存在 Log4j2 的依赖,如果想应用 Log4j2,能够排除已有的 Logback,而后再引入 Log4j2,如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

Log4j2 的配置就比拟容易了,在 reources 目录下新建 log4j2.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="warn">
    <properties>
        <Property name="app_name">logging</Property>
        <Property name="log_path">logs/${app_name}</Property>
    </properties>
    <appenders>
        <console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d][%t][%p][%l] %m%n" />
        </console>
        <RollingFile name="RollingFileInfo" fileName="${log_path}/info.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" />
                <ThresholdFilter level="WARN" onMatch="DENY"
                                 onMismatch="NEUTRAL" />
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${log_path}/warn.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="WARN" />
                <ThresholdFilter level="ERROR" onMatch="DENY"
                                 onMismatch="NEUTRAL" />
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>

        <RollingFile name="RollingFileError" fileName="${log_path}/error.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="ERROR" />
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="2 MB" />
            </Policies>
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>
    </appenders>
    <loggers>
        <root level="info">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
            <appender-ref ref="RollingFileWarn" />
            <appender-ref ref="RollingFileError" />
        </root>
    </loggers>
</configuration>

首先在 properties 节点中指定了利用名称以及日志文件地位。

而后通过几个不同的 RollingFile 对不同级别的日志别离解决,不同级别的日志将输入到不同的文件,并依照各自的命名形式进行压缩。

这段配置比拟程式化,小伙伴们能够保留下来做成 IntelliJ IDEA 模版以便日常应用。

3. 小结

好啦,这就是松哥和小伙伴们分享的 Spring Boot 日志了,整体来说并不难,小伙伴们能够认真品一品。

最初,松哥还收集了 50+ 个我的项目需要文档,想做个我的项目练练手的小伙伴无妨看看哦~



需要文档地址:https://gitee.com/lenve/javadoc

正文完
 0