跳至主要內容

Appender

Jin大约 21 分钟

Appender

1、Appender 入门

官方文档:https://logback.qos.ch/manual/appenders.htmlopen in new window

1.1、什么是 Appenders

logback 将写入日志事件的任务委托给一个名为 appender 的组件。Appender 必须实现 ch.qos.logback.core.Appenderopen in new window 接口。该接口的方法如下:

public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable<E> {

    String getName();
    /**
     * This is where an appender accomplishes its work. Note that the argument is of
     * type Object.
     * 
     * @param event
     */
    void doAppend(E event) throws LogbackException;

    void setName(String name);
}

doAppender() 方法接收一个泛型参数 E 作为唯一的参数。E 的实际参数类型取决于 logback 模块。在 logback-classic 模块里面,E 的类型是 ILoggingEventopen in new window 。在 logback-access 模块里面,E 的类型是 AccessEventopen in new windowdoAppend() 是 logback 框架里面最重要的模块。它的责任是将日志事件进行格式化,然后输出到对应的设备上。

Appender 都是实体类,这样可以确保它们通过名字被引用。Appender 接口继承了 FilterAttachable 接口。使得一个或多个过滤器可以附加到 appender 实例上。

Appender 最基本的责任是将日志事件进行输出。然而,它们可以委托 Layout 或者 Encoder 对象来对日志事件进行格式化。每一个 layout/encoder 有且只与一个 appender 相关联。例如,SocketAppender 仅仅序列化日志事件,然后再通过线路传输。

1.2、继承关系图

image-20240527143553949
image-20240527143553949

1.3、主要输出方式

因为 OutputStreamAppender 是 ConsoleAppender、FileAppender、RollingFileAppender 这3 个非常重要的 Appender 对象的父类,所以重要性不言而喻

  1. ConsoleAppender 控制台输出
  2. RollingFileAppender 根据规则输出到不同文件
  3. FileAppender 输出到文件

2、OutputStreamAppender

2.1、简介

OutputStreamAppenderopen in new window 将事件附加到 java.io.OutputStream 上。这个类提供了其它 appender 构建的基础服务。用户通常不会直接实例一个 OutputStreamAppender 实例。因为一般来说 java.io.OutputStream 类型不能方便的转为 String。因为在配置文件中没有方法去直接指定一个 OutputStream 目标对象。简单来说,你不能通过配置文件配置一个 OutputStreamAppender。但是这并不意味着 OutputStreamAppender 缺少配置属性。这些属性描述如下:

属性名属性值描述
ecoderEncoderopen in new window决定通过哪种方式将事件写入 OutputStreamAppender,Encoder 将会在单独的章节介绍
immediateFlushbooleanimmediateFlush 的默认值为 true。立即刷新输出流可以确保日志事件被立即写入,并且可以保证一旦你的应用没有正确关闭 appender,日志事件也不会丢失。从另一方面来说,设置这个属性为 false,有可能会使日志的吞吐量翻两番(视情况而定)。但是,设置为 false,当应用退出的时候没有正确关闭 appender,会导致日志事件没有被写入磁盘,可能会丢失。

OutputStreamAppender 是其他三个 appender 的父类,分别是 ConsoleAppenderFileAppender 以及 RollingFileAppenderFileAppender 又是 RollingFileAppender 的父类。下面的类图展示 OutputStreamAppender 与子类之间的关系:

appenderClassDiagram
appenderClassDiagram

3、ConsoleAppender

3.1、简介

ConsoleAppenderopen in new window 就跟名字显示的一样,是将日志事件附加到控制台,跟进一步说就是通过 System.out 或者 System.err 来进行输出。默认通过前者。ConsoleAppender 通过用户指定的 encoder,格式化日志事件。Encoder 会在接下来的章节讨论。System.outSystem.err 两者都是 java.io.PrintStream 类型。因此,它们被包装在可以进行 I/O 缓存操作的 OutputStreamWriter 中。

3.2、属性

属性名类型描述
encoderEncoderopen in new windowOutputStreamAppender 属性
targetStringSystem.outSystem.err。默认为 System.ou
withJansibooleanwithJansi 的默认值为 false。设置 withJansitrue 可以激活 Jansiopen in new window 在 windows 使用 ANSI 彩色代码。在 windows 上如果设置为 true,你应该将 org.fusesource.jansi:jansi:1.9 这个 jar 包放到 classpath 下。基于 Unix 实现的操作系统,像 Linux、Max OS X 都默认支持 ANSI 才彩色代码。

3.3、配置示例

<configuration>

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

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

4、FileAppender

4.1、简介

FileAppenderopen in new windowOutputStreamAppender 的子类,将日志事件输出到文件中。通过 file 来指定目标文件。如果该文件存在,根据 append 的值,要么将日志追加到文件中,要么该文件被截断。

4.2、属性

属性名类型描述
appendboolean如果为 true,日志事件会被追加到文件中,否则的话,文件会被截断。默认为 true
encoderEncoderopen in new window编码器配置
fileString要写入文件的名称。如果文件不存在,则新建。在 windows 平台上,用户经常忘记对反斜杠进行转义。例如,c:\temp\test.log 不会被正确解析,因为 '\t' 是一个转义字符,会被解析为一个 tab 字符 (\u0009)。正确的值应该像:c:/temp/test.log 或者 c:\temp\test.log。没有默认值。
prudentboolean在严格模式下,FileAppender 会将日志安全的写入指定文件。即使在不同的 JVM 或者不同的主机上运行 FileAppender 实例。默认的值为 false。 严格模式可以与 RollingFileAppender 结合使用。 严格模式也意味着 append 属性被自动设置为 true。 严格模式依赖排他文件锁。实验证明,文件锁大概是写入日志事件成本的 3 倍。在严格模式关闭的情况下,往一台"普通"电脑的硬盘上将一个日志事件写入文件,大概需要耗费 10 微秒。但是在开启的情况下,大概需要 30 微秒。也就是说在关闭的情况下可以一秒钟写入 100'000 个日志事件,但是在开启的情况下,一秒钟只能写入33'000 个日志事件。 严格模式可以在所有 JVM 写入同一个文件时,有效的序列化 I/O 操作。因此,随着竞相访问同一个文件的 JVM 数量上升,将会延迟每一个 I/O 操作。只要总共的 I/O 操作大约为每秒 20 个日志请求,对性能的影响可以被忽略。但是,如果应用每秒产生了 100 个以上的 I/O 操作,性能会受到明显的影响,应该避免使用严格模式。 网络文件锁 当日志文件位于网络文件系统上时,严谨模式的成本会更高。同样重要的是,网络文件系统的文件锁带有很强的偏向性,当前获得锁的进程在释放锁之后会立马又重新获得。因此,当一个进程独占日志文件,将会导致其它进程饥饿死锁。 严格模式的影响严重依赖网速以及操作系统实现的细节。我们提供了一个小型应用 FileLockSimulatoropen in new window 用于在你的环境中模拟严格模式。

立即刷新 默认情况下,每一个日志事件都会被立即刷新到底层的输出流。默认方法更加的安全,因为日志事件在你的应用没有正确关闭 appender 的情况下不会丢失。但是,要想显著的增加日志的吞吐率,你可以将 immediateFlush 设置为 false

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

4.3、配置示例

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

5、RollingFileAppender

5.1、简介

RollingFileAppenderopen in new window 继承自FileAppender,具有轮转日志文件的功能。例如,RollingFileAppender 将日志输出到 log.txt 文件,在满足了特定的条件之后,将日志输出到另外一个文件。

RollingFileAppender 进行交互的有两个重要的子组件。第一个是 RollingPolicy,它负责日志轮转的功能。另一个是 TriggeringPolicy,它负责日志轮转的时机。所以 RollingPolicy 负责发生什么,TriggeringPolicy 负责什么时候发生。

为了让 RollingFileAppender 生效,必须同时设置 RollingPolicyTriggeringPolicy。但是,如果 RollingPolicy 也实现了 TriggeringPolicy 接口,那么只需要设置前一个就好了。

5.2、属性

属性名类型描述
fileString参见 FileAppender
appendboolean参见 FileAppender
encoderEncoderopen in new window参见 OutputStreamAppender
rollingPolicyRollingPolicy当轮转发生时,指定 RollingFileAppender 的行为。下面将会详细说明
triggeringPolicyTriggeringPolicy告诉 RollingFileAppender 什么时候发生轮转行为。下面将会详细说明
prudentbooleanFixedWindowRollingPolicyopen in new window 不支持该属性。 RollingFileAppender 在使用严格模式时要与 [`TimeBasedRollingPolicy](https://logbackcn.gitbook.io/logback/04-di-si-zhang-appenders#TimeBasedRollingPolicy) 结合使用,但是有两个限制: 1. 在严格模式下,也不支持也不允许文件压缩(我们不能让一个 JVM 在写入文件时,另一个 JVM 在压缩该文件) 2. 不能对 `FileAppender` 的 `file` 属性进行设置。实际上,大多数的操作系统不允许在有进程操作文件的情况下对文件改名。 其它的参考 `FileAppender`

5.3、配置示例

    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${LOG.PATH}/${APP_NAME}_debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${LOG.PATH}/${APP_NAME}-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>150</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

RollingFileAppender执行流程如下:

1、日志始终往file配置的日志文件中追加写入,如file不存在则自动创建,如 /temp/test.log 2、按rollingPolicy配置的策略,当满足策略时,自动将file重命名为rollingPolicy中指定的归档日志文件名,生成历史归档日志,如 /temp/test.2023-04-12.log,并对归档日志进行压缩 和 过期日志删除。 3、循环 1-2

5.4、滚动执行策略(RollingPolicy)

RollingPolicyopen in new window 负责轮转的方式为:移动文件以及对文件改名。

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<?> appender);
}
  • rollover 方法负责对日志文件进行归档。
  • getActiveFileName() 方法负责获取当前日志文件的名字。
  • getCompressionMode 方法决定采取哪种压缩模式。
  • 通过 setParent 方法引用父类。

5.5、TimeBasedRollingPolicy

5.5.1、简介

  • TimeBasedRollingPolicy 是最常用的轮转策略。它是基于时间来定义轮转策略。例如按天或者按月。
  • TimeBasedRollingPolicy 既负责轮转的行为,也负责触发轮转。实际上,TimeBasedRollingPolicy 同时实现了 RollingPolicyTriggeringPolicy 接口。
  • TimeBasedRollingPolicy 的配置需要一个强制的属性 fileNamePattern 以及其它的可选属性。

5.5.2、属性

fileNamePattern
  1. 名称:文件名模式

  2. 类型:String

    • 该属性定义了轮转时的属性名。它的值应该由文件名加上一个 %d 的占位符。%d 应该包含 java.text.SimpleDateFormat 中规定的日期格式。如果省略掉这个日期格式,那么就默认为 yyyy-MM-dd。轮转周期是通过 fileNamePattern 推断出来的。
    • 注意:可以选择对 RollingFileAppenderTimeBasedRollingPolicy 的父类)中的 file 属性进行设置,也可以忽略。通过设置 FileAppenderfile 属性,你可以将当前活动日志的路径与归档日志的路径分隔开来。当前日志永远会是通过 file 指定的文件。它的名字不会随着时间的推移而发生变化。但是,如果你选择忽略 file 属性,当前活动日志在每个周期内将会根据 fileNamePattern 的值变化。
    • %d{} 中的日期格式将会遵循 java.text.SimpleDateFormat 中的约定。斜杆 '/' 或者反斜杠 '' 都会被解析成目录分隔符。
  3. 指定多个 %d

    • 可以指定多个 %d,但是只能有一个是主要的,用于推断轮转周期。其它的 %d 占位符必须通过 'aux' 标记为辅助的。见下面的示例: 多个 %d 占位符允许你在文件夹中去管理归档文件,这个跟轮转周期不同。如下所示:通过年月来管理日志文件夹,但是轮转周期是在每天晚上零点。

    • /var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log
      
      ${LOG_FILE_PATH}/info-%d{yyyy-MM-dd}.%i.log
      
  4. TimeZone

    • 在某些情况下,你可能想要根据时区而不是主机的时钟来轮转日志。你可以通过如下方式来指定一个时区,例如:

    • ${LOG_FILE_PATH}/info-%d{yyyy-MM-dd-HH, UTC}.%i.log
      
    • 参考 TimeZone.getTimeZone(String)open in new window 方法指定为 GMT。

fileNamePattern值和作用

这里列出了一些fileNamePattern值及其作用的解释。

fileNamePattern轮转周期示例
/wombat/foo.%d每天轮转(晚上零点)。由于省略了指定 %d 的日期格式,所以默认为 yyyy-MM-dd没有设置 file 属性:在 2006.11.23 这一天的日志都会输出到 /wombat/foo.2006-11-23 这个文件。晚上零点以后,日志将会输出到 wombat/foo.2016-11-24 这个文件。 设置 file 的值为 /wombat/foo.txt:在 2016.11.23 这一天的日志将会输出到 /wombat/foo.txt 这个文件。在晚上零点的时候,foo.txt 将会被改名为 /wombat/foo.2016-11-23。然后将创建一个新的 foo.txt,11.24 号这一天的日志将会输出到这个新的文件中。
/wombat/%d{yyyy/MM}/foo.txt每个月开始的时候轮转没有设置 file 属性:在 2016.10 这一个月中的日志将会输出到 /wombat/2006/10/foo.txt。在 10.31 晚上凌晨以后,11 月份的日志将会被输出到 /wombat/2006/11/foo.txt。 设置 file 的值为 /wombat/foo.txt:在 2016.10,这个月份的日志都会输出到 /wombat/foo.txt。在 10.31 晚上零点的时候,/wombat/foo.txt 将会被重命名为 /wombat/2006/10/foo.txt,并会创建一个新的文件 /wombat/foo.txt ,11 月份的日志将会输出到这个文件。依此类推。
/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每分钟轮转跟之前的例子类似,不过时间格式是 UTC
/foo/%d{yyyy-MM, aux}/%d.log每天轮转。归档文件在包含年月的文件夹下第一个 %d 被辅助标记。第二个 %d 为主要标记,但是日期格式省略了。因此,轮转周期为每天(由第二个 %d 控制),文件夹的名字依赖年与月。例如,在 2016.11 的时候,所有的归档文件都会在 /foo/2006-11/ 文件夹下,如:/foo/2006-11/2006-11-14.log

任何斜杆或者反斜杠够会被当作文件夹分隔符。任何必要的文件夹都会在有需要的时候创建。你可以轻松的将日志文件放在单独的文件夹中。

fileNamePattern 有两个目的。logback 通过该属性可以进行周期性的轮转并且得到每个归档文件的名字。注意,两种跟不同的 pattern 可能会有相同的轮转周期。yyyy-MMyyyy@MM 同样都是按月轮转,但是归档文件最终的名字不一样。

通过设置 file 属性,你可以将活动日志文件的路径与归档文件的路径分隔开来。日志将会一直输出到通过 file 属性指定的文件中,并且不会随着时间而改变。但是,如果你选择忽略 file 属性,活动日志的名字将会根据 fileNamePattern 的值在每个周期内变化。不设置 file 属性的时候,如果在轮转期间存在外部文件句柄引用日志文件,将会避免命名错误open in new window

自动压缩

TimeBasedRollingPolicy 支持文件自动压缩。如果 fileNamePattern.gz 或者 .zip 结尾,将会启动这个特性。示例如下:

${LOG_FILE_PATH}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log.zip

${LOG_FILE_PATH}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log.gz
maxHistory
  1. 名称:最大历史记录
  2. 类型:int
  3. 这个可选的属性用来控制最多保留多少数量的归档文件,将会异步删除旧的文件。
    • 比如,你指定按月轮转,指定 maxHistory = 6,那么 6 个月内的归档文件将会保留在文件夹内,大于 6 个月的将会被删除。
    • 注意:当旧的归档文件被移除时,当初用来保存这些日志归档文件的文件夹也会在适当的时候被移除
    • 将maxHistory设置为零可禁用存档删除。默认情况下,maxHistory设置为零,即默认情况下不会删除存档。
  4. 由于各种技术原因,轮转并不是时间驱动的,而是依赖日志事件。例如,在 2002.03.08,假设 fileNamePattern 的值为 yyyy-MM-dd(按天轮转),在晚上零点之后,没有日志事件到来,假设在 23 分 47 秒之后,第一个到达的日志事件将会触发轮转。也就是说轮转实际发生在 03.09 00:23'47 AM 而不是 0:00 AM。因此,依赖日志事件的到达速度,所以轮转可能会有延迟。但是,不管延迟的情况是什么样,一定周期内生成的日志事件将会被输出到指定的文件中,从这个角度来看,轮转算法始终都会是正确的。
totalSizeCap
  1. 名称:总尺寸上限
  2. 类型:int
  3. 这个可选属性用来控制所有归档文件总的大小。当达到这个大小后,旧的归档文件将会被异步的删除。使用这个属性时还需要设置 maxHistory 属性。而且,maxHistory 将会被作为第一条件,该属性作为第二条件。
  4. totalSizeCap属性可以以字节、千字节、兆字节或千兆字节为单位指定,方法是在数值后分别添加 KB、MB 和 GB 后缀。例如,5000000、5000KB、5MB 和 2GB 都是有效值,前三个值相等。没有后缀的数值被视为以字节为单位。
  5. 默认情况下,totalSizeCap设置为零,表示没有总尺寸上限。
cleanHistoryOnStart
  1. 名称:启动时删除存档
  2. 类型:布尔值
  3. 默认的值为 false
  4. 如果设置为 true,那么在 appender 启动的时候,归档文件将会被删除。默认的值为 false。 归档文件的删除通常在轮转期间执行。但是,有些应用的存活时间可能等不到轮转触发。对于这种短期应用,可以通过设置该属性为 true,在 appender 启动的时候执行删除操作。

5.5.3、TimeBasedRollingPolicy 配置示例

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

      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <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>

5.5.4、prudent 模式下(严格模式)示例

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 支持多个 JVM 同时写一个文件 -->
        <prudent>true</prudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>

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

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

5.6、基于大小以及时间的轮转策略 ( SizeAndTimeBasedRollingPolicy )

5.6.1、简介

有时你希望按时轮转,但同时又想限制每个日志文件的大小。特别是如果后期处理工具需要对日志进行大小限制。

为了满足这个需求,logback 配备了 SizeAndTimeBasedRollingPolicy

注意,TimeBasedRollingPolicy 可以限制归档文件总的大小。所以如果你想要这个限制,你可以通过设置 totalSizeCap 来达到这个目的。

基于大小的滚动除了依赖于"%d" 之外,还依赖于"%i"转换标记。%i 和 %d 标记都是必需的。每次当前日志文件在当前时间段结束之前达到maxFileSize时,它将以从 0 开始的递增索引进行归档。

5.6.2、属性

maxFileSize
  1. 名称:最大文件大小
  2. 类型:int
  3. 每次在当前时间段结束之前当前日志文件达到maxFileSize时,它将以从 0 开始的增加索引进行存档。
  4. 以“文件大小”为单位定义的选项可以以字节、千字节、兆字节或千兆字节为单位指定,方法是在数值后分别添加 KB、MB 和 GB。例如,5000000、5000KB、5MB 和 2GB 都是有效值,前三个值是等效的。
checkIncrement

自 1.3.12/1.4.12 起鉴于检查文件大小是一项相对昂贵的操作,默认情况下每 60 秒执行一次。但是,您可以将不同的检查增量设置为duration。

5.6.3、SizeAndTimeBasedRollingPolicy 配置示例

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <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>

5.6.4、源码

public class SizeAndTimeBasedRollingPolicy<E> extends TimeBasedRollingPolicy<E> {
    FileSize maxFileSize;

    public SizeAndTimeBasedRollingPolicy() {
    }
    ......
}

5.6.5、版本差异

在 1.1.7 之前的版本中一个名为 的组件SizeAndTimeBasedFNATP。但是,鉴于 SizeAndTimeBasedRollingPolicy提供了更简单的配置结构,官网不推荐使用 SizeAndTimeBasedFNATP。但是 SizeAndTimeBasedFNATP 仍可以正常使用,事实上, SizeAndTimeBasedRollingPolicy是用 SizeAndTimeBasedFNATP子组件实现的。

以下是老版本用法

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${LOG.PATH}/${APP_NAME}-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>150</maxHistory>
        </rollingPolicy>

对比新版本

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG.PATH}/${APP_NAME}-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
            <maxFileSize>10MB</maxFileSize>
            <totalSizeCap>0</totalSizeCap>
            <maxHistory>150</maxHistory>
        </rollingPolicy>

6、触发策略 TriggeringPolicy

6.1、概述

TriggeringPolicy 实现负责指示 RollingFileAppender何时进行翻转。该TriggeringPolicy接口仅包含一个方法。

package ch.qos.logback.core.rolling;

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

public interface TriggeringPolicy<E> extends LifeCycle {

  public boolean isTriggeringEvent(final File activeFile, final <E> event);
}

isTriggeringEvent() 方法接收当前活动的文件以及当前的日志事件作为参数。基于这些参数,通过具体的实现来决定轮转是不是应该发生。

TimeBasedRollingPolicy 是使用最广泛的触发策略。也可以用作轮转策略来使用。

6.2、SizeBasedTriggeringPolicy

SizeBasedTriggeringPolicyopen in new window 观察当前活动文件的大小,如果已经大于了指定的值,它会给 RollingFileAppender 发一个信号触发对当前活动文件的轮转。

SizeBasedTriggeringPolicy 只接收 maxFileSize 这一个参数,它的默认值是 10 MB。

maxFileSize 可以为字节,千字节,兆字节,千兆字节,通过在数值后面指定一个后缀 KBMB 或者 GB。例如,50000005000KB5MB 以及 2GB 都是有效的,前三个是一样的。

源码

public class SizeBasedTriggeringPolicy<E> extends TriggeringPolicyBase<E> {

    public static final String SEE_SIZE_FORMAT = "http://logback.qos.ch/codes.html#sbtp_size_format";
    /**
     * The default maximum file size.
     */
    public static final long DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB

    FileSize maxFileSize = new FileSize(DEFAULT_MAX_FILE_SIZE);
    InvocationGate invocationGate = new SimpleInvocationGate();
    Duration checkIncrement = null;

    public SizeBasedTriggeringPolicy() {
    }
    ......
}

4.5、Filter

过滤器,过滤满足条件或者不满足条件的日志 允许组合使用,可配置多个 过滤器有很多,只介绍两种常用的LevelFilterThresholdFilter

名称值说明说明备注
LevelFilter级别过滤器精确匹配指定的日志级别
ThresholdFilter阈值过滤匹配等于或高于指定级别

使用示例如下

        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->

    <!-- 拒绝所有级别低于 INFO 的, 也就是 TRACE 和 DEBUG -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>

LevelFilter属性

属性值类型说明
level匹配级别OFF、ERROR、WARN、INFO、DEBUG、TRACE、ALL
onMatchDENY, NEUTRAL, ACCEPTDENY:拒绝,不再执行后续的过滤器
NEUTRAL:中性,继续执行后面的过滤器
ACCEPT:接受,记录日志,不再执行后续过滤器
onMismatchDENY, NEUTRAL, ACCEPT同上

6、文件唯一命名 (使用时间戳)

在应用的开发阶段或者短期应用中,例如:批处理程序,在每个应用启动的时候创建一个新的日志文件。通过 <timestamp> 元素可以轻易做到这点。

timestamp 元素需要两个强制的属性 keydatePattern 以及可选的属性 timeReferencekey 属性的值是来区分哪个 timestamp 元素,并且在后续的配置中可以通过TODO 变量替换open in new window来使用。datePattern 属性用于将当前时间格式化成字符串。日期格式必须遵循 SimpleDateFormatopen in new window 中的规范。timeReference 表示时间戳引用哪个时间。默认为解析配置文件的时间,也就是当前时间。但是,在一些特定的情况下,可以设置为上下文初始化的时间。通过 设置 timeReference 的值为 contextBirth

<configuration>
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" 
             timeReference="contextBirth"/>
  ...
</configuration>
贡献者: Jin