Springboot 日志

一、日志的目的

日志,通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节.但是,这丝毫不影响它在任何一个系统中的重要的地位.为了保证服务的高可用,发现问题一定要及时,解决问题一定要迅速,所以生产环境一旦出现问题,预警系统就会通过邮件、短信甚至电话的方式实施多维轰炸模式,确保相关负责人不错过每一个可能的 bug.预警系统判断疑似 bug 大部分源于日志.比如某个微服务接口由于各种原因导致频繁调用出错,此时调用端会捕获这样的异常并打印 ERROR 级别的日志,当该错误日志达到一定次数出现的时候,就会触发报警.

 

二、常用的日志门面和日志实现

1、日志门面

JCL(Jakarta Commons Logging): Apache Jakarta 小组开发的日志门面

jboss-logging: 特定的框架使用的日志门面,一般我们用不到,例如 Hibernate 框架使用的日志接口就是 jboss-logging

SLF4J: Simple Logging Facade For Java

2、日志实现

Log4j2: Apache 重新推出的日志框架

JUL: java.util.logging 的日志实现

Log4j 和 Logback 是同一个人开发的,由于 Log4j 存在性能问题,然后 Log4j 日志框架的开发人员想要对 Log4j 进行升级,然后就有了 Logback 这个日志框架,而为了能够使日志系统具有扩展性,才写了 SLF4J 这个抽象层的日志门面.

当然还有很多没有列举出来的日志框架,为什么有了 Commons Logging 和 Log4j ,又会蹦出来 SLF4J 和 Logback?这是因为 Java 有着非常悠久的开源历史,不但 OpenJDK 本身是开源的,而且我们用到的第三方库,几乎全部都是开源的.开源生态丰富的一个特定就是,同一个功能,可以找到若干种互相竞争的开源库.因为对 Commons Logging的接口不满意,有人就搞了 SLF4J.因为对 Log4j 的性能不满意,有人就搞了 Logback.

从目前的趋势来看,越来越多的开源项目从 Commons Logging + Log4j 转向了 SLF4J + Logback 的日志架构

而我们今天的主角 Springboot 使用的日志架构就是 SLF4J + Logback

 

三、怎么使用 SLF4J 日志框架

我们可以查看 SLF4J 的官网去查看如何使用

前面我们讲到了日志门面(日志接口)和日志实现框架,这里的 SLF4J 就是一个日志接口,我们使用具体的 API 的时候调用的是日志接口中的方法,它会根据实际引入的日志实现类框架去调用具体的日志实现方法.所以呢,我们需要根据具体的日志实现框架引入对应的配置文件

SLF4J unbound: 只需要导入一个 slf4j-api.jar 就可以

SLF4J bound to logback-classic: 导入 SLF4J 日志接口的 jar 包 slf4j-api.jar、Logback 日志实现的 jar 包 logback-classic.jar、logback-core.jar

SLF4J bound to log4j: 前面我们提到过, logback 的出现就是为了对 log4j 的升级,为了扩展性,才推出了 SLF4J 这个日志接口,所以 SLF4J 这个日志接口出现的时间是要比 Log4j 日志实现框架要晚的,这个时候你想使用 SLF4J 日志门面,而具体的日志实现框架使用 Log4j ,那么就必须需要一个中间转换包,这里对应的就是 Adaptation layer(适配层:它具体的原理是:slf4j-log412.jar 包中实现 slf4j-api.jar 中的所有方法,而方法中调用的是 log4j 的日志功能方法去进行日志记录)

其它的就不进行说明了...

理论上是比较简单,但是在实际情况下,往往比上述描述的情况复杂一些,例如我们想使用 SLF4J + Logback 的方式来进行日志记录,可是我们项目中往往会引入其它的依赖,例如Spring 它使用的日志接口是 Commons-Logging,如果没有这个日志接口, Spring 启动就会报错,那么我们怎么使项目统一使用 SLF4J + Logback 的方式进行日志记录呢?

进入官网: http://www.slf4j.org/ 

点击 leagcy APIs 之后我们可以看到统一的日志处理图示,由于我们这里是想使用 SLF4J + Logback 的日志方式,所以我们就讲这一种

可以看到这里面有很多的日志,有 Spirng 的 Commons logging 日志、有 log4j 的日志、有 java.util.logging 日志,这里面的做法就是通过引入对应的中间转换 jar包(红色圈住的那几个 jar 包)

jcl-over-slf4j.jar: 这个 jar 包的作用就是既包含 Spring 的 Commons logging 日志的所有内容,这样 Spring 启动的时候就不会因为缺少 Commons logging 而报错了,又包含具体的日志输出方式,也就是采用 SLF4J 的方式输出日志

log4j-ocer-slf4j.jar: 和上面的 jcl-over-slf4j.jar 作用类似, Log4j 转换为 SLF4J 的中间转换包

jul-to-slf4j.jar: java.util.logging 转换为 SLF4J 的中间转换包

所以我们想要统一项目中的日志具体的实现步骤如下:

1、将系统中的其它日志框架排除出去(因为日志的中间替换包中已经有了该日志的实现,如果不排除出去的话就会存在日志实现的 jar 包冲突问题)

2、使用中间转换包替换原有的日志框架,防止其它依赖中有使用原有的日志框架而报错

3、导入 SLF4J 的其它实现(我们这里是 SLF4J + Logback)

 

四、Springboot 的日志关系

Springboot 中是通过 spring-boot-starter-logging 来完成相关的日志配置的

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

我们从下面的依赖图中也可以看出来,项目中 jcl-over-slf4j(java commons logging 转换成 slf4j 的中间转换包)、log4j-over-slf4j(log4j 转换成 slf4j 的中间转换包)、jul-to-slf4j(java.util.logging 转换成 slf4j 的中间转换包),而项目中真正使用的是 logback 的日志实现框架.

Springboot 日志常用的配置

在 application.yaml 中添加相应配置

一、指定文件的名称/路径

1、只指定文件的路径( path 带盘符)

logging:
  path: E:/springLog

最终会在 E:springLog 路径下生成一个默认名称的文件来保存日志,文件名称是 spring.log

2、指定路径和文件名称( path 带日志文件名称带盘符)

logging:
  path: E:/springLog/springboot.log

这种情况下, springboot 会将 springboot.log 当成是一个目录,而不会当成是一个日志文件,最终会在 E:/springLog/springboot.log 目录下面生成一个默认的spring.log 文件

3、指定路径( path 不带盘符)

logging:
  path: /springLog/

最终会在当前项目所在盘符的根目录下生成一个 springLog 目录,并且在 springLog 目录下面会生成一个默认名称的 spring.log 文件来保存日志

4、只指定文件名称( file 不带盘符)

logging:
  file: springboot.log

最终会在当前项目的根路径下生成一个 springboot.log 用来保存日志

5、同时指定路径和文件名称( file 带路径和盘符)

logging:
  file: E:/springLog/springboot.log

最终会在 E:/springLog/ 目录下生成一个 springboot.log 用来保存日志

6、同时指定路径和文件名称(不带盘符)

logging:
  file: /springboot/springboot.log

最终会在该项目所在盘符的根目录下生成一个 springboot 目录,在 springboot 目录下面生成一个 springboot.log 用来保存日志

7、同时包含 path 和 file

logging:
  path: /spring/
  file: springboot.log

这个时候同时有 path 和 file 选项,它们是冲突的, springboot 默认会选择 file 的配置项来进行处理,也就是会在当前项目下面生成一个 springboot.log 用来保存日志信息

二、指定日志输出格式 logging.pattern (日志输出格式)

logging:
  file: springbootLog.log
  pattern:
      # 在控制台输出的日志的格式
      console: '%d{yyyy-MM-dd}----> [%thread] %-5level----> %logger{50}----> %msg%n'
      # 在指定文件中日志输出的格式
      file: '%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} === %msg%n'
%d :表示日期时间 
%thread :表示线程名 
%‐5level :级别从左显示 5 个字符宽度 
%logger{50} :表示 logger 名字最长 50 个字符,否则按照句点分割. 
%msg :日志消息 
%n :换行符

三、指定日志输出级别

logging:
  level:
    # 指定日志的级别,这里指的是 com.xiaomaomao 包下面的日志级别是 trace ,其它的依旧使用 springboot 默认的 info
    com.xiaomaomao: trace

四、指定配置(自定义配置)

进入 Springboot 官网---->找到你项目中的 Springboot 对应的版本---->Reference Document

找到日志相关的章节---->Custom Log Configuration(这里面有私人订制日志的相关介绍)

给类路径下放上每个日志框架自己的配置文件即可,由于 Springboot 使用的日志实现是 Logback,我们可以找到 Logback 日志实现对应的配置文件

 

关于 logback.xml 和 logback-spring.xml 配置文件的区别,查询了一些博客,以及培训班的视频,大意如下:

logback.xml:直接就被日志框架识别了,这个时候你就不能使用 Springboot 的 profile 功能 

logback-spring.xml:日志框架就不直接加载日志的配置项,由 SpringBoot 解析日志配置,可以使用 SpringBoot 的高级 Profile 功能 
但是我这里实际上测试的时候是两个配置文件都是支持的,不会存在报错的现象,可以正常的进行环境的切换( application.yaml 配置文件配置和 IDEA 命令行参数切换环境都支持).
application.yaml 中的配置
spring:
  profiles:
    active: sit

IDEA 参数配置(--spring.profiles.active=sit)

 

五、切换日志框架

我们知道 Springboot 默认使用的是 SLF4J + Logback 的方式来记录日志的,如果我们想切换为其它的日志形式,那么该怎么做呢?

1、切换 SLF4J + Log4j

进入官网:http://www.slf4j.org/---->点击 leagcy APIs---->找到 SLF4J + log4j 的图示

再看一下整个项目的依赖关系图

找到 pom.xml---->show dependences---->找到相关的日志依赖模块

通过上面两张图可以得出具体的步骤:

1、剔除 Springboot 使用的 Logback 的日志依赖

2、剔除项目中的 jcl、jul 日志依赖,并且引入对应的中间转换包

3、引入 slf4j-log412.jar 这个依赖,并且一定要剔除 log4j-over-slf4j 这个中间转换包,否则会 jar 包冲突

在 IDEA 依赖图中选中要排除的依赖---->exclude---->便可以排除了

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	// 排除 logback 的日志依赖
	<exclusions>
		<exclusion>
			<artifactId>logback-classic</artifactId>
			<groupId>ch.qos.logback</groupId>
		</exclusion>
		// 排除 log4j 的中间转换包防止 jar 包冲突
		<exclusion>
			<artifactId>log4j-over-slf4j</artifactId>
			<groupId>org.slf4j</groupId>
		</exclusion>
	</exclusions>
</dependency>
// 引入 slf4j-log4j12 的依赖
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.7</version>
</dependency>

 

2、切换 log4j2 的日志形式

https://docs.spring.io/spring-boot/docs/2.2.11.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

通过这张图我们可以发现,这里有两个场景启动器,一个是我们默认使用的 spring-boot-starter-logging,如果你想使用 log4j2 的日志形式,只需要排除 spring-boot-starter-logging 这个依赖,然后再引入 spring-boot-starter-log4j2 的依赖就可以.

<dependency> 
	<groupId>org.springframework.boot</groupId> 
	<artifactId>spring‐boot‐starter‐web</artifactId> 
	// 排除 spring‐boot‐starter‐logging
	<exclusions> 
			<exclusion> 
				<artifactId>spring‐boot‐starter‐logging</artifactId> 
				<groupId>org.springframework.boot</groupId> 
			</exclusion> 
		</exclusions> 
</dependency> 
// 引入 spring‐boot‐starter‐log4j2
<dependency> 
	<groupId>org.springframework.boot</groupId> 
	<artifactId>spring‐boot‐starter‐log4j2</artifactId> 
</dependency> 

  

 

原文地址:https://www.cnblogs.com/xiaomaomao/p/13946478.html