【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、释放guardthis.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,因为篇幅限制,不再详细叙述,感兴趣的可以去查阅相关文档。

        至此,全文结束。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud微服务-DockerCompose(初识、安装、部署)

DockerCompose&#xff08;初识、安装、部署&#xff09; 文章目录 DockerCompose&#xff08;初识、安装、部署&#xff09;初识DockerCompose&#xff1f;DockerCompose安装DockerCompose部署微服务问题解决&#xff08;重要&#xff01;&#xff01;&#xff01;&#xff09…

小白跟做江科大51单片机之DS1302按键可调时钟

1.引入上一个程序的代码 2.引入Key和Timer0文件 3.获取按键值 定义全局变量unsigned char keynum main函数中 keynumKey(); 4.设置第一个按键的两种模式&#xff0c;以此来控制时钟的设定和显示 if(keynum1) { if(MODE0) { …

c++ primer学习笔记(二)

目录 第三章 一、命名空间的using声明 二、标准库的string类型 1、string对象的定义和初始化 2、string对象的读写 3、string对象的操作 4、string对象中字符的处理 三、标准库的vector类型 1、vector对象的定义和初始化 2、vector对象的操作 四、迭代器简介 1、简…

前端复选框问题-节点赋值未选中最后显示时确变成选中状态?

问题&#xff1a; 前两天一同事请教我&#xff1a;前端复选框问题-节点赋值未选中最后显示时确变成选中状态&#xff1f; 还有就是明明传过为的是false&#xff0c;在控制台上打印确变成选中状态&#xff0c;如下图&#xff1a; 以下是前端vue代码&#xff1a; <Scroll h…

CentoS迁移好帮手——银河麒麟服务器迁移运维管理平台最新介绍

•银河麒麟服务器迁移运维管理平台&#xff0c;面向大规模、集群式的服务器主机管理场景&#xff1b; •跨多种环境、高可用与分布式部署、配置管理、漏洞修复、服务包升级、CentoS迁移等多种核心运维场景解决方案&#xff1b; •CPU架构同源支持&#xff0c;兼容Intel、 海光…

Linux下下载安装JDK配置Java环境变量

Linux下下载安装JDK配置Java环境变量 1. 下载JDK 下载链接&#xff1a;(https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) 2. 上传至服务器并解压 可通过shell工具进行上传&#xff0c;我这里是上传安装在/opt目录 解压jdk-17.0.10_linux-x64_b…

C++之关联式容器set和map的使用

目录 1、set的使用​编辑 1、初始化 2、遍历 3、查找​编辑 4、插入​编辑 5、不支持修改与下标 2、map的使用 1、初始化​编辑 2、遍历 3、map的下标(重点) #include <iostream> #include <vector> #include <set> #include <map> #include…

2023预测误差位平面冗余-RDHEI Based on Bit-Plane

RRBE 本文仅供学习&#xff0c;切勿转载和搬运&#xff0c;如有侵权&#xff0c;联系立删~ 一、背景知识 The Gradient-Adjusted Predictor&#xff08;GAP&#xff0c;梯度调整预测器&#xff09; 根据被预测像素周围的七个像素进行预测 具体流程可参考文献X. Wu and N. M…

selenium4的相对定位

selenium4相对定位 Selenium 4新增了相对定位器&#xff0c;能帮助用户查找元素附近的其他元素。可用的相对定位器有above、below、toLeftOf、toRightOf、near。在Selenium 4中&#xff0c;find_element方法能够接受一个新方法withTagName&#xff0c;它将返回一个RelativeLoca…

项目管理必备的五张图表,助力你高效掌控全局

在项目管理中&#xff0c;图表作为一种直观的工具&#xff0c;帮助项目经理更有效的规划、监控和控制项目的各个方面&#xff0c;以下是项目经理常用的几张图表&#xff0c;它们在项目管理中发挥着至关重要的作用。 1、甘特图 甘特图&#xff08;Gantt Chart&#xff09;是最…

C语言——oj刷题——猜数字游戏

当用C语言来实现猜数字游戏时&#xff0c;我们可以设计一个简单的游戏规则&#xff1a;计算机随机生成一个1到100之间的整数&#xff0c;玩家需要通过猜测来猜出这个数字。游戏会根据玩家猜测的数字与目标数字的大小关系给出提示&#xff0c;直到玩家猜中为止。 下面是一个用C…

类体相关知识

定义 类声明之后的一对大括号“{”&#xff0c;“}” 以及它们之间 的内容称作 &#xff0c;大括号之间的内容称作类体的内容。 组成部分 变量的声明&#xff1a;用来刻画属性 。 方法的定义&#xff1a;用来刻画行为功能

2023年12月CCF-GESP编程能力等级认证Python编程七级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录・点这里 一、单选题(每题 2 分,共 30 分) 第1题 假设变量 x 为 float 类型,如果下面代码输入为 100,输出最接近( )。 A.0 B.-5 C.-8 D.8 答案:B 第2题 对于下面动态规划方法实现的函数,以下选项中…

VR科学知识互动展示介绍|游戏体验馆加盟|VR展示厅

VR科学知识互动展示是一种利用虚拟现实技术来呈现科学知识并与观众进行互动的展示方式。通过VR设备&#xff0c;参观者可以沉浸在各种科学主题的虚拟环境中&#xff0c;以全新的视角和体验来探索科学领域的知识。 这样的展示通常结合了视觉、听觉和触觉等感官体验&#xff0c;使…

springboot-异步、定时、邮件任务

一、异步任务 1、创建项目 2、创建一个service包 3、创建一个类AsyncService 异步处理还是非常常用的&#xff0c;比如我们在网站上发送邮件&#xff0c;后台会去发送邮件&#xff0c;此时前台会造成响应不动&#xff0c;直到邮件发送完毕&#xff0c;响应才会成功&#xff…

1.2_1 分层结构、协议、接口和服务

1.2_1 分层结构、协议、接口和服务 &#xff08;一&#xff09;为什么要分层&#xff1f; 主机A如果想要向主机B发送文件&#xff0c;则一定要经过中间的一些介质、链路。 发送文件前要完成的工作&#xff1a; 1.发起通信的计算机必须将数据通信的通路进行激活。 所谓的激活&a…

多线程系列(十五) -常用并发工具类详解

一、摘要 在前几篇文章中&#xff0c;我们讲到了线程、线程池、BlockingQueue 等核心组件&#xff0c;其实 JDK 给开发者还提供了比synchronized更加高级的线程同步组件&#xff0c;比如 CountDownLatch、CyclicBarrier、Semaphore、Exchanger 等并发工具类。 下面我们一起来…

OJ_空闲块

题干 C实现 /** 输入样例&#xff1a; 12 1024 2048 8192 512 16384 1024 32768 8192 65536 8192 77824 1024 80896 3072 86016 1024 91136 5120 99328 512 104448 1024 112640 3072 1024 2560 10240 512 1024 6400 512 -1 输出样例&#xff1a; 104448 1024 112640 3072 1024…

字节后端实习 一面凉经

心脏和字节永远都在跳动 深圳还有没有大厂招后端日常实习生啊&#xff0c;求捞&#xff5e;&#xff08;boss小公司也不理我&#xff09; 很纠结要不要干脆直接面暑期实习&#xff0c;又怕因为没有后端实习经历&#xff0c;面不到大厂实习。死锁了

SpringMVC-请求与响应(附Servlet相关接口替换方案)

1.请求 1.请求参数 SpringMVC将传递的参数封装到处理器方法的形参中&#xff0c;达到快速访问参数的目的 1.普通类型参数传参 page.jsp <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <body> <h1>请…