Java日志体系-笔记

日志体系

所谓的日志就是记录程序的运行而生成的文档

  • 日志框架:

    • 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 种方式之一完成:

  1. 通过以 XML、JSON、YAML 或属性格式编写的配置文件(常用)。
  2. 以编程方式,通过创建配置工厂和配置实现。
  3. 以编程方式,通过调用配置接口中公开的 API 来添加 组件到默认配置。
  4. 以编程方式,通过调用内部记录器类上的方法。

自动化配置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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>
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值