【Spring】SpringBoot日志

news2025/1/16 1:05:52

SpringBoot日志

  • 日志概述
  • 日志使用
  • 打印日志
    • 获取日志对象
    • 使用日志对象打印日志
    • 日志框架介绍
      • 门面模式
      • SLF4J框架介绍(simple logging facade for java)
    • 日志格式说明
    • 日志级别
      • 日志级别的分类
      • 日志级别的使用
    • 日志配置
      • 配置日志级别
      • 日志持久化
        • 配置日志文件的路径和文件名
        • 配置日志文件的保存路径
      • 配置日志文件分割
  • 更简单的日志输出

日志概述

  1. 为什么要学习⽇志
    ⽇志对我们来说并不陌⽣, 从JavaSE部分, 我们就在使⽤ System.out.print 来打印⽇志了. 通过打印⽇志来发现和定位问题, 或者根据⽇志来分析程序的运⾏过程.在Spring的学习中, 也经常根据控制台的⽇志来分析和定位问题.

随着项⽬的复杂度提升, 我们对⽇志的打印也有了更⾼的需求, ⽽不仅仅是定位排查问题.
⽐如需要记录⼀些⽤⼾的操作记录(⼀些审计公司会要求), 也可能需要使⽤⽇志来记录⽤⼾的⼀些喜好,把⽇志持久化, 后续进⾏数据分析等. 但是 System.out.print 不能很好的满⾜我们的需求, 我们就需要使⽤⼀些专⻔⽇志框架(专业的事情交给专业的⼈去做)

日志使用

Spring Boot 项⽬在启动的时候默认就有⽇志输出,如下图所⽰:
在这里插入图片描述
我们可以看到SpringBoot答应出来的日志却少了很多信息

SpringBoot打印出来的日志有 日志时间 日志级别 线程 打印日志的位置 日志信息等

springboot内置了日志框架slf4j,我们可以直接在程序中调用slf4j来输出日志

打印日志

打印日志的步骤:

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

获取日志对象

在程序中获取⽇志对象需要使⽤⽇志⼯⼚ LoggerFactory,如下代码所⽰:

public class LogController {
    private static Logger logger = LoggerFactory.getLogger(LogController.class);
}

LoggerFactory.getLogger需要传递一个参数,标识这个日志的名称,这样可以更清晰的直到是哪个类输出的日志,当有问题时,可以更方便直观的定位到问题类

使用日志对象打印日志

日志对象的打印方法有很多种,我们可以先使用info()方法来输出日志

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogController {
    private static Logger logger = LoggerFactory.getLogger(LogController.class);

    @RequestMapping("/log")
    public String logger(){
        logger.info("这是一段日志");
        return "打印日志";
    }
}

在这里插入图片描述

日志框架介绍

在这里插入图片描述

SLF4J不同于其他日志框架,他不是一个真正的日志实现,而是一个抽象层,对日志框架指定的一种规范,标准,接口,所有SLF4J并不能独立使用,需要和具体的日志框架配合使用

门面模式

SLF4J是门面模式的典型应用

门面模式(Facade Pattern)是一种软件设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。这个模式通过创建一个高层接口,简化了客户端与子系统之间的交互,从而降低了系统之间的耦合度。

通常情况下,一个系统由多个子系统组成,每个子系统都有自己的接口和功能。而客户端需要与这些子系统进行交互,这样可能会导致客户端代码变得复杂,并且对系统的变化比较敏感。门面模式的出现正是为了解决这个问题。

通过门面模式,客户端只需要和门面对象交互,而门面对象负责将请求委派给相应的子系统进行处理。这样一来,客户端就不需要了解子系统的具体实现细节,从而降低了客户端和子系统之间的耦合度,同时也方便了对子系统的修改和维护。

总的来说,门面模式可以帮助简化复杂系统的接口,提高系统的灵活性和可维护性,同时也能够隐藏系统的复杂性,使客户端更加容易使用。

在这里插入图片描述
门面模式主要包含两种角色

外观角色,也成为门面角色,系统对外的统一接口
子系统角色,可以同时有一个或多个SubSystem,每个SubSystem都不是一个单独的类,而是一个类的集合,SubSystem并不知道Facade的存在,

SLF4J框架介绍(simple logging facade for java)

SLF4J就是其他日志框架的门面,SLF4J可以理解为是提供日志服务的统一API接口,并不涉及到具体的日志逻辑实现

不引入日志门面

常见的日志框架有log4j ,logback等 如果一个项目已经使用log4j,而你依赖的另一个类库,假如依赖另一个日志框架logback,那么就需要吧logback也加进去

存在问题

  1. 不同的日志框架的API接口和配置文件不同,如果多个日志框架并存,那么不得不维护多套配置文件(这里的配置文件指的是用户自定义的配置文件)
  2. 如果要更换日志框架,应用程序将不得不修改代码,并且修改过程中可能会存在一些代码冲突
  3. 如果引入的第三方框架,使用了多套,那就不得不维护多套配置

引入日志门面

引入日志门面框架后,应用程序和日志框架之间有了统一 的API接口,此时应用程序只需要维护一套日志文件配置,且当底层实现框架改变时,也不需要更改应用程序代码

日志格式说明

在这里插入图片描述
从上图可以看到,⽇志输出内容元素具体如下:

  1. 时间⽇期:精确到毫秒
  2. ⽇志级别:ERROR, WARN, INFO, DEBUG 或TRACE
  3. 进程ID
  4. 线程名
  5. Logger名(通常使⽤源代码的类名)
  6. ⽇志内容

日志级别

⽇志级别代表着⽇志信息对应问题的严重性, 为了更快的筛选符合⽬标的⽇志信息

日志级别的分类

在Spring框架中,日志级别通常遵循通用的日志级别标准,比如 SLF4J 或 Logback 中定义的日志级别。Spring框架本身并没有定义自己的日志级别,而是使用这些通用的标准。以下是常见的日志级别:

TRACE:提供非常详细的日志信息,通常用于调试,跟踪程序执行过程中的细节。

DEBUG:用于输出调试信息,用于辅助定位问题和调试程序。

INFO:提供一般性的运行时信息,表明应用程序正在运行。

WARN:表示潜在的问题,不会导致应用程序停止运行,但可能需要引起注意。

ERROR:用于指出虽然发生了错误,但仍然允许程序继续运行。

FATAL:指出严重的错误,可能导致应用程序退出。

在配置Spring应用程序的日志级别时,可以通过配置文件(比如logback.xml或log4j2.xml)或者通过代码来设置。一般来说,通过配置文件进行设置更为灵活,可以根据不同的包或类设置不同的日志级别。在Spring中,也可以通过Spring Boot的application.properties或application.yml文件来配置日志级别。

总的来说,通过合理设置日志级别,可以帮助开发人员了解应用程序的运行情况,快速定位问题,提高系统的可维护性和稳定性。

日志级别的使用

⽇志级别是开发⼈员⾃⼰设置的. 开发⼈员根据⾃⼰的理解来判断该信息的重要程度

针对这些级别, Logger 对象分别提供了对应的⽅法, 来输出⽇志

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogController {
    private static Logger logger = LoggerFactory.getLogger(LogController.class);

    @RequestMapping("/log")
    public String logger(){
        logger.trace("这是一段trace日志");
        logger.debug("这是一段debug日志");
        logger.info("这是一段info日志");
        logger.warn("这是一段warn日志");
        logger.error("这是一段error日志");
        return "打印日志";
    }
}

SpringBoot 默认的⽇志框架是Logback, Logback没有 FATAL 级别, 它被映射到 ERROR .
出现fatal⽇志,表⽰服务已经出现了某种程度的不可⽤, 需要需要系统管理员紧急介⼊处理. 通常情况下, ⼀个进程⽣命周期中应该最多只有⼀次FATAL记录.
在这里插入图片描述
结果发现只打印了info,warn和error级别的日志

这与日志级别的配置有关,日志的输出默认级别时info级别 ,所以只会打印大于等于此级别的日志,也就是info,warn和error

日志配置

上述是⽇志的使⽤, ⽇志框架⽀持我们更灵活的输出⽇志, 包括内容, 格式等

配置日志级别

我们可以在配置文件application.yml中配置logging.level配置项即可
在这里插入图片描述
在这里插入图片描述
我们可以发现此时就可以打印出Debug级别的日志了

日志持久化

以上的⽇志都是输出在控制台上的, 然⽽在线上环境中, 我们需要把⽇志保存下来, 以便出现问题之后追溯问题. 把⽇志保存下来就叫持久化.

日志持久化的两种方式

  1. 配置日志文件名
  2. 配置日志的存储目录
配置日志文件的路径和文件名

yml配置文件配置
设置文件的文件名
在这里插入图片描述

在这里插入图片描述

配置日志文件的保存路径

这种方式只能设置日志的路径,文件名为固定的spring.log

在这里插入图片描述
在这里插入图片描述

注意:
logging.file.name 和 logging.file.path 两个都配置的情况下, 只⽣效其⼀, 以logging.file.name 为准

配置日志文件分割

如果我们的⽇志都放在⼀个⽂件中, 随着项⽬的运⾏, ⽇志⽂件会越来越⼤, 需要对⽇志⽂件进⾏分割

当然, ⽇志框架也帮我们考虑到了这⼀点, 所以如果不进⾏配置, 就⾛⾃动配置
默认⽇志⽂件超过10M就进⾏分割

配置项说明默认值
logging.logback.rollingpolicy.file-name-pattern⽇志分割后的⽂件名格式${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.max-file-size⽇志⽂件超过这个⼤⼩就⾃动分割10MB

配置文件分割

yml配置

logging:
  logback:
    rollingpolicy:
      max-file-size: 1KB
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
  1. ⽇志⽂件超过1KB就分割(设置1KB是为了更好展⽰. 企业开发通常设置为200M, 500M等, 此处没
    有明确标准)
  2. 分割后的⽇志⽂件名为: ⽇志名.⽇期.索引

在这里插入图片描述

更简单的日志输出

每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐, 且每个类都添加⼀遍, lombok给我们提供了⼀种更简单的⽅式.

  1. 添加 lombok 框架⽀持
  2. 使⽤ @slf4j 注解输出⽇志。
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class LogController {
//    private static Logger logger = LoggerFactory.getLogger(LogController.class);

    @RequestMapping("/log")
    public String logger(){
    	//此时对象名称为固定的log
        log.trace("这是一段trace日志");
        log.debug("这是一段debug日志");
        log.info("这是一段info日志");
        log.warn("这是一段warn日志");
        log.error("这是一段error日志");
        return "打印日志";
    }
}

在这里插入图片描述
我们可以发现 这个注解的生命周期只存在于源代码阶段
在这里插入图片描述
**代码在经过编译之后 自动为我们生成了Logger对象 **

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1197728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7安装linux版本的mysql

1.下载linux版本的mysql 进入mysql官网,点击社区版本下载: https://dev.mysql.com/downloads/mysql/ 选择版本,可以跟着我下面这个图进行选择,选择红帽版本的既可,都是linux版本的。 2.上传解压linux版本的mysql安装包…

C++初阶--类与对象(3)(图解)

文章目录 再谈构造函数初始化列表隐式类型转换explicit关键字 static成员友元类内部类匿名对象拷贝函数时的一些优化 再谈构造函数 在我们之前的构造函数中,编译器会通过构造函数,对对象中各个成员给出一个适合的初始值,但这并不能称之为初始…

思维模型 超限效应

本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。物极必反。 1 超限效应的应用 1.1 教育中的超限效应 一位老师在课堂上批评了一位学生,这位学生可能会因为老师的批评而感到沮丧和失落。如果老师在接下来的课程中继续批评这位…

数据结构与算法—搞懂队列

csdn专栏:数据结构与算法 前言 栈和队列是一对紧密相关的数据结构。之前已经介绍过栈(它遵循后进先出的原则),栈的机制相对简单,就像你进入一个狭窄的山洞,山洞只有一个出入口,因此你只能按照后…

【原创分享】Mentor PADS将PCB封装直接添加到PCB的教程

一般,批量添加封装到PCB板上有以下方法: 第一步:点击菜单栏“ECO模式--添加元器件”如图,点击以后弹出如图界面。 1)元件类型 PCB封装必须得添加完元件类型,才能通过ECO模式添加到PCB界面里面&#xff0c…

[Linux打怪升级之路]-信号的保存和递达

前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、信号的保…

红黑树-RBTree

目录 1. 红黑树的概念2. 红黑树的性质3. 结点的定义4. 结点的插入5. 整体代码 1. 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式…

基于51单片机RFID射频门禁刷卡系统设计

**单片机设计介绍, 基于51单片机RFID射频门禁刷卡系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序程序 六、 文章目录 一 概要 基于51单片机RFID射频门禁刷卡系统,是一种将单片机技术和射频标识技术应用于门禁控制系统的…

34 Feign最佳实践

2.4.2.抽取方式 将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。 例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包…

一篇文章真正讲懂模型评估指标(准确率,召回率,精确率,roc曲线,AUC值)

背景: 最近在做一些数据分析的比赛的时候遇到了一些头疼的问题,就是我们如何评估一个模型的好坏呢? 准确率,召回率,精确率,roc曲线,roc值等等,但是模型评估的时候用哪个指标呢&…

[工业自动化-12]:西门子S7-15xxx编程 - PLC从站 - ET200 SP系列详解

目录 一、概述 1.1 概述 二、系统组成 2.1 概述 2.2 与主站的通信接口模块 2.3 总线适配器 2.4 基座单元 2.5 电子模块 2.6 服务器模块 一、概述 1.1 概述 PLC ET200 SP 是西门子(Siemens)公司生产的一款模块化可编程逻辑控制器(PL…

初探SVG

SVG,可缩放矢量图形(Scalable Vector Graphics)。使用XML格式定义图像。SVG有以下优点:1)可被非常多的工具读取和修改;2)比JPEG和GIF尺寸更小,可压缩性更强;3&#xff09…

科力雷达Lidar使用指南

科力2D Lidar使用指南 作者: Herman Ye Galbot Auromix 版本: V1.0 测试环境: Ubuntu20.04(x86) PC 以及 Ubuntu20.04(Arm) Nvidia Orin 更新日期: 2023/11/11 注1: 本文内容中的硬件由 Galbot 提供支持。 注2&#x…

物联网AI MicroPython学习之语法uzlib解压缩

学物联网,来万物简单IoT物联网!! uzlib 介绍 uzlib 模块解压缩用DEFLATE算法压缩的二进制数据 (通常在zlib库和gzip存档器中使用),压缩功能尚未实现。 注意:解压缩前,应检查模块内可…

C语言——个位数为 6 且能被 3 整除但不能被 5 整除的三位自然数共有多少个,分别是哪些?

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i,j0;for(i100;i<1000;i) {if(i%106&&i%30&&i%5!0){printf("%6d",i); j;}}printf("\n一共%d个\n",j);return 0; } %6d起到美化输出格式的作用&#xff…

(一)QML加载离线地图+标记坐标点

1、实现效果 加载离线地图瓦片、鼠标拖拽、滚轮缩放在地图上固定坐标位置标注地名 &#xff08;一&#xff09;QML加载离线地图标记坐标点&#xff1a;MiniMap-mini 2、实现方法 2.1、使用工具下载离线地图 不废话&#xff0c;直接搬别人的砖&#xff0c;曰&#xff1a;他山…

jbase实现申明式事务

对有反射的语言&#xff0c;申明式事务肯定不可少。没必要没个人都try&#xff0c;catch写事务&#xff0c;写的不好的话还经常容易锁表&#xff0c;为此给框架引入申明式事务。申明式既字面意思&#xff0c;在需要事务的方法前面加一个申明&#xff0c;那么框架保证事务。 首…

比亚迪推动启动电池无铅化 车主有福了

时间过得很快&#xff0c;又到了立冬&#xff0c;意味着冬季已经开始。此时的北方已经下起了大雪&#xff0c;即便是艳阳高照的粤北山区&#xff0c;早晚也出现了较大的温差。笔者不禁想起此前做二手车时期的尴尬场面——三年以上的老车&#xff0c;尤其是没有更换过启动电池的…

38 路由的过滤器配置

3.3.断言工厂 我们在配置文件中写的断言规则只是字符串&#xff0c;这些字符串会被Predicate Factory读取并处理&#xff0c;转变为路由判断的条件 例如Path/user/**是按照路径匹配&#xff0c;这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoute…

Python实现局部二进制算法(LBP)

1.介绍 局部二进制算法是一种用于获取图像纹理的算法。这算法可以应用于人脸识别、纹理分类、工业检测、遥感图像分析、动态纹理识别等领域。 2.示例 """ 局部二进制算法&#xff0c;计算图像纹理特征 """ import cv2 import numpy as np imp…