日志体系
所谓的日志就是记录程序的运行而生成的文档
-
日志框架:
- Log4j:一个具体的日志实现框架。
- JUL:JDK中的日志记录工具,也常称为JDKLog、jdk-logging,自Java1.4以来的官方日志实现。
- Log4j2: 一个具体的日志实现框架,是LOG4J1的下一个版本,与Log4j 1发生了很大的变化,Log4j 2不兼容Log4j1。
- JCL:Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging
- SLF4J:是一套简易Java日志门面框架,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)
- Logback:一个具体的日志实现框架,和Slf4j是同一个作者,但其性能更好(推荐使用)。
-
slf4j(Simple Logging Facade for Java):是一种Java门面型日志框架,本身没有具体的日志实现,提供了一个用于在代码中记录消息的统一API。使用slf4j,我们可以在不修改底层实现的情况下更换底层日志记录框架(如log4j、Java Util Logging等),从而使代码更加灵活和可维护。
-
slf4j的作用:提供一个统一的日志接口,使代码编写者无需关心使用的具体日志记录框架,只需要依赖slf4j-api包并调用其提供的API即可进行日志输出。这样做可以让代码不受特定日志记录实现的影响,也方便了针对不同场景选择合适的日志记录框架。
-
slf4j的由来:因为在一个项目中,可能存在多个日志框架,这些日志框架本身有具体的日志实现和api接口,这样的话就会有多个日志接口,不好维护且兼容性存在问题。这个时候slf4j就出现了,用于解决上面的问题,通过slf4j统一的api再去兼容具体的日志实现这样更好维护且相对兼容。
其他的日志框架可以作为slf4j的具体实现框架,通过slf4j的统一api接口进行日志的记录
JUL (Java util logging)
核心组件
- Logger:日志记录器对象
- Handler:日志处理器对象,用于配置日志信息输出目标的组件,例如控制台、文件、数据库、邮件等
- Level:定义日志的级别,例如sevre,wring等
- Formatter:Formatter是JUL中提供的一个用于格式化日志信息输出的组件。通过Formatter,我们可以指定日志消息输出的格式,以满足不同需求。
使用配置
默认配置是输出大于等于info级别的
-
硬编码
示例配置ConsoleHandler的日志输出级别
private void configConsoleLogger(Logger logger) { // 关闭默认的处理器(可有可无,如果自己配置了就会覆盖掉) logger.setUseParentHandlers(false); // 创建处理器 (ConsoleHandler是控制台输出的处理器) Handler handler = new ConsoleHandler(); // 数据格式转换对象负责将Logger对象产生的原始日志消息格式化成可读性更好的文本 handler.setFormatter(new SimpleFormatter()); // logger添加handler logger.addHandler(handler); // 设置级别 ALL代表全部都要进行日志输出 logger.setLevel(Level.ALL); handler.setLevel(Level.ALL); }
示例自定义handler(输出日志到数据库)
package com.example.config; import com.example.datasource.JdbcUtil; import java.util.logging.Handler; import java.util.logging.LogRecord; /** * @Classname DataSourceHandler * @Description TODO 基于jul自定义handler实现将日志输出到数据库 * @Version 1.0.0 * @Date 2023/5/23 11:08 * @Created by wlh12 */ public class JulDataSourceHandler extends Handler { @Override public void publish(LogRecord record) { JdbcUtil.saveLog(record.getMessage(),record.getLevel().getName()); } @Override public void flush() { } @Override public void close() throws SecurityException { } } // jdbcUtil代码 package com.example.datasource; import java.sql.*; import java.util.logging.Logger; /** * @Classname JdbcUtil * @Description TODO * @Version 1.0.0 * @Date 2023/5/23 10:44 * @Created by wlh12 */ public class JdbcUtil { private static String URL = "jdbc:mysql://localhost:3306/java_log?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false"; private static String USERNAME = "root"; private static String PASSWORD = "wlh.lkiku.space"; private static PreparedStatement preparedStatement; private static Connection connection; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); connection = DriverManager.getConnection(URL,USERNAME,PASSWORD); } catch (Exception e){ e.printStackTrace(); } } public static void saveLog(String msg,String level){ String sql = "insert into log(msg,level) values(?,?)"; try { preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,msg); preparedStatement.setString(2,level); preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { try { preparedStatement.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } }
-
配置文件
# 设置rootLogger为ConsoleHandler handlers= java.util.logging.ConsoleHandler # 根logger级别 .level= ALL # 控制台处理器 java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.encoding=UTF-8 # 文件处理器 java.util.logging.FileHandler.level = ALL java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter #输出日志文件路径 java.util.logging.FileHandler.pattern=D:/logs/jul.log #输出日志文件限制大小(50000字节) java.util.logging.FileHandler.limit=50000 #输出日志文件限制个数 java.util.logging.FileHandler.count=10 #输出日志文件 是否是追加(不会覆盖前边的日志) java.util.logging.FileHandler.append=true # 自定义的handler也可使用对应的配置属性,属性参考实现的handler定义的属性值
log4j2
核心组件
-
Logger:日志记录器对象组件
-
Appender:配置日志信息输出目标的组件。例如控制台、文件、邮件等
-
Level:定义日志级别
-
Layout:Layout是Log4j中用来格式化日志输出的组件。Log4j预定义了多个Layout子类,以满足日志输出的不同需求,用户也可以自定义Layout子类来支持自己的格式化需求。
标准的layout配置:
%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
- %d:表示输出日期时间;
- %t:表示输出线程名;
- %p:表示输出日志级别;
- %c:表示输出Logger的名称;
- %m:表示输出日志内容;
使用配置
log4j默认日志输出是大于等于error级别的日志
Log4j 2 的配置可以通过以下 1 种方式之一完成:
- 通过以 XML、JSON、YAML 或属性格式编写的配置文件(常用)。
- 以编程方式,通过创建配置工厂和配置实现。
- 以编程方式,通过调用配置接口中公开的 API 来添加 组件到默认配置。
- 以编程方式,通过调用内部记录器类上的方法。
自动化配置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oETgMiA-1687177083125)(C:\Users\wlh12\AppData\Roaming\Typora\typora-user-images\image-20230524142409261.png)]
采用xml的配置方式示例如:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<Properties>
<Property name="logFilePath">E://workspace/log</Property>
</Properties>
<!-- 配置输出目标对象。例如控制台、数据库、文件等-->
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<!-- 配置输出到指定位置的文件-->
<File name="File" fileName="${logFilePath}/log.log">
<PatternLayout pattern="%m%n" />
</File>
<!-- 高级文件输出方式
可以定制:文件达到多大之后时间进行归档,新建日志文件进行输出等
-->
<RollingFile name="RollingFile" fileName="${logFilePath}/log-rollingFile.log"
filePattern="${logFilePath}/log-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<SizeBasedTriggeringPolicy size="1 KB" />
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<!-- 和上面的rollingfile类似,但是写入性能更好,有定时-->
<RollingRandomAccessFile name="RollingRandomAccessFile"
fileName="${logFilePath}/log-rollingRandomAccessFile.log"
filePattern="${logFilePath}/log-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<CronTriggeringPolicy schedule="0/10 * * * * ?"/>
</Policies>
<DefaultRolloverStrategy fileIndex="min" max="10"/>
</RollingRandomAccessFile>
<!-- 这里可以自定义Appender来实现将日志输出到自己想要的位置,例如输出到数据库-->
<DataSourceAppender name="myAppender" >
<PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</DataSourceAppender>
</Appenders>
<!-- 配置logger -->
<Loggers>
<!--过滤掉spring和hibernate的一些无用的debug信息-->
<logger name="org.springframework" level="INFO">
</logger>
<logger name="org.mybatis" level="INFO">
</logger>
<root level="info">
<AppenderRef ref="CONSOLE" />
<AppenderRef ref="File" />
</root>
<!-- 自定义logger 这里是对某个模块的日志logger进行了自定义-->
<logger name="com.example.Slf4jLog4j2Start" level="debug">
<AppenderRef ref="CONSOLE"/>
</logger>
<!-- 测试RollingRandomAccessFile-->
<logger name="com.example.RollingRandomAccessFile" level="debug">
<AppenderRef ref="RollingRandomAccessFile"/>
</logger>
<!-- 自定义该模块使用的是自定义的Appender-->
<logger level="info" name="com.example.DataSourceTest">
<AppenderRef ref="myAppender"/>
</logger>
<logger level="info" name="com.example.ToFileAndBase">
<AppenderRef ref="RollingFile"/>
</logger>
</Loggers>
</configuration>
配置结构解析
-
Configuration:根节点,有status和monitorInterval等多个属性,status的值有trace、debug、info、warn、error和 fatal,用于控制log4j2日志框架本身的日志级别,如果将status设置为较低的级别(如trace)就会看到很多关于log4j2本身的日志,如加载log4j2配置文件的路径等信息,一般不用设置。
monitorInterval,含义是每隔多少秒重新读取配置文件,可以不重启应用的情况下修改配置。
name:配置名称
strict: 是否使用严格的XML格式,推荐使用,规范开发者的配置编写。-
properties:配置文件全局的参数变量,用于减少自定义配置信息的重复编码,该配置是可选的,例如定义日志的存放位置D:/logs
-
Appenders:Appenders是输出源,用于定义日志输出的地方,log4j2支持的输出源有很多,有控制台Console、文件File、RollingRandomAccessFile、MongoDB、Flume等。
-
Console:控制台输出源是将日志打印到控制台上
-
File:文件输出源,用于将日志写入到指定的文件,需要配置输入到哪个位置(例如:D:/logs/mylog.log)
-
RollingRandomAccessFile: 该输出源也是写入到文件,不同的是比File更加强大,可以指定当文件达到一定大小(如20MB)时,另起一个文件继续写入日志,另起一个文件就涉及到新文件的名字命名规则,因此需要配置文件命名规则 这种方式更加实用,因为你不可能一直往一个文件中写,如果一直写,文件过大,打开就会卡死,也不便于查找日志。
- fileName:指定当前日志文件的位置和文件名称
- filePattern:指定当发生Rolling时,文件的转移和重命名规则
- SizeBasedTriggeringPolicy:指定当文件体积大于size指定的值时,触发Rolling
- DefaultRolloverStrategy:指定最多保存的文件个数
- TimeBasedTriggeringPolicy: 这个配置需要和filePattern结合使用,此时的filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟
-
RollingFile:同上,与RollingRandomAccessFile不同的是,RollingRandomAccessFile默认日志文件写入策略为异步刷盘,RollingRandomAccessFile会将日志信息先写入到缓冲区,然后缓冲区满后刷到磁盘,并清空缓冲区,默认缓冲区的大小在8-256kb,具体大小需要自己设置。
-
NoSql:MongoDb, 输出到MongDb数据库中
-
Flume:输出到Apache Flume(Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。)
-
Async:异步,需要通过AppenderRef来指定要对哪种输出源进行异步(一般用于配置RollingRandomAccessFile)
-
-
Loggers:日志器分根日志器Root和自定义日志器。每个logger可以指定一个level(TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF),不指定时level默认为ERROR。
- Logger:自定义记录器
- Root:跟记录器
-
Logback
与log4j2 作者为同一人,所以有很多相似的地方因此,例如组件和配置。
核心组件
-
Logger:日志记录器对象组件
-
Appender:配置日志信息输出目标的组件。例如控制台、文件、邮件等
-
Level:定义日志级别
-
Layout:Layout是Logback中用来格式化日志输出的组件。Log4j预定义了多个Layout子类,以满足日志输出的不同需求,用户也可以自定义Layout子类来支持自己的格式化需求。
标准的layout配置:
%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
- %d:表示输出日期时间;
- %t:表示输出线程名;
- %p:表示输出日志级别;
- %c:表示输出Logger的名称;
- %m:表示输出日志内容;
使用配置
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds" debug="false">
<!-- 尽量别用绝对路径,如果带参数不同容器路径解释可能不同,以下配置参数在pom.xml里 -->
<!-- 日志级别 -->
<property name="log.root.level" value="info"/>
<!-- 其他日志级别 -->
<property name="log.other.level" value="info"/>
<property name="log.moduleName" value="java_learn" />
<!-- 日志路径 -->
<property name="log.path" value="logs"/>
<!-- 日志文件大小 -->
<property name="log.max.size" value="500MB"/>
<!-- 定义日志输出格式-->
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n"/>
<property name="log.charset" value="UTF-8"/>
<!--控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 用来定义日志的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
</appender>
<appender name="allFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 配置日志文件的输出位置 -->
<file>${log.path}/all/${log.moduleName}_all.log</file>
<!-- 输出格式和字符集 -->
<encoder>
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
<!-- 日志文件滚动策略,防止日志文件过大,不好查阅等, -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--命名规则(按天归档)-->
<fileNamePattern>${log.path}/all/${log.moduleName}_all_%d{yyyy-MM-dd_HH:mm}.%i.log</fileNamePattern>
<!--日志最大存储天数-->
<maxHistory>60</maxHistory>
<!-- 当天的日志大小 超过${log.max.size}时,压缩日志并保存 -->
<maxFileSize>${log.max.size}</maxFileSize>
<!-- 这个Appender用来记录完整的日志,不需要过滤器 -->
</rollingPolicy>
</appender>
<!-- 日志文件输出 -->
<appender name="infoFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 设置日志不超过${log.max.size}时的保存路径,注意如果 是web项目会保存到Tomcat的bin目录 下 -->
<file>${log.path}/info/${log.moduleName}_info.log</file>
<!-- 日志输出的文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>${log.pattern}</Pattern>
<charset>${log.charset}</charset>
</encoder>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--命名规则(按天归档)-->
<fileNamePattern>${log.path}/info/${log.moduleName}_info_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大存储天数-->
<maxHistory>60</maxHistory>
<!-- 当天的日志大小 超过${log.max.size}时,压缩日志并保存 -->
<maxFileSize>${log.max.size}</maxFileSize>
</rollingPolicy>
<!--过滤器,只记录INFO级别的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志文件输出 -->
<appender name="warnFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 设置日志不超过${log.max.size}时的保存路径,注意如果 是web项目会保存到Tomcat的bin目录 下 -->
<file>${log.path}/warn/${log.moduleName}_warn.log</file>
<!-- 日志输出的文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/${log.moduleName}_warn_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大存储天数-->
<maxHistory>60</maxHistory>
<!-- 当天的日志大小 超过${log.max.size}时,压缩日志并保存 -->
<maxFileSize>${log.max.size}</maxFileSize>
</rollingPolicy>
<!-- 过滤器规则定义-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 接收的级别-->
<level>WARN</level>
<!-- 满足日志条件的时候 - ACCEPT执行-->
<onMatch>ACCEPT</onMatch>
<!-- 不满足的时候 - DENY拒绝-->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志文件输出 -->
<appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 设置日志不超过${log.max.size}时的保存路径,注意如果 是web项目会保存到Tomcat的bin目录 下 -->
<file>${log.path}/error/${log.moduleName}_error.log</file>
<!-- 日志输出的文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/${log.moduleName}_error_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大存储天数-->
<maxHistory>60</maxHistory>
<!-- 当天的日志大小 超过${log.max.size}时,压缩日志并保存 -->
<maxFileSize>${log.max.size}</maxFileSize>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- (据说)在1.3.0之后才内置输出到数据库的DbAppender-->
<!-- <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
<!-- <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
<!-- <driverClass>com.mysql.cj.jdbc.Driver</driverClass>-->
<!-- <url>jdbc:mysql://localhost:3306/java_log?serverTimezone=Asia/Shanghai</url>-->
<!-- <user>root</user>-->
<!-- <password>wlh.lkiku.space</password>-->
<!-- </connectionSource>-->
<!-- </appender>-->
<!-- 自定义输出到数据库 -->
<appender name="toMysql" class="com.example.config.DataBaseAppender">
<driverClass>com.mysql.cj.jdbc.Driver</driverClass>
<url>jdbc:mysql://localhost:3306/java_log?allowMultiQueries=true</url>
<username>root</username>
<password>wlh.lkiku.space</password>
</appender>
<!-- 为某个包下的所有类的指定Appender 这里也可以指定类名称例如:com.aa.bb.ClassName -->
<logger name="com.example.ToSqlLogger" levle="debug">
<appender-ref ref="toMysql" />
</logger>
<logger name="com.example.RollingFile" levle="info">
<appender-ref ref="infoFile"/>
<appender-ref ref="errorFile"/>
<appender-ref ref="warnFile"/>
<appender-ref ref="allFile" />
</logger>
<!-- root将级别为“DEBUG”及大于“DEBUG”的日志信息交给已经配置好的名为“Console”的appender处理,“Console”appender将信息打印到Console -->
<root level="info">
<appender-ref ref="console" /> <!-- 标识这个appender将会添加到这个logger -->
</root>
</configuration>
区别:
在log4j2的配置中分为以下几部分:
-
configuration
-
properties定义一些配置需要的配置值,例如日志文件根目录,默认级别等,便于集中管理,标签内多个property代表多个配置的值
- property
-
appenders 定义Appender目标输出源,标签内定义多个Appender
- appender
-
loggers 定义logger日志记录器,定义多个日志记录器
- logger
-
而logback如下:
- configuration
- property 定义配置值(一个,key-value)
- appender 定义Appender
- looger定义logger
- root 定义根日志记录器的配置
其他框架与slf4j结合使用
slf4j是门面型的日志框架,本身是无实现的,因此只需要在引入对应的实现日志框架,例如slf4j+jul、slf4j+log4j2以及slf4j+logback,最后通过调用slf4j统一的api接口进行日志的输出
-
对于slf4j+logback:在spring boot里,默认门面日志是slf4j,实现日志的是logback。所以就可以直接调用slf4j的api接口。
-
对于slf4j+log4j2:需要先移除spring boot自带的,在引入需要的即可,slf4j会自动去找实现,都没有的话就会报错。
移除:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- 去掉默认配置 Spring boot默认是采用的logback --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
引入:log4j2:
<!-- 引入log4j2依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
日志级别
JUL的日志级别
两个特殊级别+七个常规级别
- SEREVE:级别最高的,指严重故障的消息级别。通常,严重消息应描述相当重要的事件,这些事件将阻止正常程序执行。它们应该对最终用户和系统管理员来说是合理的理解的。此级别初始化为 1000。
- WRING:警告级别。警告是指示潜在问题的消息级别,通常,警告消息应描述最终用户或系统管理员感兴趣的事件,或指示潜在问题的事件。此级别初始化为 900。
- INFO:信息级别。通常,INFO 消息将写入控制台或其等效项。因此,INFO 级别应仅用于对最终用户和系统管理员有意义的重要消息。此级别初始化为 800。
- CONFIG:是静态配置消息的消息级别。CONFIG 消息旨在提供各种静态配置信息,以帮助调试可能与特定配置关联的问题。例如,CONFIG 消息可能包括 CPU 类型、图形深度、GUI 外观等。此级别初始化为 700。
- FINE:FINE 是提供跟踪信息的消息级别。FINE 消息可能包括次要(可恢复)故障等内容。指示潜在性能问题的问题也值得记录为 FINE。此级别初始化为 500。
- FINER:FINER 指示相当详细的跟踪消息。默认情况下,在此级别跟踪用于输入、返回或引发异常的日志记录调用。此级别初始化为 400。
- FINEST:FINEST 表示非常详细的跟踪消息。此级别初始化为 300。
- OFF:特殊级别,值关闭日志,此级别初始化int最大值
- ALL:特殊级别,指开启所有级别的日志,此级别初始化int最小值
Log4j的日志级别
两个特殊级别+六个常规级别
- FATAL:指严重故障的消息级别。级别最高的,初始值为100
- ERROR:错误级别,比较严重的消息。初始值为200
- WARN:警告级别。警告是指示潜在问题的消息级别。初始值为300
- INFO:信息级别。初始值为400
- DEBUG:debug级别的日志。初始值为500
- TRACE:详细的日志。初始值为600
- OFF:特殊级别,值关闭日志。初始值为0
- ALL:特殊级别,指开启所有级别的日志。初始值为int最大值
Logback的日志级别
两个特殊级别+五个常规级别
- ERROR:错误级别,最严重的一个级别。初始值为40000
- WARN:警告级别。警告是指示潜在问题的消息级别。初始值为30000
- INFO:信息级别。初始值为20000
- DEBUG:debug级别的日志。初始值为10000
- TRACE:详细的日志。初始值为5000
- OFF:特殊级别,值关闭日志。初始值为int最大值
- ALL:特殊级别,指开启所有级别的日志。初始值为int最小值
日志规范
- 使用Logger,不直接使用System.out.print或System.err.print打印日志信息;
- 根据level判断是否需要打印该级别日志,避免无效的日志记录;
- 为日志添加必要的上下文信息,例如请求路径、调用方法、异常信息等;
- 尽量避免在日志信息中使用敏感信息,例如密码、密钥等。
动态修改日志级别
-
通过代码中的形式进行动态的修改级别,可以实现在运行的过程中进行对级别进行重新修改。
例如:jul的动态修改
package com.example.demo; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.logging.Level; import java.util.logging.Logger; /** * @Classname DynamicUpdateLevel * @Description TODO * @Version 1.0.0 * @Date 2023/5/29 22:46 * @Created by wlh12 */ @SpringBootTest public class DynamicUpdateLevel { @Test void aVoid() throws InterruptedException { Logger logger = Logger.getLogger(DynamicUpdateLevel.class.getName()); logger.setLevel(Level.ALL); logger.log(Level.SEVERE, "Severe message"); logger.log(Level.WARNING, "Warning message"); logger.log(Level.INFO, "Info message"); Thread.sleep(2000); logger.setLevel(Level.WARNING); System.out.println("====分割线========="); logger.log(Level.SEVERE, "Severe message"); logger.log(Level.WARNING, "Warning message"); logger.log(Level.INFO, "Info message"); } }
例如:logback的动态修改
// 加载slf4j的logger,通过slf4j的api接口使用logback Logger logger = LoggerFactory.getLogger(QuickStart.class); logger.error("error message"); logger.warn("wring message"); logger.info("info message"); logger.debug("debug message"); logger.trace("trace message"); Thread.sleep(2000); // 依旧是修改对应的实现日志框架的日志级别即可。 ((ch.qos.logback.classic.Logger) logger).setLevel(Level.DEBUG); logger.error("error message"); logger.warn("wring message"); logger.info("info message"); logger.debug("debug message"); logger.trace("trace message");
-
对不同的模块进行设置不同的Appender。
例如:对com.example.RollingFile下的采用的是定义的Appender的来实现。
<logger name="com.example.RollingFile" levle="info"> <appender-ref ref="infoFile"/> <appender-ref ref="errorFile"/> <appender-ref ref="warnFile"/> <appender-ref ref="allFile" /> </logger>