目录
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 的类型为 AccessEvent。doAppend() 方法可以说是 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 的几个属性配置:
属性名称 | 类型 | 描述 |
encoder | Encoder | 编码器配置 |
immediateFlush | String | 默认值为“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 可以配置的属性如下:
属性名称 | 类型 | 描述 |
encoder | Encoder | 编码器配置 |
target | String | 输出字符串,目标为 System.out 或 System.err 。默认是 System.out。 |
withJansi | boolean | withJansi 属性默认为 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 可以配置的属性如下:
属性名称 | 类型 | 描述 |
append | boolean | 默认设置为 true,即将日志追加到文件现有内容的末尾。如果为 false,则覆盖原有文件中的内容 |
encoder | Encoder | 编码器配置 |
file | String | 要写入的文件。如果该文件不存在,则创建该文件。该选项没有默认值,示例的配置值为:c:/temp/test.log 或 c:\\temp\\test.log 注意,如果文件的父目录不存在,FileAppender 也会自动的创建它。 |
bufferSize | FileSize | 设置输出缓冲区的大小。默认值为 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 的可用属性:
属性名称 | 类型 | 描述 |
append | boolean | 默认设置为 true,即将日志追加到文件现有内容的末尾。如果为 false,则覆盖原有文件中的内容 |
encoder | Encoder | 编码器配置 |
file | String | 要写入的文件。 请注意,此处文件可以为空,在这种情况下,输出仅写入由 RollingPolicy 指定的目标。 |
rollingPolicy | RollingPolicy | 滚动执行策略,见下文详述 |
triggeringPolicy | TriggeringPolicy | 滚动触发策略,见下文详述 |
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 接口。它的可配置属性如下:
属性名称 | 类型 | 描述 |
fileNamePattern | String | 必须配置,该属性用来定义滚动(归档)日志文件。 该文件名称中一般会包含 %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 属性内,日期和时间模式内任意位置的正斜杠 "/" 或反斜杠 "\" 字符将被解释为目录分隔符。 |
maxHistory | int | 该属性用于控制要保留的归档文件的最长时间,超过该配置时间的旧文件会被异步删除。 比如,如果指定策略为每月滚动,并将 maxHistory 设置为 6,那么将只保留 6 个月内的存档文件。当旧的存档文件被删除时,为这些文件存档而创建的文件夹都会被删除。 maxHistory 的默认配置为零,即默认情况下不删除存档。 |
totalSizeCap | int | 该属性用于控制所有归档文件的总大小。当超过总大小上限时,最旧的存档将被异步删除。 此外,要使 totalSizeCap 属性生效,还需要设置 maxHistory 属性。框架 首先应用 maxHistory 属性限制,然后再应用 "总大小上限" 限制。//即首先删除超时的,然后再删除超大小的 totalSizeCap 属性的值可以通过在数值后分别添加 KB、MB 和 GB 来指定为字节、千字节、兆字节或千兆字节的单位。 默认情况下,totalSizeCap 设置为零,这意味着没有总大小上限。 |
cleanHistoryOnStart | boolean | 默认情况下,此属性设置为 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 的属性:
属性名称 | 类型 | 描述 |
maxFileSize | FileSize | 当前日志文件在滚动时间到达之前,如果达到 maxFileSize 时,都会从 0 开始递增索引并对其进行归档。 配置值后可以添加 KB、MB 和 GB 等单位来指定字节、千字节、兆字节或千兆字节。 |
checkIncrement | Duration | 检查文件大小是一项成本相对较高的操作,所以默认情况下每 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,因为篇幅限制,不再详细叙述,感兴趣的可以去查阅相关文档。
至此,全文结束。