【Logback】Logback 中的 Appenders

目录

1、什么是 Appenders?

2、解说 AppenderBase.doAppend() 方法

3、logback-core 模块中的 Appenders

(1)OutputStreamAppender

(2)ConsoleAppender

(3)FileAppender

(4)RollingFileAppender


1、什么是 Appenders?

        Appender 组件负责处理 Logback 日志写入的任务,该组件必须实现 ch.qos.logback.core.Appender 接口,该接口的主要方法总结如下://主要是解决将日志写到哪里去的问题

package ch.qos.logback.core;

import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.LifeCycle;

public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable<E> {
    String getName();

    //核心方法
    void doAppend(E var1) throws LogbackException;

    void setName(String var1);
}

        Appender 接口中其实就一个最核心的方法,即 doAppend() 方法,且该方法只有一个参数,也就是类型为 E 的对象实例。泛型 E 的实例类型需要根据 logback 的具体模块进行决定,在 logback-classic 模块内,E 的类型为 ILoggingEvent(日志记录事件),在 logback-access 模块内,E 的类型为 AccessEventdoAppend() 方法可以说是 logback 框架中最重要的方法,它负责将日志记录事件以合适的格式输出到合适的输出设备//该方法框架的灵魂和各组件之间的桥梁

2、解说 AppenderBase.doAppend() 方法

        抽象类 ch.qos.logback.core.AppenderBase 实现了 Appender 接口,该类是所有 Appender 组件的父类,它提供了所有 Appender 组件共享的基本功能,比如获取和设置 Appender 组件的名称,激活状态,layout 组件,过滤器等。在该类中有一个非常重要的方法实现,就是我们上边提到的 doAppend() 方法,AppenderBase 类的具体实现逻辑源码如下:

public synchronized void doAppend(E eventObject) {
        if (!this.guard) {
            try {
                //1、防止递归调用
                this.guard = true;
                //2、判断Appender是否开启
                if (!this.started) {
                    //状态重复计数
                    if (this.statusRepeatCount++ < 5) {
                        //发出警告信息
                        this.addStatus(new WarnStatus("Attempted to append to non started appender [" + this.name + "].", this));
                    }

                    return;
                }
                //3、检查Appender过滤器决策结果
                if (this.getFilterChainDecision(eventObject) == FilterReply.DENY) {
                    return;
                }
                //4、调用子类的append()的实现
                this.append(eventObject);
            } catch (Exception var6) {
                if (this.exceptionCount++ < 5) {
                    this.addError("Appender [" + this.name + "] failed to append.", var6);
                }
            } finally {
                //5、释放guard
                this.guard = false;
            }

        }
    }

        上边这段代码我在《Logback 日志框架的架构》这篇文章中也提到过,但也只是简要提及,这里将具体分析一下。

        AppenderBase 类中的 doAppend() 方法是同步方法(synchronized修饰),所以不同的线程把日志记录到同一个 Appender 时都是线程安全的(独占访问)。

        这里需要注意,同步有时候并不总是合适的,所以 logback 还提供了 doAppend() 的一般实现,即 ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(),该类中的实现除了不使用synchronized修饰方法外,其他逻辑与 AppenderBase 类中的实现几乎一样。

        第一步,判断 guard 属性是否被设置为 true。如果为 true,那么程序将立即跳出此方法,如果没有设置 guard ,则在下一条语句中将其设置为 true。该 guard 属性确保了 doAppend() 方法不会递归调用自己。比如,如果在 append() 方法之外的某个地方想要调用 Appender 组件去记录一些内容,那么它可能会定向到刚刚调用它的同一个 Appender 组件,从而导致无限循环和堆栈溢出。//guard 属性防止程序递归调用

        第二步,判断 started(开启状态) 是否为 true,如果为 false,doAppend() 将发送警告消息并返回。也就是说,一旦 Appender 已经关闭,就无法对其进行写入。

        Appender 对象实现了 LifeCycle 接口,这意味着它们也实现了 start()、stop() isStarted() 方法。当设置完 Appender 的所有属性后,logback 的配置框架(Joran)将调用 start() 方法来通知 Appender 激活这些属性。如果某些属性缺失或者属性之间相互干扰,那么 Appender 可能无法启动。一般情况下,根据 Appender 的类型,具体的启动的逻辑也会有所不同。//start()方法用来检查Appender配置是否完整,并激活Appender

        如果 Appender 无法启动或已停止,则会通过 logback 的内部状态管理系统发出警告消息。为了避免系统被相同的警告消息淹没,经过几次尝试后(5次),doAppend() 将停止发出这些警告。

        第三步,检查 Appender 过滤器决策结果。根据 Appender 过滤器链产生的决策结果,判断日志事件是否被拒绝或者被接受。在过滤器链没有做出决定的情况下,默认会接受日志事件。

        然后,调用子类的 append() 的实现append() 方法负责将日志记录事件输出到指定的设备上。

        最后,释放 guard ,以允许其他线程调用 doAppend() 方法。

3、logback-core 模块中的 Appenders

        logback-core 模块为构建其他 logback 模块奠定了基础,因此在 logback-core 中,实现了一些最小化定制的组件,下边,我们将探讨几个开箱即用的 Appenders(追加器)。

(1)OutputStreamAppender

        OutputStreamAppender 会使用 java.io.OutputStream 来处理日志事件。这个类会为其它 Appender 组件的构建提供基础服务。以下是该 Appender 的几个属性配置:

属性名称类型描述
encoderEncoder 编码器配置
immediateFlushString

默认值为“true”,立即刷新输出流可确保日志记录事件立即写出,防止日志记录丢失

如果将此属性设置为“false”,可能会使记录吞吐量增加四倍左右(仅是测试值),不过,当应用程序退出,Appender未被正确关闭时,就可能使尚未写入磁盘的日志记录丢失。

        用户通常不会直接实例化 OutputStreamAppender 对象,所以我们为什么还要提到它呢?

        因为 OutputStreamAppender 是 ConsoleAppender、FileAppender、RollingFileAppender 这3 个非常重要的 Appender 对象的父类,所以重要性不言而喻,下图是 OutputStreamAppender 及其子类的类图。//都是基于OutputStream进行日志处理的Appender

(2)ConsoleAppender

        顾名思义,ConsoleAppender 是将日志输出到控制台上,更准确的来说是输出到 System.out 或 System.err 上。ConsoleAppender 通过用户指定的 encoder 来格式化日志,因为 System.out 和 System.err 都是 java.io.PrintStream 类型,所以,它们都被包装在一个带有缓冲区的 OutputStreamWriter 中。

        该 Appender 可以配置的属性如下:

属性名称类型描述
encoderEncoder 编码器配置
target String输出字符串,目标为 System.out 或 System.err 。默认是 System.out
withJansibooleanwithJansi 属性默认为 false,为 true 时会激活 Jansi 库,该库在 Windows 计算机上提供对 ANSI 颜色代码的支持。请注意,基于 Unix 的操作系统(例如 Linux 和 Mac OS X)默认支持 ANSI 颜色代码。//win系统颜色支持

        以下是使用 ConsoleAppender 的示例配置:

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!--默认为 ch.qos.logback.classic.encoder.PatternLayoutEncoder-->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

(3)FileAppender

        前面提到过,FileAppender 也是 OutputStreamAppender 的子类,它的作用是把日志输出到指定的文件中。

        该 Appender 可以配置的属性如下:

属性名称类型描述
appendboolean默认设置为 true,即将日志追加到文件现有内容的末尾。如果为 false,则覆盖原有文件中的内容
encoderEncoder 编码器配置
fileString

要写入的文件。如果该文件不存在,则创建该文件。该选项没有默认值,示例的配置值为:c:/temp/test.logc:\\temp\\test.log

注意,如果文件的父目录不存在,FileAppender 也会自动的创建它。

bufferSizeFileSize

设置输出缓冲区的大小。默认值为 8192,即使在负载非常重且持续的情况下,256 KB 值一般也足够了。该属性在 OutputStreamAppender.immediateFlush 为 false 时可用。

该选项可以通过在数值后分别添加 KB、MB 和 GB 来指定字节、千字节、兆字节或千兆字节。例如,5000000、5000KB、5MB 和 2GB 都是有效值,其中前三个值是等效的。

prudent(谨慎的)boolean

默认值为 false,如果设置为 true,即开启 Prudent 模式。在 prudent 模式下,即使存在多个不同主机(JVM)上运行的 FileAppender 实例,FileAppender 也会将日志安全地写入到指定文件。//安全模式

Prudent 模式依赖独占的文件锁,实验表明,使用文件锁定的成本大约是正常写入成本的三倍 (x3),因此在 Prudent 模式下,会降低日志写入的吞吐量。

Prudent 模式可以有效地将写入同一文件的所有 JVM 之间的 I/O 操作进行排序。因此,随着竞争访问文件的 JVM 数量增加,每个 I/O 操作产生的延迟也会增加。不过,只要 I/O 操作总数仅为每秒 20 个日志请求左右时,该模式对性能的影响就可以忽略不计。但是,如果是每秒生成 100 次或更多 I/O 操作的应用程序,那么该模式可能会对性能产生影响,因此,在这种情况下应该避免使用 Prudent 模式。

当日志文件位于网络文件系统上时,Prudent 模式的成本会更大。需要注意的是,网络文件系统上的文件锁有时可能存在强烈的偏差,使得当前拥有锁的进程在释放锁后可以立即重新获得锁。因此,当一个进程霸占日志文件的锁时,其他进程可能因为等待该锁而陷入死锁状态

        默认情况下,每个日志记录事件都被会立即刷新到底层的输出流。如果应用程序在没有正确关闭 Appender 的情况下退出,这时的日志记录也不会丢失,所以这种方式也更加的安全。

        但是,为了显着提高日志记录的吞吐量,可能也会需要将 immediateFlush 属性设置为 false。

        以下是使用 FileAppender 的示例配置:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>

    <!--将immediateFlus设置成false可以获得更高的日志吞吐量-->
    <immediateFlush>true</immediateFlush>

    <!-- 默认使用PatternLayoutEncoder-->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

        如果使用时间戳对写入文件进行唯一命名?

        如果希望应用程序在每次启动时都自动创建一个新的日志文件,除了可以手动更改日志文件的名称以外,还有一种非常方便的方式,那就是使用时间戳,下边就是一个简单的例子:

<configuration>

  <!--把当前事件格式化为"yyyyMMdd'T'HHmmss",然后将其命名为bySecond,
      这个值对于所有后续配置的元素都是可用的-->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!--使用之前创建的时间戳来创建唯一的日志文件名称-->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

        <timestamp> 元素有两个强制的属性 key 和 datePattern 以及一个可选的 timeReference 属性。

  • key 属性是键的名称,在该键 key 下时间戳将作为变量可供后续配置元素使用。
  • datePattern 属性用于将当前时间(解析配置文件的时间)转换为字符串的日期模式。日期模式应遵循 SimpleDateFormat 中定义的约定。
  • timeReference 属性表示时间戳的参考时间。该时间默认是配置文件的解析时间(即当前时间)。然而,在某些情况下,参考时间使用日志上下文创建的时间可能会更加的合适。为了实现这一目标,只要将 timeReference 属性设置为 “contextBirth” 就可以了。

        示例的配置如下:

<configuration>
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" 
             timeReference="contextBirth"/>
  ...
</configuration>

(4)RollingFileAppender

        RollingFileAppender 对 FileAppender 的功能进行了扩展,它提供了滚动更新日志文件的功能。比如,使用 RollingFileAppender 将日志记录到名为 log.txt 的文件,当满足特定条件时,可以将其记录的目标更改为另一个文件。//日志文件滚动更新

        实现 RollingFileAppender 的日志滚动功能需要配置两个重要的组件,第一个组件是 RollingPolicy(滚动策略),负责执行滚动所需的操作,第二个组件是 TriggeringPolicy(触发策略),用来定义什么时候进行滚动。//滚动策略+触发策略

        一般来说,RollingFileAppender 必须同时设置 RollingPolicy 和 TriggeringPolicy。但是,如果一个 RollingPolicy 也实现了 TriggeringPolicy 接口,那么只需显式指定 RollingPolicy 即可

        以下是 RollingFileAppender 的可用属性:

属性名称类型描述
appendboolean默认设置为 true,即将日志追加到文件现有内容的末尾。如果为 false,则覆盖原有文件中的内容
encoderEncoder 编码器配置
fileString

要写入的文件

请注意,此处文件可以为空,在这种情况下,输出仅写入由 RollingPolicy 指定的目标。

rollingPolicyRollingPolicy滚动执行策略,见下文详述
triggeringPolicyTriggeringPolicy滚动触发策略,见下文详述
prudent(谨慎的)boolean

Prudent 模式不支持 FixedWindowRollingPolicy(弃用策略)

Prudent 模式只支持 TimeBasedRollingPolicy,但是有两个限制:

(1)在 Prudent 模式下,不支持也不允许文件压缩。 因为不能让一个 JVM 写入文件时,而另一个 JVM 正在压缩该文件。

(2)Appender 的 file 属性不能设置,且必须留空。因为大多数操作系统不允许在另一个进程打开文件时重命名该文件。

        什么是滚动策略(RollingPolicy)?

        RollingPolicy 用来定义文件滚动和重命名时所执行的操作,RollingPolicy 的接口如下所示:

package ch.qos.logback.core.rolling;

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.helper.CompressionMode;
import ch.qos.logback.core.spi.LifeCycle;

public interface RollingPolicy extends LifeCycle {
    void rollover() throws RolloverFailure;

    String getActiveFileName();

    CompressionMode getCompressionMode();

    void setParent(FileAppender<?> var1);
}

        RollingPolicy 接口中一共有四个方法,其中 rollover() 方法用来执行滚动(归档)当前日志文件所涉及的工作,getActiveFileName() 用来方法来获取当前日志文件(写入实时日志的位置)的文件名,getCompressionMode() 用来获取日志的压缩模式,最后,setParent() 方法使 RollingPolicy 实例可以获得对其父类的引用。

        基于时间的滚动策略:TimeBasedRollingPolicy

        TimeBasedRollingPolicy 用来定义基于时间的滚动策略,比如按天或者按月进行滚动。

        TimeBasedTriggeringPolicy 同时实现了 RollingPolicy 和 TriggeringPolicy 接口。它的可配置属性如下:

属性名称类型描述
fileNamePatternString

必须配置,该属性用来定义滚动(归档)日志文件。

该文件名称中一般会包含 %d 转换符,%d 转换符后边一般也还包含指定的日期和时间模式,比如:/test.%d{yyyy-MM-dd-HH}.log,表示按小时对日志文件进行滚动,默认的日期和时间模式为 yyyy-MM-dd

注意,当配置 RollingFileAppender 的 file 属性(父类中的属性)时,当前活动日志文件的名称就是 file 属性指定的文件名称,此时活动日志文件的名称不会随时间的改变而改变。因此,可以利用这个属性解耦活动日志文件的位置和归档日志文件的位置,这个在后边会举例。

多个 %d 转换符的说明:

fileNamePattern 的值可以包含多个 %d 转换符,但是其中只能有一个 %d 是推动日志文件滚动周期的主要转换符,其他 %d 必须使用 "aux" 参数进行标记,指明这是一个辅助性的转换符。

多个 %d 转换符有助于使用不同于滚动周期的文件夹结构来组织存档文件。比如,以下显示的文件名将按年和月来命名日志文件夹,但按天来更新日志文件:

/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log

注意,fileNamePattern 属性内,日期和时间模式内任意位置的正斜杠 "/" 或反斜杠 "\" 字符将被解释为目录分隔符。

maxHistoryint

该属性用于控制要保留的归档文件的最长时间,超过该配置时间的旧文件会被异步删除。

比如,如果指定策略为每月滚动,并将 maxHistory 设置为 6,那么将只保留 6 个月内的存档文件。当旧的存档文件被删除时,为这些文件存档而创建的文件夹都会被删除。

maxHistory 的默认配置为零,即默认情况下不删除存档。

totalSizeCapint

该属性用于控制所有归档文件的总大小。当超过总大小上限时,最旧的存档将被异步删除。

此外,要使 totalSizeCap 属性生效,还需要设置 maxHistory 属性。框架 首先应用 maxHistory 属性限制,然后再应用 "总大小上限" 限制。//即首先删除超时的,然后再删除超大小的

totalSizeCap 属性的值可以通过在数值后分别添加 KB、MB 和 GB 来指定为字节、千字节、兆字节或千兆字节的单位。

默认情况下,totalSizeCap 设置为零,这意味着没有总大小上限。

cleanHistoryOnStartboolean

默认情况下,此属性设置为 false。如果设置为 true,则存档删除将在 Appender 启动时执行。

存档删除通常在日志回滚期间执行。但是,某些应用程序的生存时间可能不够长,无法触发滚动。因此,对于此类短暂的应用程序,存档删除可能永远没有机会执行。所以通过将 cleanHistoryOnStart 设置为 true,可以避免以上这种情况

        以下是一些 fileNamePattern 的值及其效果的说明:

fileNamePattern表达式回滚时间示例
/wombat/foo.%d

按日滚动,由于 %d 转换符后省略了日期和时间匹配模式,所以采用的是默认的模式 yyyy-MM-dd

file 属性未设置:2023年11月23日的日志将输出到文件 /wombat/foo.2023-11-23。同样,24日期间的日志将输出到 /wombat/foo.2006-11-24

file 属性设置为 /wombat/foo.txt 时:2023年11月23日的日志将输出到文件 /wombat/foo.txt。日志回滚时,foo.txt 将被重命名为 /wombat/foo.2023-11-23。此外,还将创建一个新的 /wombat/foo.txt 文件,用来记录24日的日志输出,此种情况下的活动日志文件始终是 /wombat/foo.txt//file属性的作用

/wombat/%d{yyyy/MM}/foo.txt按月滚动

file 属性未设置:在2023年10月期间,日志输出将转到 /wombat/2023/10/foo.txt。 11月期间,日志输出到 /wombat/2023/11/foo.txt

file 属性设置为 /wombat/foo.txt:活动日志文件将始终为 /wombat/foo.txt。在2023年10月期间的日志将输出到 /wombat/foo.txt。 日志按月滚动后,/wombat/foo.txt 将更名为 /wombat/2023/10/foo.txt。此外,将创建一个新的 /wombat/foo.txt 文件,用来记录11月份的日志输出。 11月滚动时,/wombat/foo.txt 也将更名为 /wombat/2023/11/foo.txt

/wombat/foo.%d{yyyy-ww}.log按周滚动示例与上边类似
/wombat/foo%d{yyyy-MM-dd_HH}.log按小时滚动示例与上边类似
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log按分钟滚动示例与上边类似
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log按分钟滚动,并指定时区在某些情况下,可能希望根据与主机时区不同的时钟来滚动日志文件。那么就可以在 %d 转换符的日期和时间匹配模式中传递时区参数。

/foo/%d{yyyy-MM,aux}/%d.log

//非常有用的匹配模式

按日滚动,按年和月来归档日志文件

在此示例中,第一个 %d 转换符被标记为辅助标记。然后,第二个 %d 转换符(省略了时间和日期匹配模式)被定为主要标记。因此,滚动将每天发生(默认为 %d),并且文件夹也将按照年份和月份命名。例如,在2023年11月期间,日志文件将全部放置在 /foo/2023-11/ 文件夹下,比如 /foo/2023-11/2023-11-14.log

        如何进行自动文件压缩?

        TimeBasedRollingPolicy 支持自动文件压缩。如果 fileNamePattern 选项的值以 .gz 或 .zip 结尾,则自动启用文件压缩功能

fileNamePattern表达式回滚时间示例
/wombat/foo.%d.gz

按日滚动,自动对存档文件进行 GZIP 压缩

file 属性未设置:2023年11月23日期间的日志将输出到文件 /wombat/foo.2023-11-23。但是,当日日志滚动时,该文件将被压缩为 /wombat/foo.2023-11-23.gz。 11月24日,日志记录将输出到 /wombat/folder/foo.2023-11-24,同样到第二天开始滚动时进行压缩。

file 属性设置为 /wombat/foo.txt:2023年11月23日期间的日志输出到文件 /wombat/foo.txt。滚动时该文件将被压缩并重命名为 /wombat/foo.2023-11-23.gz。此外,将创建一个新的 /wombat/foo.txt 文件,用来记录11月24日期间的日志输出。 11月24日日志滚动时,/wombat/foo.txt 将被压缩并重命名为 /wombat/foo.2023-11-24.gz

        总结上边的配置信息,我们可以发现 fileNamePattern 属性具有有双重用途,首先,通过定义的日期和时间匹配模式,logback 可以获得请求的滚动周期。此外,它还可用于定义每个存档文件的名称。

        这里需要提一下,日期和时间匹配模式 yyyy-MM 和 yyyy@MM 都可以指定日志按月滚动,只不过它们生成的存档文件将带有不同的名称,比如:foo.2023-11.log,foo.2023@11.log。

        示例的配置文件内容如下:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <!--滚动策略-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!--按日滚动-->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!--保留30天的历史记录,总大小限制为3GB-->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

        基于文件大小和时间的滚动策略:SizeAndTimeBasedRollingPolicy

        有时后,你可能既希望按日期对日志文件进行归档,但同时又希望限制每个日志文件的大小。特别是当后期处理工具对日志文件大小有限制要求时(很多文件读取工具都有文件大小限制),这种需求会非常的迫切。

        为了满足上述这些要求,logback 也附带了基于文件大小和时间的滚动策略 SizeAndTimeBasedRollingPolicy。

        除了 "%d" 转换符之外,基于大小的滚动策略还依赖于 "%i" 转换符。在该策略下,%i 和 %d 两个转换符都是必需的。"%i" 转换符的作用,就是当前日志文件在滚动时间到达之前,如果达到 maxFileSize 时,都会从 0 开始递增索引并对其进行归档。

        下表列出了适用于 SizeAndTimeBasedRollingPolicy 的属性:

属性名称类型描述
maxFileSizeFileSize

当前日志文件在滚动时间到达之前,如果达到 maxFileSize 时,都会从 0 开始递增索引并对其进行归档。

配置值后可以添加 KB、MB 和 GB 等单位来指定字节、千字节、兆字节或千兆字节。

checkIncrementDuration检查文件大小是一项成本相对较高的操作,所以默认情况下每 60 秒执行一次。但是,你也可以设置不同的检查时间增量作为持续时间。

        需要注意的是,这些属性都只是对适用于 TimeBasedRollingPolicy 的属性的补充,也就是说,适用于 TimeBasedRollingPolicy 的属性也同样适用于 SizeAndTimeBasedRollingPolicy。

        示例的配置文件内容如下:

<configuration>

  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!--按日滚动-->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!--每个文件最大100M,仅保留60天,且保留的文件的总的大小不超过20G-->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>

        什么是触发策略(TriggeringPolicy)?

        TriggeringPolicy 用来指示 RollingFileAppender 何时滚动,TriggeringPolicy 接口仅包含一个方法。

package ch.qos.logback.core.rolling;

import ch.qos.logback.core.spi.LifeCycle;
import java.io.File;

public interface TriggeringPolicy<E> extends LifeCycle {
    boolean isTriggeringEvent(File var1, E var2);
}

        isTriggeringEvent() 方法将活动文件和当前正在处理的日志记录事件作为参数。具体实现需要根据这些参数来确定是否触发日志滚动。

        用得最多的触发策略,就是 TimeBasedRollingPolicy,它同时也实现了 RollingPolicy 接口,所以也兼作滚动策略。上边我们对 TimeBasedRollingPolicy 已经做了详细的介绍,此处不再赘述。

        至此,logback-core 模块中的 Appenders 就已经介绍完了,除了 logback-core 模块外,logback-classic 和 logback-access 模块中也有附带了很多的 Appenders,比如,SocketAppender(明文输送到远程目标)、SSLSocketAppender(加密输送到远程目标)、SMTPAppender(输送到电子邮件)、DBAppender(输送到数据库)、SyslogAppender(输送到远程日志系统)、SiftingAppender(筛选日志记录)、AsyncAppender(异步处理日志记录) 等。此外还可以自定义 Appender,因为篇幅限制,不再详细叙述,感兴趣的可以去查阅相关文档。

        至此,全文结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/439865.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

devops-Maven【部署及配置】

1、准备maven工具包&#xff0c;Maven官网下载Maven的安装包 Maven – Download Apache Maven Index of /maven (apache.org) 选择后缀是.bin.tar.gz的文件下载&#xff0c;此处下载的版本是3.9.6。 2、安装maven的目录下&#xff0c;建一个Maven路径&#xff0c;然后把压缩…

GEE 底图加载——自定义底图样式加载案例分析(含免费引如多款底图)

在本教程中&#xff0c;您将学习如何更改地图对象的选项&#xff0c;以便为底层基础地图定义自己的样式。 地球引擎中的默认地图 地球引擎的基础地图是 Google Map API 中的地图。默认选项包括 roadmap&#xff0c;显示默认的路线图视图、卫星&#xff0c;显示谷歌地球卫星图…

洗衣洗鞋店小程序对接水洗唛打印,一键预约,支付无忧

随着社会的进步和科技的发展&#xff0c;我们的生活幸福感与日俱增。为了让我们从琐碎中解脱出来&#xff0c;干洗店洗鞋店行业也日新月异。今天&#xff0c;我为大家推荐这款优秀的干洗店小程序系统&#xff0c;让您的洗衣洗鞋服务体验更上一层楼。 干洗店管理系统是一款专为洗…

前端对于大图片与小图片的处理 转base64

对于小图片&#xff0c;可以转换为base64字节编码的字符串&#xff0c;减少一次资源请求&#xff0c;资源占用多了一丢丢而已 对于大图片&#xff0c;就算了&#xff0c;得不偿失 比如&#xff0c;webpack处理图片资源

掌握这几个技术点,你也能开发出爆款ARPG游戏!

在众多ARPG游戏的发售下&#xff0c;游戏市场温度迅速升高&#xff0c;今年很可能会成为一个“ARPG手游大年”&#xff0c;或许会再次出现“神仙打架”的情况。 ARPG作为一种非常经典且流行的游戏类型, 已经诞生过无数经典的作品,比如魂系,暗黑破坏神系列,塞尔达传说系列&#…

《计算机程序的构造和解释》

文章目录 写在末尾 &#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【锡兰赠书】&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&…

一文搞懂电容两端电压为啥不能突变?

大家好&#xff0c;我是砖一。 我们工作学习过程中&#xff0c;经常会遇到的电容&#xff0c;对于电容的作用&#xff0c;可能大家一般去网上搜有很多&#xff0c;比如储能&#xff0c;滤波&#xff0c;旁路&#xff0c;去耦等等。 但是我要告诉大家的是&#xff0c;电容最重…

惊呼:腾讯云服务器99元一年,要不要来一台?

腾讯云服务器99元一年是真的吗&#xff1f;真的&#xff0c;99元优惠购买入口 txybk.com/go/99 折合每天8元1个月&#xff0c;腾讯云99元服务器配置为2核2G3M带宽&#xff0c;2024年99元服务器配置最新报价为61元一年&#xff0c;如下图&#xff1a; 腾讯云服务器99元一年 腾讯…

机器学习流程—数据预处理 清洗

机器学习流程—数据预处理 清洗 数据清洗因为它涉及识别和删除任何丢失、重复或不相关的数据。数据清理的目标是确保数据准确、一致且无错误,因为不正确或不一致的数据会对 ML 模型的性能产生负面影响。专业数据科学家通常会在这一步投入大量时间,因为他们相信Better data b…

【Docker】若依ruoyi项目部署

一 搭建局域网 1 # 搭建net-ry局域网&#xff0c;用于部署若依项目docker network create net-ry --subnet172.68.0.0/16 --gateway172.68.0.1 # 注意1&#xff1a;关闭宿主机的防火墙&#xff0c;否者容器内部的MySQL、redis等服务&#xff0c;外部访问不了&#xff1b;开放…

智慧油气场站:油气行业实现数字化转型的关键一步

智慧油气场站&#xff1a;油气行业实现数字化转型的关键一步 在现代社会&#xff0c;能源供应是国家经济发展和人民生活的重要保障。而油气场站作为能源的重要供应和储存基地&#xff0c;扮演着至关重要的角色。此外&#xff0c;油气场站还可以为石油和天然气的生产提供支持。…

分享MDN前端结构化技能、实践指南、学习资源

前言 MDN课程为成为一名成功的前端开发人员提供了一个结构化的基本技能和实践指南&#xff0c;以及推荐的学习资源。 先看下让人不得不服的书《宝宝的网页设计》&#xff08;套装共3册&#xff09; 宝宝的HTML、宝宝的CSS、宝宝的JavaScript 全球首套中英文宝宝编程启蒙书&a…

云计算项目十:ES集群安装|部署kibana

ES集群安装 部署ES集群&#xff0c;用于ELK日志分析平台的构建 es-0001 主机更改 /etc/hosts [rootes-0001 ~]# vim /etc/hosts 192.168.1.71 es-0001 192.168.1.72 es-0002 192.168.1.73 es-0003 192.168.1.74 kibana 192.168.1.75 logstash # 将最新的/etc/hosts配置文件更…

javascript正则深入

文章目录 一、前言二、高级`API`2.1、模式匹配的用法`(x)`2.2、非捕获括号的模式匹配`(?:x)`2.3、先行断言`x(?=y)`2.4、后行断言`(?<=y)x`2.5、正向否定查找`x(?!y)`2.6、反向否定查找`(?<!y)x`2.7、字符集合和反向字符集合的用法 `[xyz] / [^xyz]`2.8、词边界和非…

【C++】设计模式:观察者、策略、模板

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍设计模式&#xff1a;观察者、策略、模板。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xf…

STM32CubeMX学习笔记17--- FSMC

1.1 TFTLCD简介 TFT-LCD&#xff08;thin film transistor-liquid crystal display&#xff09;即薄膜晶体管液晶显示器。液晶显示屏的每一个像素上都设置有一个薄膜晶体管&#xff08;TFT&#xff09;&#xff0c;每个像素都可以通过点脉冲直接控制&#xff0c;因而每个节点都…

JavaScript 二分查找(迭代与递归)

二分搜索被定义为一种在排序数组中使用的搜索算法&#xff0c;通过重复将搜索间隔一分为二。二分查找的思想是利用数组已排序的信息&#xff0c;将时间复杂度降低到O(log N)。 二分查找算法示例 何时在数据结构中应用二分查找的条件&#xff1a; 应用二分查找算法&#xff1a…

Langchain-Chatchat本地搭建ChatGLM3模型和提取PDF内容

文章目录 1、软件要求2、安装CUDA2.1、安装gcc2.2、安装CUDA 3、安装Anaconda33.1、下载Anaconda33.2、创建python虚拟环境 4、部署系统4.1、下载源码4.2、安装依赖4.3、下载模型4.4、初始化配置和知识库4.4.1、初始化配置4.4.2、初始化知识库 4.5、运行4.6、运行4.6.1、启动4.…

Python学习笔记-Flask实现简单的抽奖程序

1.导入flask包和randint包 from flask import Flask,render_template from random import randint 2.初始化 Flask 应用: app Flask(__name__) 3. 定义英雄列表 hero [黑暗之女,狂战士,正义巨像,卡牌大师,德邦总管,无畏战车,诡术妖姬,猩红收割者,远古恐惧,正义天使,无极剑…

Clickhouse表引擎介绍

作者&#xff1a;俊达 1 引擎分类 ClickHouse表引擎一共分为四个系列&#xff0c;分别是Log、MergeTree、Integration、Special。其中包含了两种特殊的表引擎Replicated、Distributed&#xff0c;功能上与其他表引擎正交&#xff0c;根据场景组合使用。 2 Log系列 Log系列…