文章目录
一、日志概述
-
为什么不使用 System.out.print
使用 System.out.print 也可以打印日志,帮助我们解决定位排查的问题。但是如果要解决记录用户操作记录等问题,System.out.print 就不能很好的满足需求了,就需要使用专门的日志框架 -
日志的用途
- 发现、分析、定位问题
- 系统监控
- 日志审计
- 数据采集
二、日志使用
-
Spring Boot 项目在启动的时候默认就是有日志输出的,相比于 System.out.print 可以打印更多的内容
-
Spring Boot 内置了日志框架 Slf4j,我们可以在程序中通过调用 Slf4j 来输出日志
- Slf4j 是门面模式的典型应用
- Slf4j 不是一个真正的日志实现,而是一个抽象层,对日志框架指定的一种规范。所以,Slf4j 并不能独立使用,需要和具体的日志框架配合使用
1. 打印日志 ----- Logger()
打印日志的步骤
- 在程序中得到日志对象
- 使用日志对象输出要打印的内容
(1) 获得日志对象
//在程序中获取日志对象需要使用日志工厂 LoggerFactory
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
LoggerFactory.getLogger 需要传递⼀个参数,标识这个日志的名称。这样可以更清晰的知道是哪个类输出的日志。当有问题时,可以更方便直观的定位到问题类
(2) 使用日志对象输出要打印的内容
@RestController
public class LoggerController {
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
@RequestMapping("/logger")
public void logger(){
logger.info("要输出的日志");
}
}
2. 打印日志 ----- Lombok
- 添加 lombok 框架支持
- 使用 @slf4j 注解输出日志
引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
日志代码
lombok提供的 @Slf4j 会帮我们提供⼀个日志对象 log,直接使用即可
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class LogController {
public void log(){
log.info("--------------要输出⽇志的内容----------------");
}
}
三、门面模式(外观模式)
- 门面模式定义
门面模式(Facade Pattern)又称为外观模式,提供了⼀个统⼀的接口,用来访问子系统中的⼀群接口,其主要特征是定义了⼀个高层接口,让子系统更容易使用
门面系统相当于医院的前台,子系统相当于各个科室,门面系统(前台)指导每个客户端(病人)该去哪个子系统
2. 门面模式主要包含2种角色:
- 外观角色(Facade):也称门面角色,系统对外的统⼀接口
- 子系统角色(SubSystem):可以同时有⼀个或多个 SubSystem。每个 SubSytem 都不是⼀个单独的类,而是⼀个类的集合。SubSystem 并不知道 Facade 的存在,对于 SubSystem 而言,Facade 只是另⼀个客户端而已(即 Facade 对 SubSystem 透明)
public class FacadePatternDemo {
public static void main(String[] args) {
LightFacade lightFacade = new LightFacade();
lightFacade.lightOn();
}
}
/**
* 灯的⻔⾯
*/
class LightFacade{
private Light livingRoomLight = new LivingRoomLight();
private Light hallLight = new HallLight();
private Light diningLight = new DiningLight();
public void lightOn(){
livingRoomLight.on();
hallLight.on();
diningLight.on();
}
public void lightOff(){
livingRoomLight.off();
hallLight.off();
diningLight.off();
}
}
interface Light {
void on();
void off();
}
/**
* 客厅灯
*/
class LivingRoomLight implements Light{
@Override
public void on() {
System.out.println("打开客厅灯");
}
@Override
public void off() {
System.out.println("关闭客厅灯");
}
}
/**
* ⾛廊灯
*/
class HallLight implements Light{
@Override
public void on() {
System.out.println("打开⾛廊灯");
}
@Override
public void off() {
System.out.println("关闭⾛廊灯");
}
}
/**
* 餐厅灯
*/
class DiningLight implements Light{
@Override
public void on() {
System.out.println("打开餐厅灯");
}
@Override
public void off() {
System.out.println("关闭餐厅灯");
}
}
四、日志格式
(1) 日志级别
- 日志的级别从高到低依次为: FATAL、ERROR、WARN、INFO、DEBUG、TRACE
- FATAL:致命信息,表示需要立即被处理的系统级错误
- ERROR:错误信息,级别较高的错误日志信息,但仍然不影响系统的继续运行
- WARN: 警告信息,不影响使用,但需要注意的问题
- INFO: 普通信息,用于记录应用程序正常运行时的⼀些信息, 例如系统启动完成、请求处理完成等
- DEBUG: 调试信息, 需要调试时候的关键信息打印
- TRACE: 追踪信息,比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)
日志级别是开发人员设置的,用来给开发人员看的,通常与测试人员的 Bug 级别没有关系。
级别越高,接受的信息越少
public void printLog() {
logger.trace("================= trace ===============");
logger.debug("================= debug ===============");
logger.info("================= info ===============");
logger.warn("================= warn ===============");
logger.error("================= error ===============");
}
结果发现,只打印了info, warn和error级别的日志
这与日志级别的配置有关,日志的输出级别默认是 info级别,所以只会打印大于等于此级别的同志, 也就是 info, warn和error
五、日志配置
(1) 配置日志级别
日志级别配置只需要在配置文件中设置 “logging.level” 配置项即可
properties 和yml 只需要配置其中一个
# Properties配置
logging.level.root: debug
# yml 配置
logging:
level:
root: debug
(2) 日志持久化:把日志保存下来
持久化方式
- 配置日志文件名
- 配置日志的存储目录
【1】日志文件名
# Properties配置
logging.file.name: logger/springboot.log
# yml 配置
logging:
file:
name: logger/springboot.log
此时日志内容保存在了对应的目录下
【2】日志的存储目录
# Properties配置
logging.file.path: D:/temp
# yml 配置
logging:
file:
path: D:/temp
logging.file.name 和 logging.file.path 两个都配置的情况下, 只生效其⼀,以 logging.file.name 为准
(3) 配置日志文件分割
如果我们的日志都放在⼀个文件中, 随着项目的运行, 日志文件会越来越⼤, 需要对日志文件进行分割
配置项 | 说明 | 默认值 |
---|---|---|
logging.logback.rollingpolicy.file-name-pattern | 日志分割后的文件名格式 | ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
logging.logback.rollingpolicy.max-file-size | 日志文件超过这个大小就自动分割 | 10MB |
# Properties配置
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i
logging.logback.rollingpolicy.max-file-size=1KB
# yml 配置
logging:
logback:
rollingpolicy:
max-file-size: 1KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
(4) 配置日志格式
配置项 | 说明 | 默认值 |
---|---|---|
logging.pattern.console | 控制台日志格式 | %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MMdd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:- %5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]) {faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx} |
logging.pattern.file | 日志文件的日志格式 | %d{${LOG_DATEFORMAT_PATTERN:-yyyy-MMdd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx} |
# Properties配置
logging.pattern.console='%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
# yml 配置
logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
通常情况下, 咱们就使用默认的日志格式打印即可