【Spring Boot】一篇文章让你学会使用和查看Spring Boot日志
🎬 那我掉的头发算什么:个人主页
🔥 个人专栏: 《javaSE》《数据结构》《数据库》《javaEE》
⛺️待到苦尽甘来日
引言
日志对我们来说并不陌生,从 JavaSE 部分,我们就在使用 System.out.print 来打印日志了。通过打印日志来发现和定位问题,或者根据日志来分析程序的运行过程。在 Spring 的学习中,也经常根据控制台的日志来分析和定位问题。随着项目的复杂度提升,我们对日志的打印也有了更高的需求,而不仅仅是定位排查问题。比如需要记录一些用户的操作记录 (一些审计公司会要求),也可能需要使用日志来记录用户的一些喜好,把日志持久化,后续进行数据分析等。但是 System.out.print 不能很好的满足我们的需求,我们就需要使用一些专门日志框架 (专业的事情交给专业的人去做)。
文章目录
日志的用途
通过前面的学习,我们知道日志主要是为了发现问题,分析问题,定位问题的,但除此之外,日志还有很多用途
1.系统监控
监控现在几乎是一个成熟系统的标配,我们可以通过日志记录这个系统的运行状态,每一个方法的响应时间,响应状态等,对数据进行分析,设置不同的规则,超过阈值时进行报警。比如统计日志中关键字的数量,并在关键字数量达到一定条件时报警,这也是日志的常见需求之一
2.数据采集
数据采集是一个比较大的范围,采集的数据可以作用在很多方面,比如数据统计,推荐排序等.
- ・数据统计:统计页面的浏览量 (PV), 访客量 (UV), 点击量等,根据这些数据进行数据分析,优化公司运营策略
- ・推荐排序:目前推荐排序应用在各个领域,我们经常接触的各行各业很多也都涉及推荐排序,比如购物,广告,新闻等领域。数据采集是推荐排序工作中必须做的一环,系统通过日志记录用户的浏览历史,停留时长等,算法人员通过分析这些数据,训练模型,给用户做推荐.
3.日志审计
随着互联网的发展,众多企业的关键业务越来越多的运行于网络之上。网络安全越来越受到大家的关注,系统安全也成为了项目中的一个重要环节,安全审计也是系统中非常重要的部分。国家的政策法规、行业标准等都明确对日志审计提出了要求。通过系统日志分析,可以判断一些非法攻击,非法调用,以及系统处理过程中的安全隐患.
打印日志
简单使用
在程序中获取日志对象需要用到日志工厂,具体代码:
privateLogger logger =LoggerFactory.getLogger(LogController.class);注意这里的logger需要导入的是org.slf4j包里面的。

packagecom.hbu.springlogdemo.Controller;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RequestMapping("/log")@RestControllerpublicclassLogController{privateLogger logger =LoggerFactory.getLogger(LogController.class);@RequestMapping("/print")publicvoidprint(){System.out.println("print一个日志康康"); logger.info("logger打印日志");}}
感觉自己打印的日志跟logger打印的日志相比确实太low了。。。
所以接下来咱们开始学习Logger打印日志的方法吧!
日志框架

SLF4J 不同于其他日志框架,它不是一个真正的日志实现,而是一个抽象层,对日志框架制定的一种规范,标准,接口。所有 SLF4J 并不能独立使用,需要和具体的日志框架配合使用。
门面模式***
SLF4J 是门面模式的典型应用 (但不仅仅使用了门面模式)。
门面模式定义:
门面模式(Facade Pattern)又称为外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用。

门面模式主要包含 2 种角色:
外观角色 (Facade): 也称门面角色,系统对外的统一接口.
子系统角色 (SubSystem): 可以同时有一个或多个 SubSystem. 每个 SubSytem 都不是一个单独的类,而是一个类的集合. SubSystem 并不知道 Facade 的存在,对于 SubSystem 而言,Facade 只是另一个客户端而已 (即 Facade 对 SubSystem 透明)
比方说咱们肯定是客户端,这个外观角色其实是中间人,在子系统角色眼里呢他也是一个客户端,咱们以此只能访问一个子系统角色,但是可以请这个中间人帮忙,一次性访问很多人。
典型应用场景:房间灯光总开关
子系统:
packagecom.hbu.springlogdemo.Facade;publicclassSubStreams{staticinterfaceLight{voidon();voidoff();}staticclassLivingLightimplementsLight{@Overridepublicvoidon(){System.out.println("打开客厅灯");}@Overridepublicvoidoff(){System.out.println("关闭客厅灯");}}staticclassBedLightimplementsLight{@Overridepublicvoidon(){System.out.println("打开卧室灯");}@Overridepublicvoidoff(){System.out.println("关闭卧室灯");}}staticclass diningLight implementsLight{@Overridepublicvoidon(){System.out.println("打开厨房灯");}@Overridepublicvoidoff(){System.out.println("关闭厨房灯");}}staticclassHallLightimplementsLight{@Overridepublicvoidon(){System.out.println("打开走廊灯");}@Overridepublicvoidoff(){System.out.println("关闭走廊灯");}}}总控:
packagecom.hbu.springlogdemo.Facade;publicclassFacade{privateSubStreams.LivingLight livingLight =newSubStreams.LivingLight();privateSubStreams.BedLight bedLight =newSubStreams.BedLight();privateSubStreams.diningLight diningLight =newSubStreams.diningLight();privateSubStreams.HallLight hallLight =newSubStreams.HallLight();voidon(){ livingLight.on(); bedLight.on(); diningLight.on(); hallLight.on();}voidoff(){ livingLight.off(); bedLight.off(); diningLight.off(); hallLight.off();}}主程序:
packagecom.hbu.springlogdemo.Facade;publicclassMain{publicstaticvoidmain(String[] args){Facade facade =newFacade(); facade.on(); facade.off();}}
门面模式的优点
・减少了系统的相互依赖。实现了客户端与子系统的耦合关系,这使得子系统的变化不会影响到调用它的客户端;
・提高了灵活性,简化了客户端对子系统的使用难度,客户端无需关心子系统的具体实现方式,而只需要和门面对象交互即可.
・提高了安全性。可以灵活设定访问权限,不在门面对象中开通方法,就无法访问.
SLF4J框架介绍
SLF4J 就是其他日志框架的门面. SLF4J 可以理解为是提供日志服务的统一 API 接口,并不涉及到具体的日志逻辑实现.
不引入日志门面时
常见的日志框架有 log4J, logback 等。如果一个项目已经使用了 log4j,而你依赖的另一个类库,假如是 Apache Active MQ, 它依赖于另外一个日志框架 logback, 那么你就需要把 logback 也加载进去

存在问题:
1.不同日志框架的 API 接口和配置文件不同,如果多个日志框架共存,那么不得不维护多套配置文件 (这个配置文件是指用户自定义的配置文件).
2.如果要更换日志框架,应用程序将不得不修改代码,并且修改过程中可能会存在一些代码冲突.
3.如果引入的第三方框架,使用了多套,那就不得不维护多套配置
引入日志门面时
引入门面日志框架之后,应用程序和日志框架 (框架的具体实现) 之间有了统一的 API 接口 (门面日志框架实现), 此时应用程序只需要维护一套日志文件配置,且当底层实现框架改变时,也不需要更改应用程序代码。
SLF4J 就是这个日志门面。总的来说,SLF4J 使你的代码独立于任意一个特定的日志 API,这是一个对于开发 API 的开发者很好的思想。
日志格式

从上图可以看到,日志输出内容元素具体如下:
1.时间日期:精确到毫秒
2.日志级别:ERROR, WARN, INFO, DEBUG 或 TRACE
3.进程 ID
4.项目名称
5.线程名
6.Logger 名 (通常使用源代码的类名)
7.日志内容

日志级别
日志的级别从高到低依次为: FATAL、ERROR、WARN、INFO、DEBUG、TRACE
・FATAL: 致命信息,表示需要立即被处理的系统级错误。
・ERROR: 错误信息,级别较高的错误日志信息,但仍然不影响系统的继续运行。
・WARN: 警告信息,不影响使用,但需要注意的问题。
・INFO: 普通信息,用于记录应用程序正常运行时的一些信息,例如系统启动完成、请求处理完成等。
・DEBUG: 调试信息,需要调试时候的关键信息打印。
・TRACE: 追踪信息,比 DEBUG 更细粒度的信息事件 (除非有特殊用意,否则请使用 DEBUG 级别替代)。
packagecom.hbu.springlogdemo.Controller;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RequestMapping("/log")@RestControllerpublicclassLogController{privateLogger logger =LoggerFactory.getLogger(LogController.class);@RequestMapping("/print")publicvoidprint(){System.out.println("sout打印日志"); logger.info("logger 打印日志"); logger.trace("logger trace..."); logger.debug("logger debug..."); logger.info("logger info..."); logger.warn("logger warn..."); logger.error("logger error...");}}
首先呢,Logger压根没提供打印fatal的方法。也能理解,这种级别的错误不需要日志,直接就能看出来,比如服务器直接挂了。
其次,我们发现最低两级的日志信息没有被打印,其实这与日志的配置信息有关。日志的输出级别默认是 info级别, 所以只会打印大于等于此级别的日志, 也就是info, warn和error。
日志配置
spring: application: name:Spring-log-demo logging: level: root: trace 在yml文件里面把默认配置设为trace:


好消息:都打印出来啦
坏消息:打印出来的东西太多了。。。(细节滑轮大小)
日志持久化
以上的日志都是输出在控制台上的,然而在线上环境中,我们需要把日志保存下来,以便出现问题之后追溯问题。把日志保存下来就叫持久化.日志持久化有两种方式
1.配置日志文件名
2.配置日志的存储目录

spring: application: name:Spring-log-demo logging: level: root: info file: name: logger/log.log 
2.
spring: application: name:Spring-log-demo logging: level: root: info file: path: logger/log.log 
这两种方法都可以生成存储在本地磁盘的.log文件,设置路径时可以指定相对路径和绝对路径,效果是一样的。
使用路径的方式指定时,文件名默认是spring.log。
注意:
logging.file.name 和 logging.file.path 两个都配置的情况下, 只生效其⼀, 以logging.file.name 为准
配置文件分割
如果我们的日志都放在一个文件中,随着项目的运行,日志文件会越来越大,需要对日志文件进行分割。当然,日志框架也帮我们考虑到了这一点,所以如果不进行配置,就走自动配置。默认日志文件超过 10M 就进行分割。

logging: level: root: info file: path: logger/log.log logback: rolling policy: max-file-size:1KB file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i 可以自定义格式试一下。
更简单的日志输出
这个方法用到的依赖是lombok,咱们很久之前就接触了。
packagecom.hbu.springlogdemo.Controller;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@Slf4j@RequestMapping("/log2")@RestControllerpublicclassLogController2{@RequestMapping("/print")publicvoidprint(){ log.info("lombok简便输出");}}

以上就是本篇博客全部内容!