用个人电脑做服务器建网站,30天网站建设实录,百度一下的网址,优化点击软件文章目录 什么是日志日志的用途日志的使用如何打印日志日志级别日志框架门面模式#xff08;外观模式#xff09;日志级别的使用配置日志级别日志持久化配置日志的存储目录配置日志文件名配置日志文件分割 更简单的日志输出 什么是日志
在计算机领域#xff0c;日志是一个记… 文章目录 什么是日志日志的用途日志的使用如何打印日志日志级别日志框架门面模式外观模式日志级别的使用配置日志级别日志持久化配置日志的存储目录配置日志文件名配置日志文件分割 更简单的日志输出 什么是日志
在计算机领域日志是一个记录了发生在运行中的操作系统或其他软件中的事件或者记录了在网络聊天软件的用户之间发送的消息。
通常情况下系统日志是用户可以直接阅读的文本文件其中包含了一个时间戳和一个信息或者子系统所特有的其他信息。任何系统中日志都是非常重要的组成部分它是反映系统运行情况的重要依据也是排查问题时的必要线索。
前面我们多多少少都用过日志并且通过日志来解决我们代码中遇到的问题。像 System.out.println 打印信息就可以看作是一种简单的日志通过日志我们可以很快的定位到错误出现的位置或者问题出现的详细信息日志对我们排查问题来说是非常重要的。
虽然 System.out.println 这种形式的日志可以解决问题但是随着项目复杂度的提升我们对于日志的打印也有了更高的需求而不仅仅是定位排查问题。
一些情况我们往往需要知道程序运行的过程和操作记录通过这些记录往往能够帮助我们快速的解决遇到的问题。
日志的用途
通过前⾯的学习我们知道⽇志主要是为了发现问题分析问题定位问题的但除此之外⽇志还有很多⽤途
系统监控 监控现在⼏乎是⼀个成熟系统的标配我们可以通过⽇志记录这个系统的运⾏状态每⼀个⽅法的响应时间响应状态等对数据进⾏分析设置不同的规则超过阈值时进⾏报警。⽐如统计⽇志中关键字的数量并在关键字数量达到⼀定条件时报警这也是⽇志的常⻅需求之⼀数据采集 数据采集是⼀个⽐较⼤的范围采集的数据可以作⽤在很多⽅⾯⽐如数据统计推荐排序等
数据统计统计⻚⾯的浏览量(PV)访客量(UV)点击量等根据这些数据进⾏数据分析优化公司运营策略推荐排序⽬前推荐排序应⽤在各个领域我们经常接触的各⾏各业很多也都涉及推荐排序⽐如购物⼴告新闻等领域。数据采集是推荐排序⼯作中必须做的⼀环系统通过⽇志记录用户的浏览历史停留时⻓算法⼈员通过分析这些数据训练模型给用户做推荐
日志审计 随着互联⽹的发展众多企业的关键业务越来越多的运⾏于⽹络之上。⽹络安全越来越受到⼤家的关注系统安全也成为了项⽬中的⼀个重要环节安全审计也是系统中⾮常重要的部分。国家的政策法规、⾏业标准等都明确对⽇志审计提出了要求。通过系统⽇志分析可以判断⼀些⾮法攻击⾮法调⽤以及系统处理过程中的安全隐患
日志的使用
当我们启动 SpringBoot 项目的时候其实就会存在日志。 并且通过观察我们可以发现日志的输出内容包含很多信息包括时间、在哪个类中打印的和描述信息等等。
就是通过这些日志我们能根据时间和所属类很快的定位到问题出现的位置。这些是默认存在的会打印的日志那么我们如何打印出我们自己想要的日志呢
如何打印日志
Spring 中默认内置了一个日志框架——Slf4j我们可以通过这个框架来打印出我们想要的日志。
要想打印日志首先需要获取到日志对象。
Logger 对象的所属包是 org.slf4j 包。 这个 Logger 对象是通过 LoggerFactory 工厂类中的 getLoger获取的。
private static final Logger logger LoggerFactory.getLogger(LoggerController.class);注意getLogger 方法中的参数需要传递一个类对象用来知道是哪个类输出的日志当遇到问题时我们可以根据这个所属类更快的定位到问题所在位置。
当获取到 Logger 日志对象之后我们就可以通过 Logger 类当中的方法打印出对应的日志。 logger 类中有很多方法但是主要打印日志的方法就是 trace()、deBug()、info()、warn()、error()方法那么这些方法有什么区别呢后面再为大家解释这里我们先使用。一个方法会有很多种的重载方法我们可以根据需要选择使用哪种传递参数的方法。 package com.example.logger;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 final Logger logger LoggerFactory.getLogger(LoggerController.class);RequestMapping(/getLogger)public String getLogger() {logger.trace(我是 trace);logger.debug(我是 deBug);logger.info(我是 info);logger.warn(我是 warn);logger.error(我是 error);return hello logger;}
} 当使用网页访问这个程序的时候可以发现虽然控制台中有添加的日志输出但是可以发现只有 info、warn、error 方法的日志被输入了那么这是为什么呢
这里就需要了解什么是日志级别了
日志级别
日志级别是用于控制程序日志输出内容的一种方式不同的级别对应不同的方法。日志级别代表着日志信息对应问题的严重性。其主要意义在于
帮助开发者快速定位问题。针对不同级别的日志信息开发者可以针对性地分析和定位问题从而更快地解决问题。排除不必要的日志信息。通过设置适当的日志级别可以避免记录过多的无用信息从而节约系统资源提高应用程序的性能。监控系统运行状态。应用程序在运行时会产生大量的信息这些信息有助于开发者对系统状态进行监控和分析从而确保应用程序能够稳定运行。保护系统安全。
⽇志的级别从⾼到低依次为FATAL、ERROR、WARN、INFO、DEBUG、TRACE。
FATAL致命信息表⽰需要立即被处理的系统级错误ERROR错误信息级别较⾼的错误⽇志信息但仍然不影响系统的继续运⾏WARN警告信息不影响使⽤但需要注意的问题INFO普通信息⽤于记录应⽤程序正常运⾏时的⼀些信息例如系统启动完成、请求处理完成等DEBUG调试信息需要调试时候的关键信息打印TRACE追踪信息⽐DEBUG更细粒度的信息事件(除⾮有特殊⽤意否则请使⽤DEBUG级别替代)
如果我们不设置日志级别的话所有级别的日志信息都会被打印这样的话控制台就会出现非常多的日志信息就会导致我们不容易找到具体的需要的日志信息。一些 trace、deBug、info 级别的日志信息在我们的生产环境是用不到的这些级别的信息就是在开发环境中会使用到在生产环境中我们主要使用 warn、error 级别的日志。
⽇志级别是开发⼈员设置的⽤来给开发⼈员看的。⽇志级别的正确设置也与开发⼈员的⼯作经验有关。如果开发⼈员把error级别的⽇志设置成了info就很有可能会影响开发⼈员对项⽬运⾏情况的判断。出现error级别的⽇志信息较多时可能也没有任何问题。测试的bug级别更多是依据现象和影响范围来判断。 日志框架
在使用日志框架之前我们还需要了解 Spring 中的日志框架。 Spring 中日志框架分为两层与我们程序员直接交接的是日志门面日志的实际打印是日志实现完成的这个日志门面层相当于中间层。这种模式叫做门面模式。
门面模式外观模式
门面模式Facade Pattern也叫外观模式是一种软件设计模式它为子系统中的一组接口提供一个统一的高层接口使得子系统更容易使用。
门面模式的主要特征包括
提供一个统一的接口用来访问子系统中的一群接口。定义了一个高层接口让子系统更容易使用。 外观⻆⾊(Facade)也称门面角系统对外的统⼀接⼝
⼦系统⻆⾊(SubSystem)可以同时有⼀个或多个 SubSystem。每个SubSytem 都不是⼀个单独的类⽽是⼀个类的集合。SubSystem 并不知道 Facade 的存在对于 SubSystem ⽽⾔Facade 只是另⼀个 客户端⽽已(即 Facade 对 SubSystem 透明)
对于我们的日志框架来说为什么会使用门面模式呢其实关键的原因是为了解耦合。如果我们直接使用日志实现中的接口的话假设 log4j 1/2 打印日志时使用的是 logger.logger()那么我们在打印日志的时候调用的方法就是logger.logger()方法如果后面有一天 log4j 1/2 出现了漏洞为了安全公司决定不再使用这个接口而是改用 logback 接口但是呢logback 打印日志使用的方法是 log.log()方法那么我们之前项目中的 logger.logger() 方法都要修改成 log.log() 方法如果这代码使用的少还好如果是一千、一万行呢这样我们程序员的工作量就会很大通过使用门面模式也就是相当于添加了一个中介我们只告诉中介我们需要干什么具体的中介安排谁来做我们呢不关心由中介来安排这样就算底层日志实现的接口更换了因为有这个日志门面也就是中介在我们还是不需要做出改变的。
这里给大家用代码演示一下
//这是我们程序员调用log打印日志方法通过调用slf4j类中的log()方法
slf4j.log(xxxxxx);//这是slf4j类中的log方法
public void log(String str) {//假设日志门面slf4j使用的日志实现是log4j 1/2log4j.log(str);
}这里 log4j 12 的具体实现我们先不关心假设调用 log4j.log() 可以实现日志的打印如果日志的实现因为漏洞等安全问题需要更改日志实现接口的话我们程序员的代码是不需要更改的只需要在 slf4j的 log() 方法中更改调用的接口就行了。
public void log(String str) {//日志实现的接口更换为logbacklogback.log(str);
}通过门面模式能够解耦合很大程度的减少我们程序员的负担。
日志级别的使用
SpringBoot 默认使用的门面日志是 SLF4J默认日志实现是 logbacklogback 没有 fatal 级别它是被映射到 eror 中的。
出现fatal⽇志表⽰服务已经出现了某种程度的不可⽤需要需要系统管理员紧急介⼊处理。通常情况下⼀个进程⽣命周期中应该最多只有⼀次FATAL记录。
打印日志的时候只会打印默认日志级别以及默认日志级别之上的日志级别的日志。
SpringBoot 默认的日志级别是 info 级别也就是说只会打印出 info、warn、error的日志级别的日志那么我们如何修改默认日志级别呢
配置日志级别
前面我们学习了 SpringBoot 配置文件配置日志级别就是在配置文件中配置的。
在 properties 配置文件中这样设置 logging.lever.rootdebugyml 配置文件中这样设置
logging:level:root: debug # root 表示当前项目的所有文件的默认日志级别再次启动项目可以发现出现了 debug 日志级别以及 debug 日志级别之上的日志级别的日志。 root 表示设置当前项目所有文件的默认日志级别那么如果我们想要不同文件具有不同的默认日志级别该怎么办呢其实也不难。我们只需要在配置文件中为指定文件配置默认日志级别就可以达到不同文件配置不同默认日志级别的功能了。
# 这里我们将controller包下的默认日志级别设置为trace
logging:level:root: debugcom:example:logger:controller: trace那么这样设置的话除了controller包下的默认日志级别为trace其他的文件的默认日志级别就是debug了。 日志持久化
出现在控制台的日志是保存在内存中的当我们重启程序或者重启 idea 的时候之前的日志就会被丢掉在实际生活中我们往往需要将日志保存在磁盘上永久保存这种方式就叫做日志的持久化。
日志持久化有两种方式
配置日志的存储目录配置日志文件名
配置日志的存储目录
当我们使用配置日志的存储目录实现日志的持久化的话spring 会使用默认的文件名来命名文件。如果指定的文件目录不存在也会自动创建。
配置日志的存储目录在 properties 配置文件中使用 logging.file.pathxxx配置在 yml 配置文件中这样配置。
logging:file:path: d://logs配置文件存储目录spring 默认的日志文件名是 spring.log如果日志内容太多操作一个文件的存储大小限制的话spring 会再创建一个新的文件
配置日志文件名
保存日志我们也可以指定文件的文件名在 properties 配置文件中使用 logging.file.namexxx在 yml 配置文件中使用
logging:file:name: springboot-log.log当访问这个程序之后会在我们的项目下生成一个指定文件名的文件。 以配置日志文件名的方式保存日志如果日志的内容过多超出最大限制的话spring 会在你指定日志文件名的基础上再创建出一个日志文件来做区别。
配置日志文件分割
如果我们将日志都放在一个文件的话那么随着项目运行时间的增长文件中的内容会越来越多如果文件中的数据达到一定数量之后那么我们想要在这个文件中查找指定日志的话就会显得非常麻烦那么如何解决这个问题呢
解决这个问题可以实现对日志文件的分割当日志文件达到一定大小之后会再创建出一个日志文件将后面的日志保存在这个新创建的文件中。
关于更多的 SpringBoot 日志的配置项大家可以去官网看看SpeingBoot配置
这里日志文件分割主要与这两个配置有关。 第一个配置是日志文件分割的名称定义规则第二个则是日志文件的最大容量当日志文件的大小大于这个最大容量的话那么就会根据这个日志文件分割的名称定义规则创建出新的文件存储后面的日志信息。
logging.logback.rollingpolicy.file-name-pattern配置的默认值是 ${LOG_FILE}.%d{yyyy-MM-dd}.%i 也就是这种形式 然后我们设置日志文件的最大容量为 1KB 来看看效果
logging:file:name: d://logs/springboot.loglogback:rolling policy:file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%imax-file-size: 1KBlevel:root: debug更简单的日志输出
这里简单主要是简单在日志对象的创建上使用上面的方法创建文件对象的话每次都需要这样创建。
private static final Logger logger LoggerFactor.getLogger(Main.class)
每个类中创建日志对象的代码百分之其实都是相同的所以为了节省这个创建日志对象的代码我们就可以使用一个工具类 Lombok在这篇文章中为大家说明了如何下载 Lombok SpringMVC案例
使用 Lombok 工具类之后我们只需要在类上加上一个 slf4j 注解那么这个类中就会默认创建出一个 Logger 类的实例 log可以直接使用。 package com.example.logger.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
Slf4j
public class LombokController {RequestMapping(/getLombok)public String getLog() {log.trace(我是 trace);log.debug(我是 deBug);log.info(我是 info);log.warn(我是 warn);log.error(我是 error);return hi lombok;}
} 那么为什么加了 Slf4j 之后就会自动创建出一个 Logger 对象呢其实 Lombok 在代码编译阶段做了“手脚”。
Java程序运行原理 Lombok 作用 我们来看看编译形成的.class文件看看跟正常的创建 Logger 对象有什么区别。 可以看到Lombok作用在代码的编码期间在这个过程在 Slf4j 注解会被替换为 private static final Logger log LoggerFactory.getLogger(LombokController.class)这个创建 Logger 的代码因此当我们加上这个注解之后该类中就会自动创建一个 Logger 对象 log。通过这个注解可以简化我们的创建过程。