日志框架之Logback的使用与详细配置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日志框架之Logback的使用与详细配置相关的知识,希望对你有一定的参考价值。

(日志框架之Logback的使用与详细配置)

Logback

概述

Logback特点:

高性能:采用异步日志机制,可以将日志操作和业务逻辑分离,从而大幅度提升系统的性能。

灵活的配置:支持多种不同的配置方式,包括基于XML、Groovy、JSON等格式的配置文件,同时还支持通过代码进行配置。

多种日志级别:支持6种不同的日志级别,包括TRACE、DEBUG、INFO、WARN、ERROR和FATAL,用户可以根据需要选择合适的日志级别。

多种输出方式:支持多种不同的输出方式,包括控制台输出、文件输出、邮件发送等。用户可以根据需要选择合适的输出方式。

插件丰富:提供许多有用的插件,例如logstash-logback-encoder,可以将日志输出到ELK(Elasticsearch、Logstash、Kibana)平台上进行分析和可视化。

易于集成:Logback与Spring、Hibernate、JUnit等框架都有很好的集成,可以方便地进行应用程序的日志输出管理。

Logback三个主要模块:

1.logback-core

2.logback-classic

3.logback-access

配置文件结构

配置文件结构层次如下:

configuration : 配置文件的根元素,它包含了多个子元素:appender、logger 和 root

	appender : 定义了输出端,可以是控制台、文件、网络等,每一个appender都需要有一个唯一的名称和一个类定义
	
	logger : 定义了日志记录器,用于记录指定类的日志信息。logger元素需要指定一个名称和一个级别,以及一个可选的appender-ref子元素,用于将日志记录器连接到一个appender
	
	root : 定义了根日志记录器,它会接收所有未被其他logger接收的日志事件

Logback 的配置文件通常是 XML 格式,文件名为 logback.xml。它的结构如下:

<!--
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!--
     定义变量值的标签,property标签有两个属性,name和value;过property定义的值会被插入到logger上下文中。定义变量后,可以使$name来使用变量
     -->
    <property name="AppName" value="demo"/>
    <!--
    每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用contextName标签设置成其他名字,用于区分不同应用程序的记录
    -->
    <contextName>$AppName</contextName>
    <!--负责写日志的组件-->
    <appender>
        <filter></filter>
    </appender>
    <!--用来设置某一个包或者具体的某一个类的日志打印级别以及指定appender。-->
    <logger>
        <appender-ref ref=""/>
    </logger>
    <!---根logger,也是一种logger,且只有一个level属性-->
    <root>
    </root>
</configuration>

日志级别

ALL < TRACE < DEBUG < INFO < WARN < ERROR <FATAL <OFF
ALL:最低等级的,用于打开所有日志记录

TRACE:是最详细的日志信息,通常用于诊断问题和追踪代码执行流程。在生产环境中,应该关闭TRACE级别的日志输出,以避免影响系统性能

DEBUG:是调试信息,用于调试应用程序。在生产环境中,建议将DEBUG级别的日志输出关闭

INFO:是普通的信息记录,通常用于向用户展示可读的操作结果或执行状态。例如,当用户成功登录时,可以记录一条 INFO 级别的日志

WARN:表示警告信息,通常用于记录一些不严重但需要注意的问题。例如,当系统资源紧张时,可以记录一条WARN级别的日志

ERROR:表示错误信息,通常用于记录系统运行时发生的错误。例如,当数据库连接失败时,可以记录一条ERROR级别的日志

FATAL:表示致命错误,通常用于记录系统崩溃或无法恢复的错误。例如,当出现内存泄漏或硬盘损坏时,可以记录一条FATAL级别的日志

OFF:最高等级的,用于关闭所有日志记录。

Logback基本使用

与Maven项目集成

1.添加依赖

       <!--slf4j日志门面-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        <!--logback日志实现-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

2.配置 Logback

3.使用 Logback记录日志

public class Logback 

    public static final Logger LOGGER = LoggerFactory.getLogger(Logback.class);

    @Test
    public void test() 
            LOGGER.error("error");
            LOGGER.warn("wring");
            LOGGER.info("info");
            LOGGER.debug("debug");
            LOGGER.trace("trace");
    

18:05:38.202 [main] ERROR cn.ybzy.Logback - error
18:05:38.206 [main] WARN cn.ybzy.Logback - wring
18:05:38.207 [main] INFO cn.ybzy.Logback - info
18:05:38.207 [main] DEBUG cn.ybzy.Logback - debug

与Spring Boot集成

logging:
	config: classpath:logback.xml

用法

public class MyTest 
    private static final Logger logger = LoggerFactory.getLogger(MyTest.class);

    public static void main(String[] args) 
        logger.info("info.....");
        logger.warn("warn" + ".....");
        logger.error("error,msg=", "error....");
    

与lombok集成

logback和lombok集成,使用@Slf4j注解标注类,直接使用log对象,需添加lombok依赖

    <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
@Slf4j
public class MyTest 

    public static void main(String[] args) 
        log.info("info.....");
        log.warn("warn" + ".....");
        log.error("error,msg=", "error....");
    

Logback配置

logback组件之间的关系

1. Logger:日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。

2. Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。

3. Layout:负责把事件转换成字符串,格式化的日志信息的输出。在logback中Layout对象被封装在encoder中。

Logger配置

logger就是在程序需要使用的Logger对象

    <!--
        name:指定受此logger约束的某一个包或者具体的某一个类。或者用于自定义日志名称
        level:设置打印级别(TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF)
        addtivity:描述是否向上级logger传递打印信息。默认是true。
    -->
    <logger name="com.chongba.schedule.service.VisiableThreadPool" additivity="false">
        <!--appender-ref则是用来指定具体appender-->
        <appender-ref ref="file.thread"/>
    </logger>

自定义日志名称的使用

    <!--自定义日志名称-->
    <logger name="web" additivity="false">
        <appender-ref ref="console"/>
    </logger>
private static final Logger threadLogger = LoggerFactory.getLogger("web");

Appender配置

ConsoleAppender配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--属性配置管理,供引用使用-->

    <!--定义日志输出内容的格式-->
    <!--日志输出格式:
       %-5level
       %dyyyy-MM-dd HH:mm:ss.SSS日期
       %c类的全限定名称
       %M为method
       %L为行号
       %thread线程名称
       %m或者%msg为信息
       %n换行
     -->
    <property name="pattern" value="[%-5level] %dyyyy-MM-dd HH:mm:ss.SSS %c %M %L [%thread] %m%n"></property>

    <!--控制台日志输出的appender-->
    
    <!--name属性指定appener的名称,class指定appender的类型-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--控制输出流对象 默认 System.out(黑色) 改为 System.err(红色)-->
        <target>System.err</target>
        
        <!--日志消息格式配置-->
        
        <!-- 对记录事件进行格式化。1.把日志信息转换成字节数组 2.把字节数组写入到输出流 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--引用属性配置管理中定义的某个属性-->
            <pattern>$pattern</pattern>
            <charset>utf-8</charset>
        </encoder>
        
    </appender>

    <!--root logger 配置-->
    <root level="ALL">
        <appender-ref ref="console"/>
    </root>

</configuration>
[ERROR] 2021-03-21 18:16:14.273 cn.ybzy.Logback test 13 [main] error
[WARN ] 2021-03-21 18:16:14.277 cn.ybzy.Logback test 14 [main] wring
[INFO ] 2021-03-21 18:16:14.278 cn.ybzy.Logback test 15 [main] info
[DEBUG] 2021-03-21 18:16:14.278 cn.ybzy.Logback test 16 [main] debug
[TRACE] 2021-03-21 18:16:14.279 cn.ybzy.Logback test 17 [main] trace

FileAppender配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--属性配置管理,供引用使用-->

    <!--定义日志输出内容的格式-->
    <!--日志输出格式:
       %-5level
       %dyyyy-MM-dd HH:mm:ss.SSS日期
       %c类的全限定名称
       %M为method
       %L为行号
       %thread线程名称
       %m或者%msg为信息
       %n换行
     -->
    <property name="pattern" value="[%-5level] %dyyyy-MM-dd HH:mm:ss.SSS %c %M %L [%thread] %m%n"></property>

    <!--定义日志文件保存路径属性-->
    <property name="log_dir" value="d:/logs"></property>

    <!--日志文件输出的 appender-->
    <appender name="file" class="ch.qos.logback.core.FileAppender">
        <!--日志文件保存路径-->
        <file>$log_dir/logback.log</file>
        <!--日志消息格式配置-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>$pattern</pattern>
        </encoder>
    </appender>

    <!--root logger 配置-->
    <root level="ALL">
        <appender-ref ref="file"/>
    </root>
    
</configuration>

htmlAppender配置

   <!--html格式日志文件输出appender-->
    <appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
        <!--日志文件保存路径-->
        <file>$log_dir/logback.html</file>
        <!--html 消息格式配置-->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>%-5level%dyyyy-MM-dd HH:mm:ss.SSS%c%M%L%thread%m</pattern>
            </layout>
        </encoder>
    </appender>

RollingFileAppender配置

rollingPolicy子标签:滚动策略。常用的滚动策略如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--属性配置管理,供引用使用-->
    <!--定义日志输出内容的格式-->
    <property name="pattern" value="[%-5level] %dyyyy-MM-dd HH:mm:ss.SSS %c %M %L [%thread] %m%n"></property>

    <!--定义日志文件保存路径属性-->
    <property name="log_dir" value="d:/logs"></property>
    
    <!--日志拆分和归档压缩的appender对象-->
    <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志文件保存路径-->
        <file>$log_dir/roll_logback.log</file>
        <!--日志消息格式配置-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>$pattern</pattern>
	        <charset>utf-8</charset>
        </encoder>
        <!--指定拆分规则-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--按照时间和压缩格式声明拆分的文件名-->
            <fileNamePattern>$log_dir/rolling.%dyyyy-MM-dd.log%i.zip</fileNamePattern>
            <!-- <fileNamePattern>$log_dir/rolling.%dyyyy-MM-dd.log%i</fileNamePattern>-->
            <!--日志文件保留天数-->
        	<MaxHistory>30</MaxHistory>
            <!--按照文件大小拆分,日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始 -->
            <maxFileSize>1MB</maxFileSize>
        </rollingPolicy>
    </appender>


    <!--root logger 配置-->
    <root level="ALL">
        <appender-ref ref="rollFile"/>
    </root>

</configuration>

Filter配置

filter的类型

LevelFilter:

ThresholdFilter:

<!--日志拆分和归档压缩的appender对象-->
    <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <!--日志级别过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--日志过滤规则-->
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        
    </appender>

异步日志配置

	<!--异步日志-->
    <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
        <!--指定某个具体的appender-->
        <appender-ref ref="rollFile"/>
    </appender>

    <!--root logger 配置-->
    <root level="ALL">
        <appender-ref ref="async"/>
    </root>

示例配置

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <property name="LOG_CONTEXT_NAME" value="web-app"/>
    <!--定义日志文件的存储地址 勿在LogBack的配置中使用相对路径-->
    <property name="LOG_HOME" value="logs/$LOG_CONTEXT_NAME"/>
    <!-- 定义日志上下文的名称 -->
    <contextName>$LOG_CONTEXT_NAME</contextName>

    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%dyyyy-MM-dd HH:mm:ss.SSS [%thread] %-5level %logger56.%method:%L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>

    <!--info日志统一输出-->
    <appender name="file.info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Prudent>true</Prudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名,按小时生成-->
            <FileNamePattern>$LOG_HOME/%dyyyy-MM-dd/info/info.%dyyyy-MM-dd-HH.%i.log</FileNamePattern>
            <!--日志文件输出的文件名,按天生成-->
            <!--<FileNamePattern>$LOG_HOME/%dyyyy-MM-dd/error/error.%dyyyy-MM-dd.%i.log</FileNamePattern>-->
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始 -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
            <pattern>%dyyyy-MM-dd HH:mm:ss.SSS [%thread] %-5level %logger56.%method:%L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <!--错误日志统一输出-->
    <appender name="file.error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--省略,参考file.info appender-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--warn日志统一输出-->
    <appender name="file.warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--省略,参考file.info appender-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--  日志输出级别 -->
    <root level="debug">
        <appender-ref ref="console"/>
        <appender-ref ref="file.error"/>
        <appender-ref ref="file.info"/>
        <appender-ref ref="file.warn"/>
    </root>

    <!-- 某类/包下的所有日志使用file.info appender输出-->
    <logger name="cn.ybzy.demo.controller.TestController" additivity="false">
        <appender-ref ref="file.info"/>
    </logger>

	<logger name="org.hibernate.SQL">
        <level value="DEBUG"/>
    </logger>

</configuration>

重学SpringBoot系列之日志框架与全局日志管理


日志框架的体系结构

五花八门的日志工具包

日志框架

  • JDK java.util.logging 包:java.util.logging 是 jdk1.4 发布的 java 日志包,可以说是应用比较久远的日志工具包
  • log4j: apache 的一个开源项目,提供了强有力的 java 日志支持,甚至他也提供了其他语言包括
    C、C++、.Net、PL/SQL 的接口,从而实现多语言并存的分布式环境日志打印。目前已经停止更新,所以不推荐使用。
  • Logback:由log4j创始人设计的另一个开源日志组件,作为Spring Boot默认的日志框架,应用比较广泛。
  • log4j2 :Apache Log4j2是对Log4j的升级,它比其前身Log4j1.x提供了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些问题。它基于LMAX公司开发Disruptor(一个开源的无锁并发框架),改善了Log4j和Logback在架构设计方面的缺陷,具有超高的吞吐量和低延迟,性能比Log4j1.x和Logback更好。

日志门面

  • commons-logging: Apache commons类库中的一员,他作为一个日志门面,能够自动选择使用 log4j 还是JDK logging,但是他不依赖Log4j,JDK Logging的API。如果项目的classpath中包含了log4j的类库,就会使用log4j,否则就使用JDK Logging。
  • SLF4J:可以说是目前应用最为广泛的日志门面了,它提供了一个日志抽象层,允许你在后台使用任意一个日志类库。如:log4j、log4j2、logback

日志门面存在的意义

为什么不直接使用日志框架,而是搞出一个日志门面?

日志门面(SLF4J)主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架来实现,例如log4j和logback等。 对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、log4j2、logback等),中间使用桥接器完成桥接。

前面介绍的几种日志框架,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性要求。有了SLF4J这个门面之后,程序员永远都是面向SLF4J编程,可以实现简单快速地替换底层的日志框架而不会导致业务代码需要做相应的修改

在使用 SLF4J 进行日志记录时,通常都需要在每个需要记录日志的类中定义 Logger 变量,如下所示:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
public class LogTestController 
    private static final Logger logger = LoggerFactory.getLogger(LogTestController.class);

    @GetMapping("/test")
    public void test()
        logger.trace("Trace 日志...");
        logger.debug("Debug 日志...");
        logger.info("Info 日志...");
        logger.warn("Warn 日志...");
        logger.error("Error 日志...");
    

这显然属于重复性劳动,降低了开发效率,如果你在项目中引入了 Lombok,那么可以使用它提供的 @Slf4j 注解来自动生成上面那个变量,默认的变量名是 log,如果我们想采用惯用的 LOGGER 变量名,那么可以在工程的 main/java 目录中增加 lombok.config 文件,并在文件中增加 lombok.log.fieldName=LOGGER 的配置项即可


日志框架选型

  • Spring Boot 默认的日志记录框架使用的是 Logback
  • 其中 Log4j 可以认为是一个过时的函数库,已经停止更新,不推荐使用,相比之下,性能和功能也是最差的。
  • logback 虽然是 Spring Boot 默认的,但性能上还是不及 Log4j2,因此,在现阶段,日志记录首选Log4j2。

SLF4J + Log4j2 是我们推荐的日志记录选型。

性能测试结果


Log4j2官网


日志级别

细说各日志框架整合配置前,我们先来大致了解下,最常见的日志的几个级别:ERROR, WARN, INFO, DEBUG和TRACE。像其他的,比如ALL、OFF和FATAL之类的开发过程中应该基本上是不会涉及的。所以以下从低到高一次介绍下常见的日志级别。

  • TRACE:追踪。一般上对核心系统进行性能调试或者跟踪问题时有用,此级别很低,一般上是不开启的,开启后日志会很快就打满磁盘的。
  • DEBUG:调试。这个大家应该不陌生了。开发过程中主要是打印记录一些运行信息之类的。
  • INFO:信息。这个是最常见的了,大部分默认就是这个级别的日志。一般上记录了一些交互信息,一些请求参数等等。可方便定位问题,或者还原现场环境的时候使用。此日志相对来说是比较重要的。
  • WARN:警告。这个一般上是记录潜在的可能会引发错误的信息。比如启动时,某某配置文件不存在或者某个参数未设置之类的。
  • ERROR:错误。这个也是比较常见的,一般上是在捕获异常时输出,虽然发生了错误,但不影响系统的正常运行。但可能会导致系统出错或是宕机等。

日志级别从小到大为trace<debug<info<warn<error<fatal,由于通常日志框架默认日志级别设置为INFO,因此上面样例trace和debug级别的日志都看不到。

2020-08-17 13:59:16.566  INFO c.z.b.l.controller.LogTestController     : Info 日志...
2020-08-17 13:59:16.566  WARN  c.z.b.l.controller.LogTestController     : Warn 日志...
2020-08-17 13:59:16.566 ERROR  c.z.b.l.controller.LogTestController     : Error 日志...

常见术语概念解析

  • appender:主要控制日志输出到哪里,比如:文件、数据库、控制台打印等
  • logger: 用来设置某一个包或者具体某一个类的日志打印级别、以及指定appender
  • root:也是一个logger,是一个特殊的父logger。所有的子logger最终都会将输出流交给root,除非在子logger中配置了additivity=“false”。
  • rollingPolicy:所有日志都放在一个文件是不好的,所以可以指定滚动策略,按照一定周期或文件大小切割存放日志文件。
  • RolloverStrategy:日志清理策略。通常是指日志保留的时间。
  • 异步日志:单独开一个线程做日志的写操作,达到不阻塞主线程的目的。

  • 同步日志,主线程要等到日志写磁盘完成之后,才能继续向下执行
  • 异步日志,主线程写日志只是将日志消息放入一个队列,之后就继续向下执行,这个过程是在内存层面完成的。之后由专门的线程从队列中获取日志数据写入磁盘,所以不阻塞主线程。主线程(核心业务代码)执行效率很高。

logback日志框架配置

logback既可以通过application配置文件进行日志的配置,又可以通过logback-spring.xml进行日志的配置。通常情况下,使用全局配置文件application.yml或properties进行配置就足够了,如果您的日志输出需求特别复杂而且需求比较个性化,可以考虑使用logback-spring.xml的配置方式。


application配置文件实现日志配置

我们可以在applicaition.properties(yml) 文件中进行日志的配置

logging:
  level:
    root: info
    com.dhy.boot.launch.controller: debug
  file:
    path: D:\\logs
    name: D:\\logs\\boot-launch.log
    max-size: 10MB
    max-history: 10
  pattern:
    console: '%red(%dyyyy-MM-dd HH:mm:ss) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger10) - %cyan(%msg%n)'
    file: '%dyyyy-MM-dd HH:mm:ss.SSS %-5level [%thread] %logger : %msg%n'
  • logging.level.root=info指定整个系统的默认日志级别是info,日志级别统一化
  • logging.level.com.dhy.boot.launch.controller=debug,指定某个特定的package的日志级别是debug,日志级别个性化。优先级角度,个性配置大于统一配置。
  • logging.file.path将日志输出到指定目录,如果不指定logging.file.name,日志文件的默认名称是spring.log。配置了logging.file.name之后,logging.file.path配置失效。
  • 无论何种设置,Spring Boot都会自动按天分割日志文件,也就是说每天都会自动生成一个新的log文件,而之前的会自动打成GZ压缩包。# 日志文件大小
  • 可以设置logging.file.max-size=10MB分割的每个日志的文件最大容量,超过这个size之后日志继续分隔。
  • 可以设置保留的日志时间logging.file.max-history=10,以天为单位
  • logging.pattern.file输出到文件中的日志的格式
  • logging.pattern.console控制台输出日志的格式,为了在控制台调试时候显示效果更清晰,为日志增加了颜色。red、green等等

这里日志文件会自动创建,无需手动指定


日志格式占位符

配合这张图,看一下占位符和logging.pattern.console格式配置之间的关系

  • %dHH:mm:ss.SSS:日志输出时间(red)
  • %thread:输出日志的进程名字,这在Web应用以及异步任务处理中很有用 (green)
  • %-5level:日志级别,并且使用5个字符靠左对齐 (highlight高亮蓝色)
  • %logger:日志输出类的名字 (boldMagenta粗体洋红色)
  • %msg:日志消息 (cyan蓝绿色)
  • %n:平台的换行符

使用logback-spring.xml实现日志配置

需求

一般情况下,使用全局配置文件application.yml或properties进行配置就足够了,如果您的日志输出需求特别复杂,可以考虑使用logback-spring.xml的配置方式。

spring boot 用自带的logback打印日志,多环境打印:

  • 生产环境输出到控制台和文件,一天一个文件,保留30天.
  • 开发环境输出到控制台和打印sql(mybatis)输出,生产环境不打印这个信息
  • 测试环境只输出到控制台。不输出到文件

打印Mybatis SQL,只需要把使用到Mybatis的package的日志级别调整为DEBUG,就可以将SQL打印出来。

前提:项目已经支持application.yml的profile多环境配置


需求实现

因为logback是spring boot的默认日志框架,所以不需要引入maven依赖,直接上logback-spring.xml放在resources下面

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--引入默认的一些设置-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <!--web信息-->
    <logger name="org.springframework.web" level="info"/>

    <!--写入日志到控制台的appender,用默认的,但是要去掉charset,否则windows下tomcat下乱码-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>$CONSOLE_LOG_PATTERN</pattern>
        </encoder>
    </appender>

    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_PATH" value="D:/logs/boot-launch"/>
    <!--写入日志到文件的appender-->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名,每天一个文件-->
            <FileNamePattern>$LOG_PATH.%dyyyy-MM-dd.log</FileNamePattern>
            <!--日志文件保留天数-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%dyyyy-MM-dd HH:mm:ss.SSS [%thread] %-5level %logger50 - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!--异步写日志到文件-->
    <appender name="asyncFileAppender" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>0</discardingThreshold>
        <queueSize>500</queueSize>
        <appender-ref ref="FILE"/>
    </appender>

    <!--生产环境:打印控制台和输出到文件-->
    <springProfile name="prod">
        <root level="info">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="asyncFileAppender"/>
        </root>
    </springProfile>

    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <!-- 打印sql -->
        <logger name="com.dhy.boot.launch" level="DEBUG"/>
        <root level="DEBUG">
            <appender-ref ref="CONSOLE"/>
        </root>
    </springProfile>

    <!--测试环境:打印控制台-->
    <springProfile name="test">
        <root level="info">
            <appender-ref ref="CONSOLE"/>
        </root>
    </springProfile>
</configuration>

异步日志配置:

  • 异步日志queueSize 默认值256,异步日志队列的容量。
  • discardingThreshold:当异步日志队列的剩余容量小于这个阈值,会丢弃TRACE, DEBUG or INFO级别的日志。如果不希望丢弃日志(即全量保存),那可以设置为0。但是当队列占满后,非阻塞的异步日志会变成阻塞的同步日志。所以在高并发低延迟要求的系统里面针对不重要的日志可以设置discardingThreshold丢弃策略,值大于0。

测试一下

上面配置完成之后,可以使用如下代码测试一下,是否满足需求

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
public class LogTestController 
    private static final Logger logger = LoggerFactory.getLogger(LogTestController.class);

    @GetMapping("/testlog")
    public void test()
        logger.trace("Trace 日志...");
        logger.debug("Debug 日志...");
        logger.info("Info 日志...");
        logger.warn("Warn 日志...");
        logger.error("Error 日志...");
    


log4j2日志框架整合与使用

引入maven依赖

Spring Boot默认使用LogBack,但是我们没有看到显示依赖的jar包,其实是因为所在的jar包spring-boot-starter-logging都是作为spring-boot-starter-web或者spring-boot-starter依赖的一部分。

如果这里要使用Log4j2,需要从spring-boot-starter-web中去掉spring-boot-starter-logging依赖,同时显示声明使用Log4j2的依赖jar包,具体如下:

<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>

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

另外log4j是之前使用比较广泛的软件,容易与log4j2发生冲突,如果冲突将log4j从相应的软件里面排除掉,比如:dozer

<dependency>
    <groupId>net.sf.dozer</groupId>
    <artifactId>dozer</artifactId>
    <version>5.4.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
    </exclusions>
</dependency>

添加配置文件log4j2-spring.xml

在resources目录下新建一个log4j2-spring.xml文件,放在src/main/resources目录下即可被Spring Boot应用识别。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <properties>
        <!--日志输出位置-->
        <property name="LOG_HOME">D:/logs</property>
    </properties>

    <Appenders>
        <!-- 将日志输出到控制台-->
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <!--设置日志格式及颜色-->
            <PatternLayout
                    pattern="[%style%dbright,green][%highlight%p][%style%tbright,blue][%style%Cbright,yellow]: %msg%n%style%throwablered"
                    disableAnsi="false" noConsoleNoAnsi="false"/>
        </Console>

        <!-- 将日志输出到文件-->
        <RollingFile name="FILE-APPENDER"
                     fileName="$LOG_HOME/log4j2-demo.log"
                     filePattern="$LOG_HOME/log4j2-demo-%dyyyy-MM-dd-%i.log">
            <!--设置日志格式-->
            <PatternLayout>
                <pattern>[%d][%p][%t][%C] %m%n</pattern>
            </PatternLayout>
            <Policies>
                <!-- 设置日志文件切分参数 -->
                <SizeBasedTriggeringPolicy size="100 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <!--设置最大存档数-->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </Appenders>

    <Loggers>
        <!-- 根日志设置 -->
        <Root level="debug">
            <AppenderRef ref="CONSOLE" level="debug"/>
            <AppenderRef ref="FILE-APPENDER" level="info"/>
        </Root>

        <!--spring日志-->
        <Logger name="org.springframework" level="info"/>
        <!-- mybatis日志 -->
        <Logger name="com.mybatis" level="warn"/>
    </Loggers>
</configuration>
  • 上文两个Appender,一个叫做CONSOLE用于输出日志到控制台,一个叫做FILE-APPENDER输出日志到文件
  • PatternLayout用于指定输出日志的格式,[%d][%p][%t][%C] %m%n这些占位符将结合下文测试结果为大家介绍
  • Policies用于指定文件切分参数

TimeBasedTriggeringPolicy默认的size是1,结合filePattern定

以上是关于日志框架之Logback的使用与详细配置的主要内容,如果未能解决你的问题,请参考以下文章

slf4j 与 logback日志配置详解

最全最详细Logback高级讲解

java日志框架之logback初探

springboot使用之三:springboot使用logback日志

走进Java接口测试之日志框架Logback

14-Java之-Logback大型项目使用总结