SpringBoot 日志

一:日志的作用

(1)定位和发现问题

💗通过日志,可以找到问题出现的原因和地方

(通过后端的日志,可以知道报错的原因,比如空指针异常等等)

(2)系统监控

💗我们可以通过日志记录这个系统的运行状态,每⼀个方法的响应时间、响应状态等,对数据进行分析,设置不同的规则,超过阈值时进行报警

(比如统计日志中关键字的数量,并在关键字数量达到⼀定条件时报警,这也是日志的常见需求)

(3)数据采集

💗数据采集是⼀个较大的范围,采集的数据可以作用在很多方面,比如数据统计,推荐排序等


①数据统计:统计页面的浏览量(PV),访客量(UV),点击量等,根据这些数据进行数据分析, 优化公司运营策略


②推荐排序:目前推荐排序应用在各个领域, 我们经常接触的各行各业很多也都涉及推荐排序, 比如购物、广告、新闻等等;数据采集是推荐排序工作中必须做的⼀环, 系统通过日志记录用户的浏览历史, 停留时长等,算法人员通过分析这些数据,训练模型,给用户做推荐

(4)日志审计

💗网络安全是现在大家非常关注的问题,系统安全也成了项目的一个很重要的环节,因此,安全审计也是系统中非常重要的部分;通过系统日志分析,可以判断⼀些非法攻击、非法调用以及系统处理过程中的安全隐患


二:日志的使用

(1)观察默认的日志

(2)打印日志的步骤

①获取日志对象


②使用日志对象输出要打印的内容

(3)日志对象

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


**💗日志类:**Logger

(Logger对象是属于org.slf4j包下的,不要导错了)


**💗获取日志对象需要使用日志工厂类:**LoggerFactory


**💗获取日志对象的方法:**getLogger

(该方法需要传递⼀个参数,用来标识这个日志的名称,一般名称我们会写类名,这样可以更清晰的知道是哪个类输出的日志;当有问题时, 可以更方便直观的定位到问题类)


复制代码
//比如
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);

(4)使用日志对象打印日志

💗输出日志的方法:info()


java 复制代码
package com.example.demo.Controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;

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

    //@PostConstruct表示属性注入完毕后就会执行print方法
    @PostConstruct
    public void print(){
       logger.info("---这是一个日志内容---");
    }
}

三:日志框架介绍

(1)整体框架图

💗SLF4J不是一个真正的日志实现,而是日志门面,真正的日志是由log4j I/2或logback实现


💚总的来说,SLF4J是⼀个抽象层,是对日志框架制定的⼀种规范、标准、接口,只是一个假象罢了,真正的操作由log4j I/2或logback实现


(2)门面模式(外观模式)

1.典型应用

💛SLF4J是门面模式的典型应用,但不仅仅使用了门面模式

2.门面模式的定义

💞门面模式(Facade Pattern)又称为外观模式, 提供了一个统一的接口,用来访问子系统中的⼀群接口;其主要特征是定义了⼀个高层接口,让子系统更容易使用


2.门面模式的角色

①外观角色(Facade):也称门面角色,系统对外的统一接口


②子系统角色(SubSystem):可以同时有⼀个或多个SubSystem;每个SubSytem都不是一个单独的类,而是⼀个类的集合;SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另⼀个客户端而已

(即Facade对SubSystem透明)


③举例:比如去医院看病,可能要去挂号、门诊、化验、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待⼈员来处理,就很方便

(3)门面模式的实现

1.实现场景

🌟场景:一般我们回家时会开各个屋的灯,离开家时也会关闭各个屋的灯


💞如果在家里设置⼀个总开关,来控制整个屋的灯就会很方便

2.门面模式的实现

①先创建一个facade包,代码的实现全部放在里面


②创建一个灯的接口,取名为Light,里面有开灯和关灯两个方法,其他类继承接口重写即可

java 复制代码
package com.example.demo.facade;

public interface Light {
    void on();
    void off();
}

③创建一个走廊灯,取名为HallLight,使其实现Light接口

java 复制代码
package com.example.demo.facade;

public class HallLight implements Light {
    @Override
    public void on() {
        System.out.println("打开走廊灯");
    }

    @Override
    public void off() {
        System.out.println("关闭走廊灯");
    }
}

④创建一个客厅灯,取名为LivingLight,使其实现Light接口

java 复制代码
package com.example.demo.facade;

public class LivingLight implements Light{
    @Override
    public void on() {
        System.out.println("打开客厅灯");
    }

    @Override
    public void off() {
        System.out.println("关闭客厅灯");
    }
}

创建一个餐厅灯,取名为DinnigLight,使其实现Light接口

java 复制代码
package com.example.demo.facade;

public class DiningLight implements Light {
    public void on(){
        System.out.println("打开餐厅灯");
    }
    public void off(){
        System.out.println("关闭餐厅灯");
    }
}

⑥创建一个总开关FacadePattern,在其里面实现所有灯的开和关

(SLF4J就相当于这个总开关FacadePattern)

java 复制代码
package com.example.demo.facade;

//这是一个总开关
public class FacadePattern {
    //实现一键开所有灯的功能
    public void LightOn(){
        HallLight hallLight = new HallLight();
        hallLight.on();
        LivingLight livingLight = new LivingLight();
        livingLight.on();
        DiningLight diningLight = new DiningLight();
        diningLight.on();
    }

    //实现一键关所有灯的功能
    public void LightOff(){
        HallLight hallLight = new HallLight();
        hallLight.off();
        LivingLight livingLight = new LivingLight();
        livingLight.off();
        DiningLight diningLight = new DiningLight();
        diningLight.off();
    }
}

⑦实现一个Main方法,在里面实现一键式开灯和关灯

java 复制代码
package com.example.demo.facade;

public class Main {
    public static void main(String[] args) {
        FacadePattern facadePattern = new FacadePattern();
        facadePattern.LightOn();
        facadePattern.LightOff();
    }
}

(4)门面模式的优点

①减少了系统的相互依赖,实现了客户端与子系统的耦合关系, 这使得子系统的变化不会影响到调用它的客户端


②提高了灵活性;简化了客户端对子系统的使用难度,客户端⽆需关系子系统的具体实现方式,而只需要和门面对象交互即可


③提高了安全性;可以灵活设定访问权,不在门面对象中开通方法, 就无法访问

四:日志级别

(1)日志级别的分类

💗由高到低分别为:FATAL➜ERROR➜WARN➜INFO➜DEBUG➜TRACE


(2)日志级别的解析

①FATAL:致命信息;表示需要立即被处理的系统级错误


②ERROR:错误信息;级别较高的错误信息日志,但仍然不影响系统的继续运行


③WARN:警告信息;不影响使用,但需要注意的问题


④INFO:普通信息;用于记录应用程序正常运行时的⼀些信息,例如系统启动完成、请求处理完成等


⑤DEBUG:调试信息;需要调试时候的关键信息打印


⑥TRACE:追踪信息,比DEBUG更细粒度的信息事件

(除非有特殊用意,否则请使用DEBUG级别替代)

(3)日志级别的使用

1.方法

💞****针对这些级别,Logger对象分别提供了对应的方法,来输出日志


🌟关于FATAL级别的日志:

(1)SpringBoot默认的日志框架是Logback,Logback没有FATAL级别,它被映射到ERROR

(2)出现FATAL级别的日志,表示服务已经出现了某种程度的不可用, 需要需要系统管理员紧急介入处理,通常情况下, ⼀个进程生命周期中应该最多只有⼀次FATAL记录


日志级别 方法
ERROR logger.error()
WARN logger.warn()
INFO logger.info()
DEBUG logger.debug()
TRACE logger.trace()
2.默认日志级别的配置

💜日志的输出级别默认是info级别, 所以只会打印大于等于此级别的日志,也就是info, warn和error

(如果需要输出其余日志,需要进行日志级别的配置)


java 复制代码
package com.example.demo.Controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;

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

    //@PostConstruct表示属性注入完毕后就会执行print方法
    @PostConstruct
    public void print(){
       logger.trace("这是一个trace级别的日志");
       logger.debug("这是一个debug级别的日志");
       logger.info("这是一个info级别的日志");
       logger.warn("这是一个warn级别的日志");
        logger.error("这是一个error级别的日志");
    }
}

五:日志配置

(1)配置日志级别

**💗logging.level:**配置日志级别

(level后面可以接指定的目录;表示指定目录下的日志都是该级别)


💙****root表示根目录;即所有的目录都设为该级别

(2)配置日志持久化

1.概念

💗即保存日志的意思;因为目前我们的日志都是输出在控制台上的,然而在线上环境中, 我们需要把日志保存下来, 以便出现问题之后追溯问题

2.方式一

**💗logging.file.name:**配置日志文件名


🌟value可以是路径/文件名

💚(如果不指定路径,就默认存在当前目录下)

💚(路径或者目录如果不存在则会自动创建)

3.方式二

**💗logging.file.path:**配置日志的存储目录


🌟value只能是路径,文件名默认是spring.log

4.两种方式注意事项

🌟logging.file.name和logging.file.path如果同时配置的话,以logging.file.name为准

(3)配置日志文件分割

1.为什么要分割

🌟如果日志都放在一个文件中,随着项目的运行,日志文件会越来越大,需要对日志文件进行分割


💗如果我们不配置,日志框架会自动配置;默认日志文件超过10M就进行分割

**2.**日志分割后的文件名格式

💗logging.logback.rollingpolicy.file-name-pattern**:日志分割后的文件名格式**


3.日志文件超过多少自动分割

💗****logging.logback.rollingpolicy.max-file-size:日志文件超过多少自动分割


4.配置文件

①Properties配置


②yml配置


③注意事项

(1)日志超过多少就分割,此处没有明确的标准,每个公司也都不一样

(2)分割后的日志⽂件名为: 日志名.日期.索引

(4)配置日志格式

1.控制台日志格式

**💗logging.pattern.console:**配置控制台日志格式


2.日志文件的日志格式

**💗logging.pattern.file:**配置日志文件的日志格式


3.配置项说明

**①%clr(表达式){颜色}:**设置控制台输入日志的颜色


**②%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}:**日期和时间;以毫秒为单位


**③%5p:**显示日志级别ERROR,MARN,INFO,DEBUG,TRACE


④各式各样的百分号字母:


⑤填充与截取:

4.常见问题-无法显示颜色

🌟解决办法:需要配置,让IDEA支持控制台颜色显示


①打开启动配置


②添加VM options


③添加这句:-Dspring.output.ansi.enabled=ALWAYS


④设置完重启启动程序即可

六:更简单的日志输出

(1)方法

🌟两个步骤


(1)添加lombok框架支持

(2)使用@Slf4j注解输出日志

(2)lombok依赖

java 复制代码
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

(3)输出日志

💚lombok提供的@Slf4j会帮我们提供⼀个日志对象log,我们直接使用就可以


java 复制代码
package com.example.demo.Controller;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;

@Slf4j
@RestController
public class LoggerController {

    //@PostConstruct表示属性注入完毕后就会执行print方法
    @PostConstruct
    public void print(){
       log.trace("这是一个trace级别的日志");
       log.debug("这是一个debug级别的日志");
       log.info("这是一个info级别的日志");
       log.warn("这是一个warn级别的日志");
       log.error("这是一个error级别的日志");
    }
}
相关推荐
bobz9656 分钟前
ovs patch port 对比 veth pair
后端
Asthenia041216 分钟前
Java受检异常与非受检异常分析
后端
uhakadotcom30 分钟前
快速开始使用 n8n
后端·面试·github
JavaGuide37 分钟前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9651 小时前
qemu 网络使用基础
后端
Asthenia04121 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04121 小时前
Spring 启动流程:比喻表达
后端
Asthenia04122 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
致心2 小时前
记一次debian安装mariadb(带有迁移数据)
后端