【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。

一、日志框架介绍

1、浅谈与slfj4、log4j、logback的关系

  • Slf4j

SLF4J(Simple Logging Facade for Java)是一个日志框架的抽象层,可以与不同的日志实现进行绑定。它允许开发人员在代码中使用统一的日志接口,而无需关心具体的日志实现。

简单来讲就是slf4j是一系列的日志门面,也可以理解为 slf4j 是接口,而 logbacklog4j具体实现了这些接口的日志框架,slf4j 具备很高的易用性和很好的抽象性。

  • Log4j

Logback是Log4j的后继版本,由Log4j的作者开发。相比Log4j,Logback具有更好的性能和更丰富的功能,同时也更易于配置和扩展。

  • Logback

Logback是Log4j的后继版本,由Log4j的作者开发。相比Log4j,Logback具有更好的性能和更丰富的功能,同时也更易于配置和扩展。

  • Log4j2

log4j2是log4j的代替升级版,之前log4j曾爆出“核弹级”漏洞,现在已经不推荐使用了。

<br>

2、性能方面

在测试环境和条件相同的情况下,log4j2 全面优于 logback, log4j2性能是 logback的两倍。

建议使用Log4j2,因为它是三种框架中最快、最先进的。如果性能不是你的最高优先级,那么Logback仍然是一个不错的选择。

<br>

3、Slf4j使用方法

使用SLF4J编写日志消息非常简单。首先需要调用 LoggerFactory 上的 getLogger 方法来实例化一个新的 Logger 对象。一共有两种方法:

  • 方法1:直接使用

使用 org.slf4j.LoggerFactorygetLogger 方法获取Logger实例,推荐 private static final。然后就可以调用记录器上的 errorwarninfodebugtrace 方法之一,以编写具有相应日志级别的日志消息。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        // 日志级别默认从高到低:ERROR,WARN,INFO,DEBUG,TRACE
        log.error("This is an error message");
        log.warn("This is a warn message");
        log.info("This is an info message");
        log.debug("This is a debug message");
        log.trace("This is a trace message");
    }
}
  • 方法2:使用lombok(推荐)

直接在类上打上lombok的注解, 这个方法是最简单,代码量最小,编程效率最高的, 而且lombok组件在很多场景都很好用

  • 引入lombok坐标
<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
</dependency>
  • 使用Lombok中的Slf4j
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Main {
    public static void main(String[] args) {
        log.error("This is an error message");
        log.warn("This is a warn message");
        log.info("This is an info message");
        log.debug("This is a debug message");
        log.trace("This is a trace message");
    }
}

<br>


<br>

二、log4j配置

Apache Log4J是一个非常古老的日志框架,多年来一直是最流行的日志框架。它包含了一些基本概念,如分层日志级别和日志记录器,这些概念仍然被现代日志框架使用。

官网:https://logging.apache.org/log4j/1.x/

开发团队在2015年宣布了Log4j的生命终结。虽然很多遗留项目仍在使用它,但如果我们启动一个新项目,推荐使用log4j2或logback。

在讨论Log4j2和Logback之前,让我们先快速了解一下所需的依赖项和配置。

  • log4j依赖
<!-- log4j日志 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  • log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n"/>
        </layout>
    </appender>
    <logger name="java.sql">
        <level value="debug"/>
    </logger>
    <logger name="org.apache.ibatis">
        <level value="info"/>
    </logger>
    <root>
        <level value="debug"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

<br>


<br>

三、log4j2配置

官网:https://logging.apache.org/log4j/2.x/

1、SpringBoot整合Log4j2

pom.xml中排除SpringBoot自带的日志依赖(SpringBoot默认选用SLF4J和logback来记录日志)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--排除自带的日志依赖-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

引入log4j2依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>3.2.5</version>
</dependency>

<br>

2、非SpringBoot项目引入的依赖

  • log4j2所必须的依赖
<!-- Log4j2 dependencies -->
<!-- log4j2 门面API -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.1</version>
</dependency>
<!-- log4j2的日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
</dependency>
<!-- 为slf4j绑定日志实现 log4j2的适配器 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.13.3</version>
</dependency>
  • 若是日志使用的是slf4j+log4j2,并使用log4j2的异步日志,引入如下依赖
<!-- 使用slf4j作为日志的门面,使用log4j2来记录日志 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
<!-- log4j2 门面API -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.1</version>
</dependency>
<!-- log4j2的日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
</dependency>
<!-- 为slf4j绑定日志实现 log4j2的适配器 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.13.3</version>
</dependency>
<!-- log4j2并发编程依赖包,如果配置异步日志需要引入下面两个 -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.0</version>
</dependency>

<br>

3、log4j2-spring.xml文件(Spring项目)或log4j2.xml(非Spring项目)

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--
status:用来指定log4j本身打印日志的级别,框架默认级别为warn (若是设置debug,log4j的配置过程也会展现出来)
monitorInterval:用于指定log4j自动重新配置的监测间隔时间,单位是秒(s),最小的间隔时间是5s。(修改配置文件后无需重新发动应用,可以自动加载)
-->
<configuration status="warn" monitorInterval="30">
    <!-- 全局参数 -->
    <properties>
        <!-- 日志打印级别 -->
        <property name="LOG_LEVEL">DEBUG</property>
        <!-- APP名称 -->
        <property name="APP_NAME" value="Mybatis"/>
        <!-- 日志文件存储路径 -->
        <property name="LOG_HOME">../logs</property>
        <!-- 日志编码 -->
        <property name="CHARSET" value="UTF-8"/>
        <!-- 存储天数 -->
        <property name="LOG_MAX_HISTORY" value="60d"/>
        <!-- 单个日志文件最大值, 单位 = KB, MB, GB -->
        <property name="LOG_MAX_FILE_SIZE" value="10MB"/>
        <!-- 每天每个日志级别产生的文件最大数量 -->
        <property name="LOG_TOTAL_NUMBER_DAILY" value="100"/>
        <!-- 压缩文件的类型,支持zip和gz,建议Linux用gz,Windows用zip -->
        <property name="ARCHIVE_FILE_SUFFIX" value="zip"/>
        <!-- 日志文件名 -->
        <property name="LOG_FILE_NAME" value="${LOG_HOME}"/>
        <property name="FILE_NAME_PATTERN" value="${LOG_HOME}/%d{yyyy-MM-dd}"/>
        <!--日志输出格式-控制台彩色打印-->
        <property name="ENCODER_PATTERN_CONSOLE">%blue{%d{yyyy-MM-dd HH:mm:ss.SSS}} | %highlight{%-5level}{ERROR=Bright
            RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} | %yellow{%t} |
            %cyan{%c{1.}} : %white{%msg%n}
        </property>
        <!--日志输出格式-文件-->
        <property name="ENCODER_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %5pid --- [%15.15t] %c{1.} [%L] : %m%n
        </property>
        <!--日志输出格式-控制台彩色打印-->
        <!--<property name="DEFAULT_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight{%-5level} %style{%5pid}{bright,magenta} -&#45;&#45; [%17.17t] %cyan{%c{1.} [%L]} : %m%n
        </property>-->
        <property name="DEFAULT_PATTERN">%blue{%d{yyyy-MM-dd HH:mm:ss,SSS}} %cyan{[%thread]} %highlight{%-5level}{ERROR=Bright
            RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Magenta, TRACE=Bright White} %cyan{%logger [%L]} : %m%n
        </property>
    </properties>
    <Appenders>
        <!-- 控制台的输出配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 输出日志的格式 -->
            <PatternLayout pattern="${DEFAULT_PATTERN}" charset="${CHARSET}"/>
        </Console>
        <!-- 新增包含所有级别日志的文件 Appender -->
        <RollingFile name="RollingFileAllLevels" fileName="${LOG_FILE_NAME}/all.log"
                     filePattern="${FILE_NAME_PATTERN}/${APP_NAME}-all.%d{yyyy-MM-dd HH.mm}-%i.log">
            <Filters/>  <!-- 不过滤任何日志级别 -->
            <!-- 日志输出格式-文件 -->
            <PatternLayout pattern="${ENCODER_PATTERN}"/>
            <!-- 触发策略 -->
            <Policies>
                <!-- 归档每天的文件,每天滚动一次 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制单个文件大小,日志达到size滚动一次 -->
                <SizeBasedTriggeringPolicy size="${LOG_MAX_FILE_SIZE}"/>
            </Policies>
            <!-- 限制每天文件个数 -->
            <DefaultRolloverStrategy compressionLevel="9" max="${LOG_TOTAL_NUMBER_DAILY}">
                <!-- 日志保留策略,日志只保留60天 -->
                <Delete basePath="${LOG_HOME}" maxDepth="1">
                    <IfFileName glob="*-all.*.log"/>
                    <IfLastModified age="${LOG_MAX_HISTORY}"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <!-- 打印出所有的info及以下级别的信息,每次大小超过size进行压缩,作为存档-->
        <RollingFile name="RollingFileAll" fileName="${LOG_FILE_NAME}/info.log"
                     filePattern="${FILE_NAME_PATTERN}/${APP_NAME}-info.%d{yyyy-MM-dd HH.mm}-%i.log">
            <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="${LOG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 输出日志的格式 -->
            <PatternLayout pattern="${ENCODER_PATTERN}"/>
            <Policies>
                <!-- 归档每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制单个文件大小 -->
                <SizeBasedTriggeringPolicy size="${LOG_MAX_FILE_SIZE}"/>
            </Policies>
            <!-- 限制每天文件个数 -->
            <DefaultRolloverStrategy compressionLevel="9" max="${LOG_TOTAL_NUMBER_DAILY}">
                <Delete basePath="${LOG_HOME}" maxDepth="1">
                    <IfFileName glob="*-info.*.log"/>
                    <IfLastModified age="${LOG_MAX_HISTORY}"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="RollingFileDebug" fileName="${LOG_FILE_NAME}/debug.log"
                     filePattern="${FILE_NAME_PATTERN}/${APP_NAME}-debug.%d{yyyy-MM-dd HH.mm}-%i.log">
            <Filters>
                <ThresholdFilter level="DEBUG"/>
                <ThresholdFilter level="INFO" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="${ENCODER_PATTERN}"/>
            <Policies>
                <!-- 归档每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制单个文件大小 -->
                <SizeBasedTriggeringPolicy size="${LOG_MAX_FILE_SIZE}"/>
            </Policies>
            <!-- 限制每天文件个数 -->
            <DefaultRolloverStrategy compressionLevel="9"
                                     max="${LOG_TOTAL_NUMBER_DAILY}">
                <Delete basePath="${LOG_HOME}" maxDepth="1">
                    <IfFileName glob="*-debug.*.log"/>
                    <IfLastModified age="${LOG_MAX_HISTORY}"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${LOG_FILE_NAME}/warn.log"
                     filePattern="${FILE_NAME_PATTERN}/${APP_NAME}-warn.%d{yyyy-MM-dd HH.mm}-%i.log">
            <Filters>
                <ThresholdFilter level="WARN"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="${ENCODER_PATTERN}"/>
            <Policies>
                <!-- 归档每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制单个文件大小 -->
                <SizeBasedTriggeringPolicy size="${LOG_MAX_FILE_SIZE}"/>
            </Policies>
            <!-- 限制每天文件个数 -->
            <DefaultRolloverStrategy compressionLevel="9" max="${LOG_TOTAL_NUMBER_DAILY}">
                <Delete basePath="${LOG_HOME}" maxDepth="1">
                    <IfFileName glob="*-warn.*.log"/>
                    <IfLastModified age="${LOG_MAX_HISTORY}"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${LOG_FILE_NAME}/error.log"
                     filePattern="${FILE_NAME_PATTERN}/${APP_NAME}-error.%d{yyyy-MM-dd HH.mm}-%i.log">
            <Filters>
                <ThresholdFilter level="ERROR"/>
            </Filters>
            <PatternLayout pattern="${ENCODER_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_FILE_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy compressionLevel="9" max="${LOG_TOTAL_NUMBER_DAILY}">
                <Delete basePath="${LOG_HOME}" maxDepth="1">
                    <IfFileName glob="*-error.*.log"/>
                    <IfLastModified age="${LOG_MAX_HISTORY}"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>
    <!-- 只有定义了logger并引入以上Appenders,Appender才会生效 -->
    <Loggers>
        <!-- Root:指定项目的根日志,如果没有单独指定Logger,那么默认使用该Root日志输出 -->
        <root level="${LOG_LEVEL}">
            <!-- AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender -->
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileAll"/>
            <appender-ref ref="RollingFileDebug"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
            <!-- 添加新的Appender引用 -->
            <appender-ref ref="RollingFileAllLevels"/>
        </root>
    </Loggers>
</configuration>

在log4j2中, 共有8个级别,按照从低到高为:OFF(关闭)>FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)>Trace(追踪)>All(所有)。

  • OFF:最高等级的,用于关闭所有日志记录。
  • Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
  • Error:输出错误信息日志。
  • Warn:输出警告及warn以下级别的日志。
  • Info:消息在粗粒度级别上突出强调应用程序的运行过程。
  • Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
  • Trace:是追踪,就是程序推进一下。
  • All:最低等级的,用于打开所有日志记录。

从左到右打印的内容越来越详细,程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。

  • 控制台设置日志彩色输出

在Log4j 2.10以前的版本,pattern中配置%highlight属性是可以正常打印彩色日志的,例如:

<property name="DEFAULT_PATTERN">%blue{%d{yyyy-MM-dd HH:mm:ss,SSS}} %cyan{[%t]} %highlight{%-5level}{ERROR=Bright
    RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Magenta, TRACE=Bright White} %cyan{%logger [%L]} : %m%n
</property>

通过查阅官方文档,发现在2.10版本以后,Log4j2默认关闭了Jansi(一个支持输出ANSI颜色的类库)

IDEA中,点击右上角->Edit Configurations,在VM options中添加配置 log4j.skipJansi 这个全局属性即可。

-Dlog4j.skipJansi=false

启动应用,显示效果如下:

<br>


<br>

四、logback配置

Logback的架构分为三个模块,logback-corelogback-classiclogback-access

Logback core提供了日志框架的核心功能。Logback classic为核心功能添加了更多功能,例如对SLF4J的本机支持。logback access将其与servlet容器集成,以便可以使用它编写HTTP访问日志。

官网:https://logback.qos.ch/

SpringBoot官方推荐使用带有-spring的文件名作为配置,如logback-spring.xml而不是logback.xml

这样命名的好处在于:因为标准的logback.xml配置文件加载得太早,所以不能在其中使用扩展,需要使用logback-spring.xml

当然上面是默认的命名规则,如果你想自定义xml的名称,自定义路径,可以通过logging.config属性配置:logging.config=classpath:logging-config.xml

  • 引入logback依赖

只需要定义对logback-classic的依赖。它包括对logback core和SLF4J API的依赖关系。

<!-- slf4j日志门面的一个具体实现 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
  • logback-spring.xml、logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="10 seconds" debug="false">
    <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
    <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
    <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="log" />
    <property name="console_log_pattern"
              value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
    <property name="charset" value="UTF-8"/>
    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
         <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
             <level>DEBUG</level>
         </filter>
        <encoder>
            <pattern>${console_log_pattern}</pattern>
        </encoder>
    </appender>
    <!--输出到文件,只记录INFO级别信息-->
    <appender name="info_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/roll_info/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>${console_log_pattern}</pattern>
            <charset>${charset}</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 如果超过10MB就删除 -->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>10MB</maxFileSize>
        </triggeringPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--输出到文件,只记录WARN级别信息-->
    <appender name="warn_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    </appender>
    <!--输出到文件,只记录ERROR级别信息-->
    <appender name="error_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    </appender>
    <!--
    root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
    level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
    可以包含零个或多个appender元素。
    -->
    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="info_file" />
        <appender-ref ref="warn_file"/>
        <appender-ref ref="error_file"/>
    </root>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
        <logger>仅有一个name属性,
        一个可选的level和一个可选的additivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              如果未设置此属性,那么当前logger将会继承上级的级别。
        additivity:是否向上级logger传递打印信息,默认是true
    -->
    <!-- 使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
         第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
         第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
    -->
    <logger name="com.hyh.logback.web.LogTestController" level="WARN" additivity="false">
        <appender-ref ref="console"/>
        <appender-ref ref="warn_file"/>
        <appender-ref ref="error_file"/>
    </logger>
    <!--    如果多环境开发可以用springProfile -->
    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <!--可以输出项目中的debug日志,包括mybatis的sql日志-->
        <logger name="com.hyh.logback.web" level="DEBUG">
            <appender-ref ref="console"/>
        </logger>
        <!--
            root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
            level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
            可以包含零个或多个appender元素。
        -->
        <root level="INFO">
            <appender-ref ref="console"/>
        </root>
    </springProfile>
</configuration>

最终的效果,会在项目路径下生成日志文件:/log/info/log-info-2024-11-10.0.log,并且日志文件的策略也在xml中定义。

  • 简易版logback配置(只在控制台输出日志信息,不记录到文件)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="DEBUG">
        <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
        <appender-ref ref="STDOUT" />
    </root>
    <!-- 根据特殊需求指定局部日志级别 -->
    <logger name="com.aizen.crowd.mapper" level="DEBUG"/>
</configuration>

<br>

最佳实践

  1. 滚动日志,永远不让磁盘满
  • 根据运行环境要求, 配置最大日志数量
  • 根据运行环境要求, 配置日志文件最大大小
  1. 日志如何使用才方便统计和定位问题
  • 统一日志格式,比如统一先打印方法名称,再打印参数列表
  • 写好要打印参数的 toString方法
  1. 日志如何配置性能才比较高
  • 日志配置应该遵循结构清晰,尽量简化的原则,能不让框架计算的,尽量不让框架计算, 比如方法名,行号等
  1. 全公司,或者个人使用习惯统一,这样有助于后续的日志收集、分析和统计

<br>


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
255 3
|
2月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
103 1
|
2月前
|
SQL XML 监控
SpringBoot框架日志详解
本文详细介绍了日志系统的重要性及其在不同环境下的配置方法。日志用于记录系统运行时的问题,确保服务的可靠性。文章解释了各种日志级别(如 info、warn、error 等)的作用,并介绍了常用的日志框架如 SLF4J 和 Logback。此外,还说明了如何在 SpringBoot 中配置日志输出路径及日志级别,包括控制台输出与文件输出的具体设置方法。通过这些配置,开发者能够更好地管理和调试应用程序。
|
4月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
136 3
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1650 14
|
2月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
35 0
|
2月前
|
数据可视化
Tensorboard可视化学习笔记(一):如何可视化通过网页查看log日志
关于如何使用TensorBoard进行数据可视化的教程,包括TensorBoard的安装、配置环境变量、将数据写入TensorBoard、启动TensorBoard以及如何通过网页查看日志文件。
223 0
|
2月前
|
存储 分布式计算 NoSQL
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
45 0
|
2月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
60 0
|
3月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。