共计 8026 个字符,预计需要花费 21 分钟才能阅读完成。
@[toc]
之前录过一个视频和大家分享 Spring Boot 日志问题,然而总感觉差点意思,因而松哥打算再通过一篇文章来和大家捋一捋 Java 中的日志问题,顺便咱们把 Spring Boot 中的日志问题也说分明。
1. Java 日志概览
说到 Java 日志,很多初学者可能都比拟懵,因为这里波及到太多货色了:Apache Commons Logging
、Slf4j
、Log4j
、Log4j2
、Logback
、Java Util Logging
等等,这些框架各自有什么作用?他们之间有什么区别?
1.1 总体概览
上面这张图很好的展现了 Java 中的日志体系:
能够看到,Java 中的日志框架次要分为两大类:日志门面 和日志实现。
日志门面
日志门面定义了一组日志的接口标准,它并不提供底层具体的实现逻辑。Apache Commons Logging
和 Slf4j
就属于这一类。
日志实现
日志实现则是日志具体的实现,包含日志级别管制、日志打印格局、日志输入模式(输入到数据库、输入到文件、输入到控制台等)。Log4j
、Log4j2
、Logback
以及 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
组合。
Logback
是 Slf4j
的原生实现框架,它也出自 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 Logging
、Log4j
等框架,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 中只能实现对日志一些非常简单的配置,如果想实现更加细粒度的日志配置,那就须要应用日志实现的原生配置,例如 Logback
的 classpath:logback.xml
,Log4j
的 classpath: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