9. Spring Boot 日志文件

本篇文章源码位置延续上个章节:SpringBoot_demo

本篇文章内容源码位于上述地址的com/chenshu/springboot_demo/logging包下

1. 日志的作用

发现和定位问题: 日志是程序的重要组成部分,它在系统、程序出现错误或异常时提供诊断和解决问题的线索,从而定位问题;只有定位到了问题的位置,程序员才可以对症下药,从而解决问题。

除了发现和定位问题,我们还可以通过日志实现其他功能,比如:

  • 记录用户登录日志,用于分析用户是正常登录还是恶意破解登录;
  • 记录系统的操作日志,方便回复数据和定位操作人;

2. Spring Boot 日志概述

其实所谓日志我们也不是第一次接触了,在Spring Boot这个框架中集成了日志框架,我们在启动项目时在console中所打印的信息其实就是日志。

并且每一条日志记录都默认包含了这些信息:日志打印时间、日志打印级别、线程ID、线程名称、打印日志的类名、日志信息

以上内容就是Spring Boot 输出的控制台日志信息。

通过上述日志信息我们能引出下面几个问题:

  1. Spring Boot是因为内置了日志框架才能打印日志信息的,那么Spring Boot 内置的日志框架是什么呢?
  2. 打印日志是需要开销的,程序在不同的环境需要打印不同级别的日志信息,如何通过日志的级别来筛选所需打印日志的内容呢?
  3. 除了发现和定位问题,我们还想通过日志实现其他功能,那么开发者如何在程序中自定义打印日志呢?
  4. 开发环境中我们可以根据控制台打印的日志信息排查问题,那如果是生产环境总不能24小时盯着控制台信息找问题吧,这时候我们就要讲日志信息持久化保存,那么如何将日志信息持久化保存呢?

我们接下来要讲的内容就是针对上述问题。

3. Spring Boot 的内置日志框架【了解】

Spring Boot中内置的日志门面是SLF4J,而具体的日志实现是logback,日志门面是什么?日志实现又是什么?下面给大家简单说说。

3.1 门面模式

门面模式的核心为: 外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。

解释: 其实门面模式就相当于给各式各样的实现封装了一层统一的外观,对于用户来说不用关心市面上提供的各种各样的具体实现的api是什么,只需要通过门面所提供的统一的api来使用。

3.2 日志实现

市面上有许多日志实现,如:

  • Java原生的JUL(Java Util Logging)
  • log4j 1/2
  • logback

不同的日志实现,它们的api写法都有所不同,但凡你想去更改一种日志实现,都需要去更改每一处日志代码。

3.3 日志门面(Logging Facade)

为了解决上述问题,引入了日志门面,而SLF4j就是一种日志门面,通过SLF4J,我们可以随意换另外一个日志框架,应用程序不需要修改任意一行代码,就可以直接上线。

门面模式下的用户视角图示:

4. 自定义日志打印

自定义打印日志的步骤大概分为下面两步:

  • 在程序中得到日志对象;
  • 使用日志相关语法输出要打印的内容;

4.1 得到日志对象

由于Spring Boot中内置的是slf4j的框架,这里我们要选择用org.slf4j包下的Logger接口:

使用LoggerFactory中的getLogger()方法,需要传一个参数来指定打印日志的类:

java 复制代码
private static Logger log = LoggerFactory.getLogger(TestController.class);

4.2 通过日志对象打印信息

LoggingController里创建一个日志的测试方法,通过日志对象来调用方法,方法名称代表了日志级别,日志级别及使用会在后面说到。

这里我们使用info方法来测试:

java 复制代码
@RestController
public class LoggingController {
    private static Logger log = LoggerFactory.getLogger(LoggingController.class);

    @RequestMapping("loggingtest1")
    public void loggingTest1() {
        log.info("This is my first Spring Boot Log.");
    }
}

成功打印出下面日志信息:

lua 复制代码
2024-04-07 21:23:34.681  INFO 14515 --- [nio-8001-exec-1] c.c.s.config.controller.TestController   : This is my first Spring Boot Log.

5. 日志持久化

a) 通过日志的保存名称持久化

在application.yml中通过配置日志的名称完成持久化:

yaml 复制代码
# 日志的保存名称
logging:
  file:
    name: logging_demo.log

只设置名称会将日志默认保存在工作目录下:

点开查看一下:

还可以设置在指定路径下:

yaml 复制代码
logging:
  file:
    name: /Users/chenshu/Documents/logging/logging_demo.log

b) 通过日志的保存目录持久化

在application.yml中通过配置日志的名称完成持久化:

yaml 复制代码
# 日志的保存路径
logging:
  file:
    path: /Users/chenshu/Documents/logging

这样的设置会将日志保存在指定的路径下:

特性:

  1. 日志不会随着项目重新启动而去覆盖,会一直追加
  2. 当日志比较大的时候,会自动分割成多个文件,名称为原文件名+日期+.gz

6. 日志级别

不同的开发环境需要不同的日志级别

  • 测试环境下,我们不怎么考虑系统的开销,而是想要看到更多的日志信息,这时候我们就可以用开销来换取更多日志信息;
  • 开发环境下,我们也不怎么需要考虑系统的开销,但又想过滤掉一些不怎么需要的信息,以免影响查看日志;
  • 生产环境下,产品是要交付给用户进行使用的,使用的时候需要更多的考虑系统的开销,这时我们就可以只筛选一些重要的日志信息来节省开销;

6.1 六种日志级别

日志级别从低到高分别为:trace、debug、info、warn、error、fatal

  • trace: 追溯的意思,级别最低;
  • debug:需要调试时候的关键信息打印;
  • info:普通的打印信息(默认级别);
  • warn:警告,不影响程序运行,但需要注意的问题;
  • error:错误信息,级别较高的错误日志信息;
  • fatal:致命的,因为代码异常导致程序退出执行的事件;

由于fatal只会打印代码异常导致程序退出执行的事件,所以Logger对象提供了除了fatal事件的对应api:

java 复制代码
@RequestMapping("loggingtest2")
public void loggingTest2() {
    //追溯
    log.trace("log level: trace");
    //调试
    log.debug("log level: debug");
    //信息
    log.info("log level: info");
    //警告
    log.warn("log level: warn");
    //错误
    log.error("log level: error");
}

访问对应路由后,发现控制台只打印了info、warn、error的日志:

perl 复制代码
2024-04-07 23:22:21.124  INFO 14925 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: info
2024-04-07 23:22:21.124  WARN 14925 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: warn
2024-04-07 23:22:21.124 ERROR 14925 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: error

这是因为Spring Boot的日志级别默认是info,因此只会显示trace及以上的信息,接下来我来演示一下如何在不同环境的配置文件中设置不同的日志默认级别。

6.2 设置日志级别

日志级别的配置只需要在配置文件中设置"logging.level"配置项即可,我在前面配置的基础上进行修改:

yaml 复制代码
logging:
  file:
    path: /Users/chenshu/Documents/logging
  level:
    root: debug

上面的root表示的是根路径,也就是所有信息的级别都为debug

重新访问路由方法后,打印了下面信息,证明我们确实把默认级别设置为debug

yaml 复制代码
2024-04-07 23:56:38.246 DEBUG 15035 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: debug
2024-04-07 23:56:38.246  INFO 15035 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: info
2024-04-07 23:56:38.246  WARN 15035 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: warn
2024-04-07 23:56:38.246 ERROR 15035 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: error

上面那样配置会打印所有类中的debug及以上级别的日志信息,看起来非常眼花缭乱:


更精细化的日志级别设置

除了root根路径级别的设置,我们还可以精细化到自己的某个包中的级别,像下面这样,将com/chenshu/springboot_demo包下的类级别设置为debug,其他的类中的信息全都设置为warn:

yaml 复制代码
logging:
  file:
    path: /Users/chenshu/Documents/logging
  level:
    root: debug
    com:
      chenshu:
        springboot_demo: warn

这样的一番操作,相当于给com/chenshu/springboot_demo包下的类开了一个白名单,原先的一堆系统的日志信息都被过滤掉了,只剩下了我需要的重要日志信息:

yaml 复制代码
2024-04-08 00:07:01.232  INFO 15095 --- [           main] c.c.s.SpringBootDemoApplication          : Starting SpringBootDemoApplication using Java 1.8.0_381 on chenshudeAir with PID 15095 (/Users/chenshu/Code/classcode_java/blog-demo/SpringBoot_demo/target/classes started by chenshu in /Users/chenshu/Code/classcode_java/blog-demo/SpringBoot_demo)
2024-04-08 00:07:01.234 DEBUG 15095 --- [           main] c.c.s.SpringBootDemoApplication          : Running with Spring Boot v2.7.6, Spring v5.3.24
2024-04-08 00:07:01.234  INFO 15095 --- [           main] c.c.s.SpringBootDemoApplication          : The following 1 profile is active: "dev"
2024-04-08 00:07:02.264  INFO 15095 --- [           main] c.c.s.SpringBootDemoApplication          : Started SpringBootDemoApplication in 1.353 seconds (JVM running for 1.892)
2024-04-08 00:07:23.780 DEBUG 15095 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: debug
2024-04-08 00:07:23.780  INFO 15095 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: info
2024-04-08 00:07:23.780  WARN 15095 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: warn
2024-04-08 00:07:23.780 ERROR 15095 --- [nio-8001-exec-1] c.c.s.logging.LoggingController          : log level: error

7. 练习

上篇文章讲过了多环境的配置文件的使用,结合本篇文章所学的日志级别的设置,模拟一下实际开发中的场景:

将测试环境、开发环境、生产环境的日志分别存储在同一个目录下但命名不同的三个文件中,并且设置测试环境中的日志级别为trace、开发环境中为debug、生产环境中为error

相关推荐
计算机学长felix9 分钟前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
Re.不晚12 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐18 分钟前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。21 分钟前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野28 分钟前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航30 分钟前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq04151 小时前
J2EE平台
java·java-ee
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
豪宇刘1 小时前
SpringBoot+Shiro权限管理
java·spring boot·spring