日志文件是一种记录计算机系统或应用程序运行状态和活动的文件。日志文件可以包含各种重要信息,如错误报告、警告、事件、用户活动等。日志文件通常用于故障排除、性能优化、安全审计和法律合规等方面。日志文件可以在本地存储,也可以通过网络传输到远程服务器进行集中存储和分析。对于大型系统和应用程序,日志文件通常很大,需要专门的工具和技术来处理和分析。
简单点儿来说,日志文件就是帮助我们记录程序开发或者使用过程中的一些必要信息,帮助我们进行后期的维护和纠错~
日志是程序的重要组成部分,最主要的作用就是帮助我们 排除和定位问题, 除此之外,还有如下常用功能:
在日常开发中,日志也被广泛使用:
调试和故障排除:当代码出现问题时,日志可以帮助开发人员确定问题所在,信息包括错误消息、异常堆栈和变量值。开发人员可以利用这些信息快速定位问题。
性能分析和优化:日志中可以记录程序的运行时间、内存使用情况和磁盘IO等信息。开发人员可以利用这些信息来寻找性能瓶颈,并优化代码以提高性能。
安全监控:日志可以记录系统和应用程序的访问情况、用户行为,以及异常登录等信息。这些日志数据有助于开发人员监控和检测潜在的安全问题。
操作审计:日志可以记录用户的操作,包括登录、退出、修改记录等。这些日志可以用于审计和追踪用户活动。
运维和监控:日志可以用于监控应用程序的运行状态,并在系统出现异常时通知运维人员。开发人员也可以使用日志来跟踪应用程序的版本和部署情况。
总之,日志是开发中不可或缺的一部分,它可以帮助开发人员快速排查问题,优化性能,并保证应用程序的安全和可靠性。
Spring Boot 项⽬在启动的时候默认就有⽇志输出,如下图所示:
可见,Spring Boot内置了日志框架,从而能完成日志在控制台的打印。那么问题就来了,同样是在控制台打印,为什么不使用System.out.print打印呢? 答案是显然的:
还有一个问题,在控制台打印的日志是不能被永久保存的,怎么把⽇志永久的保存下来呢? 别急,带着问题我们继续往后看~
自定义日志打印主要步骤如下:
获取日志对象
在程序中获取⽇志对象需要使⽤⽇志⼯⼚ LoggerFactory,代码如下:
// 1. 得到日志对象
private final Logger logger = LoggerFactory.getLogger(UserController.class);
其中,getLogger方法需要传入当前类,用于说明日志归属类,便于我们更加直观的定位到问题类。同时,需要注意的是,Logger 对象属于 org.slf4j
包下。
使用日志对象打印日志
日志对象的打印方法有很多,示例代码如下:
// 2. 写日志的方法
@RequestMapping("/hi")
public String sayHi() {
// 写日志
logger.trace("我是 trace");
logger.debug("我是 debug");
logger.info("我是 info");
logger.warn("我是 warn");
logger.error("我是 error");
return "Hi, Spring Boot.";
}
实现结果:
可以看到,使用了 5 种不同的方法打印日志信息,但是,控制台只打印了其中的三种,这是由于日志级别的设置造成的,具体后面详细说明。同时,通过控制台打印的信息我们可以看出,一条日志信息包含时间、日志的级别、线程ID、线程名称、日志归属的包和类以及日志的内容。
日志级别的作用在于通过设置不同级别的日志来查看不同严重程度的问题信息,方便定位问题,快速排除问题。比如在生产环境中,一般只记录INFO及以上级别的日志,这样可以减少日志量,避免影响系统性能。而在调试过程中,一般会开启DEBUG级别的日志,以便更详细地了解程序的运行情况,从而找到问题所在。
总的来说,通过设置日志级别,可以大大节省开发者信息筛选的时间,帮助我们快速定位和排除问题。
⽇志的级别分为:
实际中,我们能自定义的只有前5个,而致命级别的日志,会在代码异常导致程序退出时执行。日志级别的顺序如下图所示:
例如,当设置日志级别为 error 时,我们就只能收到 error、fatal 级别的日志了。而之前的案例中,是因为 Spring Boot 中默认的日志级别是 info, 因此,控制台只有 info、warn、error 级别的日志信息。
日志级别的设置,只需要在配置文件中设置 logging.level
配置项即可。
配置根路径的日志级别:
# 日志级别设置
logging:
level:
root: error
此时,我们再次运行自定义日志打印中的代码,得到如下结果:
可见,控制台干净了许多,原来的info等日志信息都被筛选掉了~
在根路径日志级别的基础上配置子目录日志级别
# 日志级别设置
logging:
level:
root: error
com:
hxh:
demo:
controller: trace
此时,对于 com.hxh.demo.controller
包下的类,trace 及以上级别的日志信息被打印到控制台上。
到这里,我们已经了解到如何自定义日志打印以及如何设置日志级别。但是还遗留了一个致命性的问题:日志信息是输出在控制台的,如果重新启动项目,控制台的信息不就消失了吗?有没有什么方法能够将日志信息保存起来,方便以后查看呢?
答案是肯定的,在生产环境中,我们常常把日志信息保存下来。而将日志信息保存下来的过程就叫做日志持久化。想要将⽇志进⾏持久化,只需要在配置⽂件中指定⽇志的存储⽬录或者是指定⽇志保存⽂件名之后,
Spring Boot 就会将控制台的⽇志写到相应的⽬录或⽂件下了。
配置日志文件的保存路径:
# 设置日志文件的目录
logging:
file:
path: D:\\home\\log
配置日志文件的文件名:
logging:
file:
name: D:\\home\\log\\spring-1024.log
通过观察自定义日志打印的案例,我们可以看出,每个需要打印日志的归属类都需要有如下语句:
private final Logger logger = LoggerFactory.getLogger(UserController.class);
该语句比较固定,写起来不太“优雅”,这里提供一种更加简洁的方式:使用 lombok 来更简单的输出,具体步骤如下:
添加 lombok 依赖
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.20version>
<optional>trueoptional>
dependency>
输出日志
使⽤ @Slf4j
注解,在程序中使⽤ log 对象即可输⼊⽇志,并且只能使⽤ log 对象才能输出,这是 lombok 提供的对象名(原因见后面lombok原理)
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
@RequestMapping("/student")
@Slf4j
public class StudentController {
// 打印日志
@RequestMapping("/hi")
public String sayHi() {
log.error("这是通过 lombok 打印的日志信息~");
return "hi";
}
}
Lombok 是一种 Java 库,它提供了一些注解来自动生成 Java 代码。Lombok 的原理是在编译时通过 Java 的注解处理器和 AST(Abstract Syntax Tree,抽象语法树)转换器代替开发人员手动编写常见的 Java 代码(如构造函数、getter 和 setter 方法、equals 和 hashCode 方法等)。也就是说,Lombok 在编译期间生成代码,而不是在运行时生成。 Lombok 的使用可以节省开发者在编写 Java 代码时的时间和精力,并且可以让代码更加简洁易懂。
之前使用 lombok 简单输出日志的案例中,编译生成的字节码文件反编译后如下图所示:
@slf4j 注解,实质上就是帮助我们进行了 log 对象的创建,我们只需要使用 log 对象即可~
常见的 lombok 注解如下:
注解 | 说明 |
---|---|
@Getter | 自动生成getter方法 |
@Setter | 自动生成setter方法 |
@ToString | 自动生成toString方法 |
@EqualsAndHashCode | 自动生成equals和hashCode方法 |
@NoArgsConstructor | 自动生成无参构造器 |
@AllArgsConstructor | 自动生成全参构造器 |
@RequiredArgsConstructor | 自动生成必填参数的构造器 |
@Data | 自动生成getter、setter、toString、equals和hashCode方法 |
@Builder | 自动生成Builder模式的代码 |
@Log | 自动生成日志对象 |
@Slf4j | 自动生成@Slf4j注解 |
@Value | 生成不可变类,即final字段以及对应的getter方法 |
@UtilityClass | 生成工具类,包含私有构造器和静态方法 |
本文被 JavaEE编程之路 收录点击订阅专栏 , 持续更新中。
以上便是本文的全部内容啦!创作不易,如果你有任何问题,欢迎私信,感谢您的支持!