目录
一、日志的用途
二、日志使用
2.1 打印日志
2.1.1 在程序中获取日志对象
2.1.2 使用日志对象打印日志
2.2、日志框架介绍
2.2.1 门面模式(外观模式)
2.2.2 门面模式的实现
2.2.3 SLF4J 框架介绍
2.3 日志格式的说明
2.4 日志级别
2.4.1 日志级别的分类
2.4.2 日志级别的使用
2.5 日志配置
2.5.1 配置日志级别
2.5.2 日志持久化
2.5.3 配置日志文件分割
三、 @Slf4j注解
3.1 添加lombok依赖
3.2 输出日志
一、日志的用途
1. 系统监控
监控现在⼏乎是⼀个成熟系统的标配, 我们可以通过日志记录这个系统的运⾏状态,每⼀个方法的响应 时间,响应状态等,对数据进行分析,设置不同的规则,超过阈值时进⾏报警.⽐如统计⽇志中关键字的数量,并在关键字数量达到⼀定条件时报警,这也是⽇志的常⻅需求之⼀。
2. 数据采集
数据采集是⼀个⽐较大的范围,采集的数据可以作⽤在很多⽅⾯,比如数据统计,推荐排序等.
• 数据统计:统计页面的浏览量(PV),访客量(UV),点击量等,根据这些数据进行数据分析,优化公司运营 策略
• 推荐排序: 目前推荐排序应⽤在各个领域,我们经常接触的各行各业很多也都涉及推荐排序,比如购 物,⼴告,新闻等领域.数据采集是推荐排序⼯作中必须做的⼀环,系统通过日志记录⽤户的浏览历史,停留时长等,算法⼈员通过分析这些数据,训练模型,给⽤户做推荐。
3. 日志审计
随着互联网的发展,众多企业的关键业务越来越多的运行于网络之上.网络安全越来越受到大家的关注,系统安全也成为了项目中的⼀个重要环节, 安全审计也是系统中非常重要的部分.国家的政策法规、行业标准等都明确对日志审计提出了要求.通过系统日志分析,可以判断⼀些非法攻击,非法调⽤,以及系统处理过程中的安全隐患.
二、日志使用
2.1 打印日志
2.1.1 在程序中获取日志对象
在程序中获取日志对象需要使用日志工程LoggerFactory,如下代码所示:
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
注意:Logger对象是属于org.slf4j包下的
2.1.2 使用日志对象打印日志
日志对象的打印方法有很多种,我们可以先使⽤info()方法来输出日志,如下代码所示:
package com.example.demo.controller;
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 LoggerController {private static Logger logger = LoggerFactory.getLogger(LoggerController.class);@RequestMapping("/logger")public String logger() {logger.info("------要输出的内容-------");return "打印日志";}
}
打印日志效果展示:
2.2、日志框架介绍
SLF4J不同于其他日志框架,它不是⼀个真正的日志实现,而是⼀个抽象层,对日志框架制定的⼀种规范, 标准,接口.所有SLF4J并不能独立使用,需要和具体的日志框架配合使用.
2.2.1 门面模式(外观模式)
门面模式(FacadePattern)又称为外观模式,提供了⼀个统⼀的接⼝,⽤来访问子系统中的⼀群接口. 其主要特征是定义了⼀个⾼层接口,让子系统更容易使用.
门面模式主要包含2种角色:
外观角色(Facade):也称门面角色,系统对外的统一接口,
子系统角色(SubSystem):可以同时有一个或多个SubSystem.每个SubSytem都不是一个单独的类,而是一个类的集合.SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另一个客户端而已(即Facade对SubSystem透明)
举个例子:
比如去医院看病,可能要去挂号,门诊,化验,取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
2.2.2 门面模式的实现
场景:
回家时,我们会开各个屋的灯离开家时,会关闭各个屋的灯 如果家里设置⼀个总开关,来控制整个屋的灯的打开与关闭就会很方便。
package FacadePattern;public class FacadePatternDemo {public static void main(String[] args) {LightFacafe lightFacafe = new LightFacafe();lightFacafe.lightOn();lightFacafe.lightOff();}
}interface Light {void on();void off();
}/** 灯的门面* */
class LightFacafe {private Light livingRoomLight = new LivingRoomLight();private Light hallLight = new HallLight();private Light dingingLight = new DingLight();public void lightOn() {livingRoomLight.on();hallLight.on();dingingLight.on();}public void lightOff() {livingRoomLight.off();hallLight.off();dingingLight.off();}
}/** 客厅灯* */class LivingRoomLight implements Light {@Overridepublic void on() {System.out.println("打开客厅的灯");}@Overridepublic void off() {System.out.println("关闭客厅的灯");}
}/** 走廊灯* */class HallLight implements Light {@Overridepublic void on() {System.out.println("打开客厅的灯");}@Overridepublic void off() {System.out.println("关闭客厅的灯");}
}/** 餐厅灯* */class DingLight implements Light {@Overridepublic void on() {System.out.println("打开餐厅的灯");}@Overridepublic void off() {System.out.println("关闭餐厅的灯");}
}
门面模式的优点
1、减少了系统的相互依赖.实现了客户端与子系统的耦合关系,这使得子系统的变化不会影响到调用它的客户端;
2、提高了灵活性,简化了客户端对子系统的使用难度,客户端无需关心子系统的具体实现方式, 而只需要和门面对象交互即可.
3、提高了安全性.可以灵活设定访问权限,不在门面对象中开通方法,就无法访问
2.2.3 SLF4J 框架介绍
SLF4J 就是其他日志框架的门面.SLF4J可以理解为是提供日志服务的统一API接口,并不涉及到具体的 日志逻辑实现.
引入日志门面
引入门面日志框架之后,应用程序和日志框架(框架的具体实现)之间有了统一的AP接口(门面日志框架实现),此时应用程序只需要维护一套日志文件配置,且当底层实现框架改变时,也不需要更改应用程序代码.
SLF4J 就是这个日志门面. 总的来说,SLF4J使你的代码独立于任意⼀个特定的日志API,这是⼀个对于开发API的开发者很好的思想.
2.3 日志格式的说明
2.4 日志级别
2.4.1 日志级别的分类
日志的级别从高到低依次为:FATAL、ERROR、WARN、INFO、DEBUG、TRACE
FATAL:致命信息,表示需要立即被处理的系统级错误。
ERROR:错误信息,级别较⾼的错误日志信息,但仍然不影响系统的继续运行。
WARN:警告信息,不影响使用,但需要注意的问题。
INFO:普通信息,用于记录应用程序正常运行时的⼀些信息,例如系统启动完成、请求处理完成等。
DEBUG:调试信息,需要调试时候的关键信息打印。
TRACE:追踪信息,比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)
日志级别通常和测试人员的Bug级别没有关系,日志级别是开发人员设置的,用来给开发人员看的.日志级别的正确设置,也与开发人员的工作经验有关.如果开发人员把error级别的日志设置成了info,就很有可能会影响开发人员对项目运行情况的判断.出现error级别的日志信息较多时,可能也没有任何问题,测试的bug级别更多是依据现象和影响范围来判断。
日志级别的顺序:
2.4.2 日志级别的使用
日志级别是开发⼈员自己设置的.开发⼈员根据自己的理解来判断该信息的重要程度
针对这些级别,Logger对象分别提供了对应的方法,来输出日志.
@RestController
public class LoggerController {private static Logger logger = LoggerFactory.getLogger(LoggerController.class);@RequestMapping("/printLog")public String pringtLog() {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.
2.5 日志配置
2.5.1 配置日志级别
⽇志级别配置只需要在配置⽂件中设置"logging.level"配置项即可,如下所示例。
Properties配置
logging.level.root=debug
yml配置
logging:level:root=debug:
运行结果:
2.5.2 日志持久化
配置文件名的路径和文件名
Properties配置
logging.file.name=logger/springboot.log
yml配置
logging:level:root=debug:file:name: logger/springboot.log
运行结果显示,日志内容保存在对应的目录下
配置日志文件的保存路径
Properties配置
logging.file.path=D:/temp
yml配置
logging:file:path: C:\logger
运⾏程序,该路径下多出⼀个日志文件:spring.log
注意:
logging.file.name 和 logging.file.path 两个都配置的情况下,只⽣效其⼀,以 logging.file.name 为准
2.5.3 配置日志文件分割
如果我们的日志都放在⼀个⽂件中,随着项⽬的运行,日志⽂件会越来越⼤,需要对日志文件进行分割
配置项 | 说明 | 默认值 |
logging.logback.rollingpolicy.file-name-pattern | ⽇志分割后的⽂件名 格式 | ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
logging.logback.rollingpolicy.m ax-file-size | 日志文件超过这个大 小就自动分割 | 10MB |
Properties配置
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%ilogging.logback.rollingpolicy.max-file-size=1KB
yml配置
logging:file:path: C:/loggerlogback:rollingpolicy:file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%imax-file-size: 1KB
1. ⽇志⽂件超过1KB就分割(设置1KB是为了更好展示.企业开发通常设置为200M,500M等,此处没 有明确标准)
2. 分割后的⽇志⽂件名为:日志名.日期.索引
多次运行程序 查看日志分割效果
修改控制台颜色显示
添加 VMoptions-Dspring.output.ansi.enabled=ALWAYS
在控制台中的显示
三 @Slf4j注解
3.1 添加lombok依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency>
3.2 输出日志
@Slf4j
@RestController
public class LoggerController {// private static Logger logger = LoggerFactory.getLogger(LoggerController.class);@RequestMapping("/printLog")public String pringtLog() {log.info("---info---");return "打印不同级别的日志";}
}
lombok提供的 @Slf4j注解 会帮我们提供⼀个日志对象log,我们可以直接使用