日志框架 Logback 官方手册(第四章:Appenders)

以下内容翻译整理自logback官方手册,地址:logback官方手册


Appender 是什么?

Logback将编写日志事件的任务委托给称为appenders的组件。Appenders必须实现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 {

  public String getName();
  public void setName(String name);
  void doAppend(E event);
  
}

Appender接口中的大多数方法都是settergetter。只有doAppend()方法是例外的,它将一个类型为E的对象作为参数。E的实际类型将根据logback模块的不同而有所不同。在logback-classic模块中,E的类型是ILoggingEvent,在logback-access模块中,E的类型是AccessEventdoAppend()方法是logback框架中最重要的方法。它负责将日志事件以适当的格式输出到适当的输出设备。

Appenders是可以被命名的。这确保了可以通过名称引用它们,这是脚本配置中很重要的一个特性。Appender接口扩展了FilterAttachable接口,可以将一个或多个过滤器附加到一个appender实例。过滤器将在下一章详细讨论。

Appenders负责最终输出日志事件。但是,它们可以将日志事件的格式化委托给一个Layout或一个Encoder对象。每个Layout/Encoder都与一个且仅与一个appender关联。有些appenders具有内置或固定的事件格式,因此,它们既不需要也没有Layout/Encoder。例如,SocketAppender只会在通过网络传输日志事件之前对它们进行序列化。

AppenderBase

ch.qos.logback.core.AppenderBase类是实现了Appender接口的一个抽象类。它提供了所有appenders共享的基础功能,例如获取或设置它们的名称、激活状态、布局和过滤器的方法。它是logback自带的所有appenders的超类。虽然是一个抽象类,AppenderBase实际上实现了Appender接口中的doAppend()方法。下面是实现代码:

public synchronized void doAppend(E eventObject) {

  // prevent re-entry.
  if (guard) {
    return;
  }

  try {
    guard = true;

    if (!this.started) {
      if (statusRepeatCount++ < ALLOWED_REPEATS) {
        addStatus(new WarnStatus(
            "Attempted to append to non started appender [" + name + "].",this));
      }
      return;
    }

    if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
      return;
    }
    
    // ok, we now invoke the derived class's implementation of append
    this.append(eventObject);

  } finally {
    guard = false;
  }
}

这里实现的doAppend()是一个同步方法。因此,从不同的线程记录到相同的appender是线程安全的。当线程(例如T)执行doAppend()方法时,其他线程随后的调用将排队,直到T离开doAppend()方法,从而确保Tappender的独占访问。

由于这种同步并不总是合适的,所以logback又提供了一个ch.qos.logback.core.UnsynchronizedAppenderBase,和AppenderBase类非常类似。为了简洁起见,我们在本文档的其余部分只讨论UnsynchronizedAppenderBase

doAppend()方法做的第一件事是检查守卫是否被设置为true。如果是,则立即退出。如果不是,则在下一个语句中将其设置为true。该保护确保doAppend()方法不会递归地调用自己。假设一个在append()方法之外调用的组件想要记录一些东西。它的调用可以直接指向刚才调用它的相同的追加器,从而导致无限循环和堆栈溢出。

在接下来的语句中,我们检查started字段是否为true。如果不是,doAppend()将发送一个警告消息并返回。换句话说,一旦一个appender被关闭了,就不可能再对它进行写入。Appender接口继承了LifeCycle接口,这意味着它的实现类也实现了start()stop()isStarted()方法。设置完appender的所有属性后,Joranlogback的配置框架,它会调用start()方法来通知appender激活其属性。根据其类型的不同,如果某些属性丢失或由于各种属性之间的干扰,appender可能启动失败。例如,考虑到文件创建依赖于截断模式,在Append选项的值被确定之前,FileAppender不能对它的File选项的值执行操作。显式激活步骤确保appender在其属性的值被知道后对其进行操作。

如果appender无法启动或已经停止,将通过logback的内部状态管理系统发出警告消息。经过多次尝试,为了避免同一警告消息的副本充斥内部状态系统,doAppend()方法将停止发出这些警告。

下一个if语句检查附加过滤器的结果。根据过滤器链产生的决策,可以拒绝或显式接受事件。在过滤器链没有做出决定的情况下,默认情况下接受事件。

然后doAppend()方法调用派生类的append()方法实现。此方法的实际工作是将执行将事件附加到适当设备。

最后,释放保护,以便允许随后的请求调用doAppend()方法。

Logback-core

logback -core是构建其他logback模块的基础。提供了几个定制的的appender。在接下来的几节中,我们将介绍这几个的appenders

OutputStreamAppender

OutputStreamAppender追加事件到一个java.io.OutputStream。该类提供了其他appender构建的基础。用户通常不会直接实例化OutputStreamAppender对象,因为一般来说java.io.OutputStream类型不能方便地映射到字符串,因为无法在配置脚本中指定目标OutputStream对象。简单地说,您不能从配置文件配置OutputStreamAppender。然而,这并不意味着OutputStreamAppender缺乏可配置属性,下面将描述这些属性。

属性名称 类型 描述
encoder Encoder 确定将事件写入底层OutputStreamAppender的方式。之后会有专门的一章中介绍编码器。
immediateFlush boolean 即时刷新的默认值是“true”。输出流的立即刷新确保立即写出日志事件,并且在应用程序在没有正确关闭附加程序就退出时不会丢失日志事件。另一方面,将此属性设置为“false”可能会使日志吞吐量增加四倍(因人而异)。但是,如果在应用程序退出时没有正确关闭appenders,那么尚未写入磁盘的日志事件可能会丢失。

OutputStreamAppender是其他三个追加器的超类,也就是ConsoleAppenderFileAppenderRollingFileAppender的超类。下图展示了OutputStreamAppender及其子类的类图。

ConsoleAppender

ConsoleAppender,顾名思义,附加在控制台,或者更准确地说是System.out或者System.err。前者是默认目标。ConsoleAppender在用户指定的编码器的帮助下格式化事件。编码器将在下一章中讨论。这两个System.outSystem.err的类型是java.io.PrintStream,因此,它们是被封装在OutputStreamWriter中的缓冲 I/O 操作。

属性名称 类型 描述
encoder Encoder OutputStreamAppender的属性介绍。
target String 一个字符串值System.out或者System.err,默认是System.out
withJansi boolean 默认情况下,withJansi属性被设置为false。将withJansi设置为true将激活Jansi库,该库在Windows机器上提供对ANSI颜色代码的支持。在一个Windows主机上,如果这个属性被设置为true,那么您应该在类路径上添加“org.fusesource.jansi:jansi:1.9”。注意,LinuxMac OS X等基于unix的操作系统默认支持ANSI颜色代码。

下面是一个使用ConsoleAppender的示例配置。

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

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

FileAppender

FileAppenderOutputStreamAppender的一个子类,追加日志事件到一个文件中,目标文件由File选项指定。如果文件已经存在,根据append属性的值,要么被追加,要么被截断。

属性名称 类型 描述
append boolean 如果为true,事件将追加到现有文件的末尾。如果appendfalse,则截断任何现有文件。append选项默认为true
encoder Encoder OutputStreamAppender的属性介绍。
file String 要写入的文件的名称,如果文件不存在,就创建它。在Windows平台上,文件c:\temp\test.log应该被写为c:/temp/test.logc:\\temp\\test.logFile选项没有默认值。如果文件的父目录不存在,FileAppender会自动创建它。
prudent boolean (1)在谨慎模式下,FileAppender将安全地写入指定的文件,即使存在运行在不同JVM(可能运行在不同主机上)中的其他FileAppender实例。prudent的默认值为false。谨慎模式可以与RollingFileAppender一起使用。谨慎模式意味着append属性被自动设置为true(2) prudent更多地依赖于排他性文件锁。实验表明,文件锁定的开销大约是编写日志事件开销的三倍(x3)。在对本地硬盘上的文件进行写操作时,如果关闭了谨慎模式,写一个日志事件大约需要10微秒。当谨慎模式打开时,写一个日志事件大约需要30微秒。(3)谨慎模式有效地序列化所有写到同一文件的JVM之间的 I/O 操作。因此,随着争用访问文件的JVM数量的增加,每次 I/O 操作造成的延迟也会增加。只要 I/O 操作的总数低于每秒20个日志请求,对性能的影响应该可以忽略不计。如果每秒生成100个或更多 I/O 操作的应用程序可以看到对性能的影响,应该避免使用谨慎的模式。(4)当日志文件位于网络文件系统中时,谨慎模式的成本甚至更高。同样重要的是,网络文件系统上的文件锁有时可能存在严重偏差,导致当前拥有锁的进程在释放锁时立即重新获得锁。因此,当一个进程占用日志文件锁时,其他进程在等待锁时超时,直到出现死锁。(5)谨慎模式的影响高度依赖于网络速度和操作系统实现细节。我们提供了一个非常小的应用程序 FileLockSimulator,它可以帮助您模拟环境中谨慎模式的行为。

默认情况下,每个日志事件都会立即刷新到底层输出流。从某种意义上说,如果应用程序在没有正确关闭appenders的情况下退出,日志事件不会丢失,这种默认方法更安全。但是,为了显著提高日志吞吐量,您可能需要将immediateFlush属性设置为false。下面是FileAppender配置文件的一个例子:

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- 将immediateFlush设置为false,以获得更高的日志吞吐量 -->
    <immediateFlush>true</immediateFlush>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

唯一命名的文件(按时间戳)

在应用程序开发阶段或短期应用程序的情况下,例如,批量应用程序,最好在每次启动新的应用程序时创建一个新的日志文件。在<timestamp>元素的帮助下,这非常容易做到。下面是一个例子:

<configuration>

  <!-- 插入一个格式为"yyyyMMdd'T'HHmmss"的时间戳"bySecond"到日志记录器上下文。这个值将是可用于所有后续配置元素 -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- use the previously created timestamp to create a uniquely
         named log file -->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

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

timestamp元素接受两个强制属性keydatePattern,以及一个可选的timeReference属性。key属性的值是时间戳名称,后续配置元素可以通过引用该名称将时间戳作为变量。datePattern属性表示用于将当前时间转换为字符串的日期格式。日期模式应该遵循SimpleDateFormat中定义的约定。timeReference属性表示时间戳的时间引用。默认值是当前时间。然而,在某些情况下,可能需要使用上下文出生时间作为时间引用。这可以通过将timeReference属性设置为“contextBirth”来实现。如下所示:

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

RollingFileAppender

RollingFileAppender扩展了FileAppender,使其能够滚动日志文件。例如,RollingFileAppender可以将日志记录到一个名为log.txt的文件中,一旦满足某个条件,就将其日志记录目标更改为另一个文件。

RollingFileAppender有两个重要的子组件。第一个是RollingPolicy,负责滚动所需的操作。第二个子是TriggeringPolicy,负责什么时候进行触发滚动。

要想发挥任何作用,RollingFileAppender必须同时设置RollingPolicyTriggeringPolicy。但是,如果它的RollingPolicy也实现TriggeringPolicy接口,那么只需要显式地指定前者。下面是RollingFileAppender的可用属性:

属性名称 类型 描述
file String FileAppender属性描述。
append boolean FileAppender属性描述。
encoder Encoder OutputStreamAppender的属性介绍。
rollingPolicy RollingPolicy 在发生翻转时指示RollingFileAppender行为的组件。请参阅下面的更多信息。
triggeringPolicy TriggeringPolicy 告诉RollingFileAppender何时激活翻转过程。请参阅下面的更多信息。
prudent boolean 在谨慎模式下不支持FixedWindowRollingPolicy。谨慎模式下RollingFileAppender支持与TimeBasedRollingPolicy结合使用,有两个限制:(1)在谨慎模式下,不支持也不允许文件压缩。(我们不能让一个JVM在另一个JVM压缩文件时写入文件)(2)FileAppenderfile属性必须保持空白。实际上,大多数操作系统都不允许在打开另一个进程时重命名文件。详情请参见FileAppender的属性描述。

滚动策略概述

RollingPolicy负责包含文件移动和重命名的翻转过程。RollingPolicy接口如下所示:

package ch.qos.logback.core.rolling;  

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;

public interface RollingPolicy extends LifeCycle {

  public void rollover() throws RolloverFailure;
  public String getActiveFileName();
  public CompressionMode getCompressionMode();
  public void setParent(FileAppender appender);
}

rollover方法完成了归档当前日志文件所涉及的工作。调用getActiveFileName()方法来计算当前日志文件的文件名(写入活动日志的地方)。如getCompressionMode方法所示,滚动策略还负责确定压缩模式。最后,通过setParent方法向滚动策略提供对其父策略的引用。

TimeBasedRollingPolicy

TimeBasedRollingPolicy可能是最流行的滚动策略。它定义了一个基于时间的滚动策略,例如按天或按月。基于时间的滚转策略同时承担滚转和触发滚转的责任。实际上,TimeBasedTriggeringPolicy同时实现了RollingPolicyTriggeringPolicy接口。TimeBasedRollingPolicy的配置采用一个强制性的fileNamePattern属性和几个可选属性。

属性名称 类型 描述
fileNamePattern String (1)强制的fileNamePattern属性定义了滚动(存档)日志文件的名称。它的值应该由文件名组成,加上适当放置的%d转换说明符。%d转换说明符可以包含java.text.SimpleDateFormat指定的日期和时间模式。如果省略了日期和时间模式,会指定默认模式yyyy-MM-dd。滚转周期由fileNamePattern的值推断得出。(2)注意,可以设置或省略RollingFileAppender(TimeBasedRollingPolicy的父类)中的file属性。通过设置包含FileAppenderfile属性,您可以解耦活动日志文件的位置和归档日志文件的位置。当前日志总是针对file属性指定的文件。因此,当前活动日志文件的名称不会随时间而更改。但是,如果您选择忽略file属性,那么活动文件将根据fileNamePattern的值为每个周期重新计算一次。下面的例子可以说明这一点。(3)时间和日期模式,%d{}中内容遵循java.text.SimpleDateFormat约定。在fileNamePattern属性或日期和时间模式中的任何位置上的正斜杠'/'或反斜杠'\'字符都将被解释为目录分隔符。(4)多个%d说明符:可以指定多个%d说明符,但其中只能有一个是主说明符,即用于推断滚动周期。所有其他令牌都必须通过传递“aux”参数标记为辅助性的(参见下面的示例)。多个%d说明符允许您在不同于滚转期间的文件夹结构中组织归档文件。例如,下面所示的文件名模式按年/月组织日志文件夹,但每天在午夜时会将日志文件滚动按天生成一个文件。/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log(5)时区:在某些情况下,您可能希望根据不同于主机时区的时钟来滚动日志文件。可以在%d转换说明符中按照日期和时间模式传递时区参数。例如:aFolder/test.%d{yyyy-MM-dd-HH, UTC}.log。如果指定的时区标识符未知或拼写错误,根据TimeZone.getTimeZone(String)方法规范指定为GMT时区。
maxHistory int 可选的maxHistory属性控制要保存的最大归档文件数量,异步删除旧文件。例如,如果您指定每月滚动,并将maxHistory设置为6,就会保存6个月的存档文件,删除6个月以上的文件。注意,随着旧归档日志文件的删除,为日志文件存档而创建的任何文件夹都将被适当地删除。
totalSizeCap int 可选的totalSizeCap属性控制所有存档文件的总大小。当超过总大小上限时,将异步删除最旧的存档。totalSizeCap属性也需要设置maxHistory属性。此外,总是先应用“最大历史”限制,然后应用“总大小上限”限制。
cleanHistoryOnStart boolean 如果设置为true,将在appender启动时执行删除存档。默认情况下,此属性设置为false

下面是一些fileNamePattern值,并解释了它们的效果。

fileNamePattern Rollover schedule Example
/wombat/foo.%d 每日翻转(午夜)。由于省略了%d说明符的时间和日期模式,所以设定了默认模式yyyy-MM-dd,对应于每天的翻转。 (1)文件属性未设置:在2006年11月23日,日志输出将进入文件/wombat/foo.2006-11-23。在午夜和24日剩下的时间里,日志输出将定向到/wombat/foo.2006-11-24(2)文件属性设置为/wombat/foo.txt:在2006年11月23日,日志输出将进入文件/wombat/foo.txt。午夜时分,foo.txt将更名为/wombat/foo.2006-11-23。将创建一个新的/wombat/foo.txt文件,11月24日剩余的日志输出将定向到新的foo.txt
/wombat/%d{yyyy/MM}/foo.txt 每月初进行滚转。 (1)文件属性未设置:在2006年10月,日志输出将转到/wombat/2006/10/foo.txt。在10月31日午夜之后,在11月的剩余时间里,日志输出将定向到/wombat/2006/11/foo.txt(2)文件属性设置为/wombat/foo.txt:活动日志文件将一直是/wombat/foo.txt。在2006年10月期间,日志输出转到/wombat/foo.txt。10月31日午夜,/wombat/foo.txt将更名为/wombat/2006/10/foo.txt。将创建一个新的/wombat/foo.txt文件,11月份剩余时间的日志输出将放在该文件中。在11月30日午夜,/wombat/foo.txt将更名为/wombat/2006/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 在每一分钟的开始滚动。 与前面的情况类似,只是文件名将用UTC表示。
/foo/%d{yyyy-MM,aux}/%d.log 每天翻转。档案位于包含年和月的文件夹下。 在本例中,第一个%d说明符被标记为辅助的。第二个%d说明符省略了时间和日期模式,是主要的。因此,滚动将每天发生(%d的缺省值yyyy-MM-dd),文件夹名称将取决于年份和月份。例如,在2006年11月期间,存档文件将全部放在/foo/2006-11/文件夹例如:/foo/2006-11/2006-11-14.log

任何向前或向后斜杠字符都被解释为文件夹(目录)分隔符。任何需要的文件夹都将根据需要创建。因此,您可以轻松地将日志文件放在单独的文件夹中。

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

fileNamePattern Rollover schedule Example
/wombat/foo.%d.gz 每日滚动(在午夜)与自动GZIP压缩存档文件。 (1)文件属性未设置:在2009年11月23日期间,日志输出将转到文件/wombat/foo.2009-11-23。然而,在午夜,该文件将被压缩为/wombat/foo.2009-11-23.gz。11月24日,日志输出将定向到/wombat/folder/foo.2009-11-24,直到第二天它被滚动。(2)文件属性设置为/wombat/foo.txt:在2009年11月23日,日志输出将进入文件/wombat/foo.txt。在午夜,该文件将被压缩并重新命名为/wombat/foo.2009-11-23.gz。将创建一个新的/wombat/foo.txt文件,11月24日剩余时间的日志输出将放在该文件中。11月24日午夜,/wombat/foo.txt将被压缩并改名为/wombat/foo.2009-11-24.gz,以此类推。

fileNamePattern有双重用途。首先,通过研究模式,logback计算请求的翻转周期。其次,它计算每个存档文件的名称。注意,两种不同的模式可以指定相同的周期性。模式yyyy-MMyyyy@MM都指定了每月的滚动,尽管生成的归档文件将使用不同的名称。

通过设置file属性,您可以解耦活动日志文件的位置和存档日志文件的位置。日志输出将定向到file属性指定的文件中。因此,活动日志文件的名称不会随时间而更改。但是,如果您选择忽略file属性,然后根据fileNamePattern的值为每个周期重新计算活动文件。通过不设置file选项,您可以避免文件重命名错误,这些错误发生在存在外部文件句柄在滚转期间引用日志文件时。

由于各种技术原因,滚动不是时钟驱动的,而是取决于日志事件的到来。例如,在2002年3月8日,假设fileNamePattern设置为yyyy-MM-dd(每日翻转),午夜后第一个事件的到来将触发翻转。如果在午夜之后的23分47秒内没有日志记录事件,那么翻转实际上将发生在3月9日凌晨00:23'47,而不是凌晨0:00。因此,根据事件的到达率,可能会触发一些延迟的滚动。但是,不管延迟如何,翻转算法是正确的,因为在某个时间段内生成的所有日志事件都将输出到分隔该时间段的正确文件中。

下面是RollingFileAppenderTimeBasedRollingPolicy的示例配置。

<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} - %msg%n</pattern>
    </encoder>
  </appender> 

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

下一个配置示例演示了在谨慎模式下使用与TimeBasedRollingPolicy关联的RollingFileAppender

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

SizeAndTimeBasedRollingPolicy

有时,您可能希望按日期归档文件,但同时限制每个日志文件的大小,特别是如果之后使用的处理工具对日志文件有大小限制时。为了满足这一需求,logback提供了SizeAndTimeBasedRollingPolicy

注意,TimeBasedRollingPolicy已经允许限制归档日志文件的总体大小。如果只希望限制日志归档文件的总体大小,那么上面描述的TimeBasedRollingPolicy设置totalSizeCap属性应该就够用了。

下面是一个示例配置文件,演示了基于时间和单个文件大小的日志文件归档。

<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>
       <!-- 每个文件最多100MB,保存60天的历史记录,但总大小最多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>

注意%d之外的%i转换符号。%i%d转换符都是必需的,每次当前日志文件在当前时间段结束之前达到maxFileSize时,将使用一个递增索引(从0开始)对其进行归档。

基于大小和时间的存档支持删除旧的存档文件。您需要使用maxHistory属性指定要保存的周期数。当应用程序停止并重新启动时,日志将继续记录在正确的位置,即当前期间的最大索引号。

1.1.7之前的版本中,这个文档提到了一个名为SizeAndTimeBasedFNATP的组件。但是,考虑到SizeAndTimeBasedFNATP配置结构比较简单,我们不再记录SizeAndTimeBasedFNATP。不过,使用SizeAndTimeBasedFNATP的早期配置文件将继续正常工作。实际上,SizeAndTimeBasedRollingPolicy是用SizeAndTimeBasedFNATP子组件实现的。

FixedWindowRollingPolicy

当滚动时,FixedWindowRollingPolicy根据下面描述的固定窗口算法重命名文件。fileNamePattern选项表示归档(滚动)日志文件的文件名模式。此选项是必需的,并且必须在模式中包含整数令牌%i。下面是FixedWindowRollingPolicy的可用属性。

属性名称 类型 描述
minIndex int 此选项表示窗口索引的下界。
maxIndex int 此选项表示窗口索引的上界。
fileNamePattern String 此选项表示在重命名日志文件时紧跟着FixedWindowRollingPolicy的模式。它必须包含字符串%i,该字符串表示将插入当前窗口索引值的位置。例如,使用与最小值和最大值为13关联的MyLogFile%i.log将生成名为MyLogFile1.logMyLogFile2.logMyLogFile3.log的归档文件。注意,文件压缩也是通过这个属性指定的。例如,fileNamePattern设置为MyLogFile%i.log.zip,这意味着存档文件必须使用zip格式进行压缩;还支持gz格式。

由于固定窗口滚动策略需要的文件重命名操作与窗口大小一样多,因此强烈建议不要使用较大的窗口大小。当用户指定较大的值时,当前实现将自动将窗口大小减小到20。

让我们来看一个关于固定窗口翻转策略的更具体的例子。假设minIndex设置为1maxIndex设置为3fileNamePattern属性设置为foo%i.logfile属性被设置为foo.log

滚动数量 活动输出目标 存档日志文件 描述
0 foo.log - 还没有发生滚转,将日志返回到初始文件。
1 foo.log foo1.log 第一次翻转。foo.log被重命名为foo1.log。创建一个新的foo.log文件并成为活动输出目标。
2 foo.log foo1.log, foo2.log 第二次翻转。将foo1.log重命名为foo2.logfoo.log被重命名为foo1.log。创建一个新的foo.log文件并成为活动输出目标。
3 foo.log foo1.log, foo2.log, foo3.log 第三个翻转。将foo2.log重命名为foo3.log。将foo1.log重命名为foo2.logfoo.log被重命名为foo1.log。创建一个新的foo.log文件并成为活动输出目标。
4 foo.log foo1.log, foo2.log, foo3.log 在这轮和随后的几轮中,滚动从删除log.foo3.log开始。其他文件通过增加索引重命名,如前面的步骤所示。在接下来的滚动中,将一直有三个归档日志和一个活动日志文件。

下面的配置文件给出了一个配置RollingFileAppenderFixedWindowRollingPolicy的示例。注意,File选项是强制性的,即使它包含与fileNamePattern选项所传递的一些相同的信息。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>tests.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

触发策略概述

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,它也是滚动策略的两倍,前面已经与其他滚动策略一起讨论过。

SizeBasedTriggeringPolicy

SizeBasedTriggeringPolicy查看当前活动文件的大小。如果它的大小超过指定的大小,它将向拥有的RollingFileAppender发出信号,触发现有活动文件的翻转。

SizeBasedTriggeringPolicy只接受一个参数maxFileSize,默认值为10MB

maxFileSize选项可以用字节、千字节、兆字节或千兆字节来指定,方法是分别用KBMBGB作为数字值的后缀。例如,50000005000KB5MB2GB都是有效值,前三个值是等价的。

下面是一个带有RollingFileAppender的示例配置,它与SizeBasedTriggeringPolicy一起在日志文件达到5MB时触发翻转。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Logback Classic

虽然日志事件在logback-core中是通用的,但在logback-classic中,它们始终是ILoggingEvent的实例。Logback-classic不过是一个专门处理ILoggingEvent实例的管道。

SocketAppender 和 SSLSocketAppender

到目前为止,所涉及的appenders只能记录日志到本地资源。相反,SocketAppender的设计目的是通过网络传输序列化的ILoggingEvent实例来记录日志到远程实体。当使用SocketAppender时,线路上的日志事件将以明文形式发送。然而,当使用SSLSocketAppender时,日志事件是通过安全通道传递的。

序列化事件的实际类型是LoggingEventVO,它实现了ILoggingEvent接口。然而,就日志事件而言,远程日志记录是非侵入性的。在反序列化后的接收端,可以像在本地生成一样记录事件。运行在不同机器上的多个SocketAppender实例可以将它们的日志输出定向到格式固定的中央日志服务器。SocketAppender不接受关联的layout,因为它将序列化的事件发送到远程服务器。SocketAppender运行在传输控制协议(TCP)层之上,TCP层提供了一个可靠的、有序的、流控制的端到端八位字节流。因此,如果远程服务器是可访问的,那么日志事件最终将到达那里。如果远程服务器关闭或无法访问,日志事件将被删除。当服务器恢复时,事件传输将透明地恢复。这种透明的重连接由一个连接器线程执行,该线程定期尝试连接到服务器。

日志事件由本机TCP实现自动缓冲。这意味着,如果到服务器的链接很慢,但是仍然比客户机生成事件的速度快,客户机将不会受到慢速网络连接的影响。但是,如果网络连接比事件生成的速度慢,那么客户机只能以网络速度前进。特别是在连接到服务器的网络连接关闭的极端情况下,客户机最终将被阻塞。或者,如果网络链接已打开,但服务器已关闭,则不会阻塞客户机,尽管日志事件将由于服务器不可用而丢失。

即使SocketAppender不再附加到任何日志程序,它也不会在连接器线程存在时被垃圾回收。连接器线程仅在与服务器的连接关闭时才存在。为了避免这种垃圾收集问题,您应该显式地关闭SocketAppender。长生命周期应用程序会创建/销毁许多SocketAppender实例,应该注意这个垃圾收集问题。大多数其他应用程序可以安全地忽略它。如果托管SocketAppenderJVMSocketAppender关闭之前(显式关闭或垃圾收集之后关闭)退出,那么管道中可能会丢失未传输的数据。这是基于Windows系统的常见问题。为了避免丢失数据,通常可以显式地关闭SocketAppender(),或者在退出应用程序之前调用LoggerContextstop()方法。

远程服务器由remoteHostport属性标识。下表列出了SocketAppender属性。SSLSocketAppender支持许多额外的配置属性,这些属性将在“使用SSL”一节中详细介绍。

属性名称 类型 描述
includeCallerData boolean includeCallerData选项接受一个布尔值。如果为true,则调用方数据将对远程主机可用。默认情况下,不会向服务器发送调用方数据。
port int 远程服务器的端口号。
reconnectionDelay Duration reconnectionDelay选项接受一个持续时间字符串,比如“10秒”,表示每次尝试连接到服务器失败之间的等待时间。这个选项的默认值是30秒。将此选项设置为0将关闭重连接功能。注意,在成功连接到服务器的情况下,将不存在连接器线程。
queueSize int queueSize属性接受一个整数(大于零),该整数表示要保留的日志事件数量,以便交付给远程接收器。当队列大小为1时,发送到远程接收器的事件是同步的。当队列大小大于1时,假设队列中有可用空间,就会将新事件加入队列。使用大于1的队列长度可以通过消除由临时网络延迟引起的阻塞从而提高性能。还可参考eventDelayLimit属性。
eventDelayLimit Duration eventDelayLimit选项接受一个持续时间字符串,比如“10秒”。它表示在本地队列已满(即已经包含queueSize事件)时,在删除事件之前等待的时间。如果远程主机持续缓慢地接受事件,可能会发生这种情况。此选项的默认值为100毫秒。
remoteHost String 服务器的主机名。
ssl SSLConfiguration 仅支持SSLSocketAppender,此属性表示appender将使用SSL配置,如“使用SSL”中所述。

日志服务器选项

标准的Logback-Classic为服务器提供了两个选项,用于接收来自SocketAppenderSSLSocketAppender的日志事件。

  • ServerSocketReceiver及其支持SSL-enabled程序的SSLServerSocketReceiver是接收器组件,可以在应用程序的logback.xml配置文件中配置这些组件,以便从远程套接字追加器接收事件。有关配置细节和使用示例,请参见接收器Receivers的介绍。
  • SimpleSocketServer及其支持SSL-enabled程序的SimpleSSLSocketServer都提供了易于使用的独立Java应用程序,该应用程序的设计目的是配置并从shell的命令行接口运行。这些应用程序只是等待来自SocketAppenderSSLSocketAppender客户机的日志事件。每个接收到的事件都根据本地服务器策略进行日志记录。下面给出了使用示例。

使用 SimpleSocketServer

SimpleSocketServer应用程序接受两个命令行参数:portconfigFile;其中port是要监听的端口,configFile是XML格式的配置脚本。

假设您在logback-examples/目录中,使用以下命令启动SimpleSocketServer

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \
  src/main/java/chapters/appenders/socket/server1.xml

这里6000是要监听的端口号,server1.xml是一个配置脚本,它向根日志记录器添加了一个ConsoleAppender和一个RollingFileAppender。启动SimpleSocketServer之后,您可以使用SocketAppender从多个客户机向它发送日志事件。与本手册相关的例子包括两个这样的客户端:chapters.appenders.SocketClient1chapters.appenders.SocketClient2两个客户机都在等待用户在控制台上输入一行文本。文本被封装在一个debug级别的日志事件中,然后发送到远程服务器。这两个客户机在SocketAppender的配置上有所不同。SocketClient1以编程方式配置追加器,而SocketClient2需要配置文件。

假设SimpleSocketServer在本地主机上运行,您可以使用以下命令连接到它:

java chapters.appenders.socket.SocketClient1 localhost 6000

您键入的每一行都应该出现在上一步中启动的SimpleSocketServer的控制台。如果停止并重启SimpleSocketServer,客户机将透明地重新连接到新服务器实例,尽管断开连接时生成的事件将简单地(并且不可挽回地)丢失。

SocketClient1不同,示例应用程序SocketClient2本身并不配置logback。它需要XML格式的配置文件。如下所示的配置文件client1.xml创建了一个SocketAppender并将其附加到根日志记录器。

<configuration>
          
  <appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <includeCallerData>${includeCallerData}</includeCallerData>
  </appender>

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

</configuration>

注意,在上面的配置脚本中,remoteHostportincludeCallerData 属性的值不是直接给出的,而是作为替代变量键给出的。变量的值可以指定为系统属性:

java -Dhost=localhost -Dport=6000 -DincludeCallerData=false \
  chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/client1.xml

该命令的结果应该与前面的SocketClient1示例类似。

请允许我们重复一遍,以强调日志事件的序列化不具有侵入性。反序列化事件与任何其他日志事件携带相同的信息。它可以像在本地生成一样进行操作;除了默认情况下序列化日志事件不包含调用方数据之外。这里有一个例子来说明这一点。首先,使用以下命令启动SimpleSocketServer

 java ch.qos.logback.classic.net.SimpleSocketServer 6000 \
  src/main/java/chapters/appenders/socket/server2.xml

配置文件server2.xml创建一个ConsoleAppender,其布局输出调用者的文件名和行号以及其他信息。如果像以前一样使用配置文件client1.xml运行SocketClient2,你会注意到服务器端的输出将包含两个问号之间的括号,而不是文件名和行号的调用者:

2006-11-06 17:37:30,968 DEBUG [Thread-0] [?:?] chapters.appenders.socket.SocketClient2 - Hi

通过将includeCallerData选项设置为true,指示SocketAppender包含调用方数据,可以很容易地更改结果。使用下面的命令就可以了:

java -Dhost=localhost -Dport=6000 -DincludeCallerData=true \
  chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/client1.xml

由于反序列化事件可以与本地生成的事件以相同的方式处理,甚至可以将它们发送到另一台服务器进行进一步处理。作为练习,您可能希望设置两个服务器,其中第一个服务器将其接收到的事件从客户机传输到第二个服务器。

使用 SimpleSSLSocketServer

SimpleSSLSocketServerSimpleSocketServer一样,也需要portconfigFile命令行参数。此外,必须使用命令行中指定的系统属性为日志服务器的X.509凭证提供位置和密码。

假设您在logback-examples/目录中,使用以下命令启动SimpleSSLSocketServer

java -Djavax.net.ssl.keyStore=src/main/java/chapters/appenders/socket/ssl/keystore.jks \
    -Djavax.net.ssl.keyStorePassword=changeit \
    ch.qos.logback.classic.net.SimpleSSLSocketServer 6000 \
    src/main/java/chapters/appenders/socket/ssl/server.xml

本例使用只适合于测试和实验的X.509凭据运行SimpleSSLSocketServer。在生产设置中使用SimpleSSLSocketServer之前,您应该获得一个适当的X.509凭据来标识您的日志服务器。有关详细信息,请参见"使用SSL"。

因为服务器配置在根元素上指定debug="true",您将在服务器的启动日志中看到将要使用的SSL配置。这对于验证本地安全策略实现是否正确非常有用。

运行SimpleSSLSocketServer后,可以使用SSLSocketAppender连接到服务器。下面的示例显示了所需的appender配置:

<configuration debug="true">
          
  <appender name="SOCKET" class="ch.qos.logback.classic.net.SSLSocketAppender">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <ssl>
      <trustStore>
        <location>${truststore}</location>
        <password>${password}</password>
      </trustStore>
    </ssl>
  </appender>

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

</configuration>

注意,与前面的示例一样,remoteHostport的值是使用替换的变量键指定的。此外,请注意ssl属性及其嵌套的trustStore属性的存在,该属性指定存储的位置和密码。这个配置是必要的,因为我们的示例服务器使用的是自签名证书。有关SSLSocketAppenderSSL配置属性的更多信息,请参见“使用SSL”。

通过在命令行上指定替换变量值作为系统属性,我们可以使用这种配置运行客户机应用程序:

java -Dhost=localhost -Dport=6000 \
    -Dtruststore=file:src/main/java/chapters/appenders/socket/ssl/truststore.jks \
    -Dpassword=changeit \
    chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/ssl/client.xml

与前面的示例一样,您可以在客户机应用程序提示时输入一条消息,消息将被发送到日志服务器(现在通过一个安全通道),并显示在控制台。

注意,命令行上给出的truststore属性指定一个文件URL,该URL标识可信任的存储位置。您还可以使用类路径URL,如“使用SSL”中所述。

正如我们前面在服务器启动时看到的,由于客户机配置在根元素上指定了debug="true",客户机的启动日志记录包括SSL配置的详细信息,以帮助审查本地策略的一致性。

ServerSocketAppender 和 SSLServerSocketAppender

前面讨论的SocketAppender组件(及其支持ssl的对应组件)旨在允许应用程序通过网络连接到远程日志服务器,以便向服务器交付日志事件。

在某些情况下,让应用程序启动到远程日志服务器的连接可能不方便或不可行。对于这些情况,Logback提供ServerSocketAppender

不启动到远程日志服务器的连接,ServerSocketAppender被动地监听TCP套接字,等待来自远程客户机的传入连接。提交到附加器的日志事件分布到每个连接的客户机。当没有客户机连接时发生的日志事件将被立即丢弃。

除了基本的ServerSocketAppender之外,Logback还提供了SSLServerSocketAppender,它使用一个安全加密的通道将日志事件分发给每个连接的客户机。此外,启用sslappender完全支持基于证书的相互认证,可以使用这种认证确保只有经过授权的客户端才能连接到appender来接收日志事件。

为在线路上传输而编码日志事件的方法与SocketAppender使用的方法相同;每个事件都是ILoggingEvent的序列化实例。只有连接启动的方向是相反的。SocketAppender在建立到日志服务器的连接时充当主动对等点,而ServerSocketAppender是被动的;它侦听来自客户机的传入连接。

ServerSocketAppender子类型仅用于Logback接收器组件。有关此组件类型的附加信息,请参见接收器。ServerSocketAppender支持以下配置属性:

属性名称 类型 描述
address String 附加程序将侦听的本地网络接口地址。如果未指定此属性,则追加器将侦听所有网络接口。
includeCallerData boolean 如果为真,则调用方数据将对远程主机可用。默认情况下,不会向客户机发送调用方数据。
port int 附加程序将侦听的端口号。
ssl SSLConfiguration 仅支持SSLServerSocketAppender,此属性提供了将由appender使用的SSL配置,如“使用SSl”中所述。

下面的示例演示了一个使用ServerSocketAppender的配置:

<configuration debug="true">
  <appender name="SERVER" 
    class="ch.qos.logback.classic.net.server.ServerSocketAppender">
    <port>${port}</port>
    <includeCallerData>${includeCallerData}</includeCallerData>
  </appender>

  <root level="debug">
    <appender-ref ref="SERVER" />
  </root>  

</configuration>

注意,此配置与前面的示例不同,仅在为appender指定的类中使用ServerSocketAppender,并且在没有remoteHost属性的情况下——此appender被动地等待来自远程主机的入站连接,而不是打开到远程日志服务器的连接。

下面的示例演示了使用SSLServerSocketAppender的配置。

<configuration debug="true">
  <appender name="SERVER" 
    class="ch.qos.logback.classic.net.server.SSLServerSocketAppender">
    <port>${port}</port>
    <includeCallerData>${includeCallerData}</includeCallerData>
    <ssl>
      <keyStore>
        <location>${keystore}</location>
        <password>${password}</password>
      </keyStore>
    </ssl>
  </appender>

  <root level="debug">
    <appender-ref ref="SERVER" />
  </root>  

</configuration>

此配置与前一个配置之间的主要区别在于,appenderclass属性标识了SSLServerSocketAppender类型,以及嵌套ssl元素的存在,在本例中,嵌套ssl元素指定了包含附加器X.509凭据的密钥存储库的配置。有关SSL配置属性的信息,请参阅“使用SSL”。

因为ServerSocketAppender子类型被设计用于与接收器组件一起使用,所以我们将接收器的章节提供使用示例。

SMTPAppender

SMTPAppender将日志事件累积到一个或多个固定大小的缓冲区中,并在发生用户指定的事件后通过电子邮件发送适当缓冲区的内容。SMTP电子邮件传输(发送)是异步执行的。默认情况下,电子邮件传输由级别错误的日志事件触发。此外,默认情况下,所有事件都使用一个缓冲区。

下表总结了SMTPAppender的各种性能。

属性名称 类型 描述
smtpHost String SMTP服务器的主机名。这个参数是强制性的。
smtpPort int SMTP服务器正在监听的端口。默认为25。
to String 收件人的电子邮件地址。会将触发事件作为每个发出电子邮件的内容。可以通过用逗号分隔目标地址来指定多个收件人。另外,还可以使用多个<to>元素指定多个收件人。
from String SMTPAppender以通常的电子邮件地址格式发送的电子邮件的发起者。如果您希望包含发送者的名称,则使用“Adam Smith <smith@moral.org>”格式,以便消息显示为源自“Adam Smith <smith@moral.org>”
subject String 邮件的主题。它可以是PatternLayout作为有效转换模式接受的任何值。布局将在下一章讨论。发出的电子邮件消息将具有与在触发电子邮件消息的日志事件上应用模式相对应的主题行。假设subject选项设置为“Log: %logger - %msg”,并且触发事件的日志程序名为“com.foo.Bar”,并包含消息“Hello world”,然后发出的电子邮件将有主题行“Log: com.foo.Bar - Hello World”。默认情况下,该选项设置为“%logger{20} - %m”
discriminator Discriminator discriminator的帮助下,SMTPAppender可以根据鉴别器返回的值将传入的事件分散到不同的缓冲区中。默认识别器总是返回相同的值,以便对所有事件使用相同的缓冲区。通过指定非默认识别器,可以接收包含与特定用户、用户会话或客户端IP地址相关的事件的电子邮件消息。
evaluator Ievaluator 该选项通过创建一个新的<EventEvaluator/>元素来声明。需要通过class属性指定用户希望用作SMTPAppender求值器的类的名称。在没有此选项的情况下,SMTPAppender被分配一个OnErrorEvaluator实例,该实例在遇到ERROR级别或更高级别的事件时触发电子邮件传输。Logback附带了其他几个评估器,即OnMarkerEvaluator(下面讨论)和一个名为JaninoEventEvaluator的强大评估器,将在另一章讨论。最新版本的logback附带了一个更强大的评估器GEventEvaluator
cyclicBufferTracker CyclicBufferTracker 顾名思义,CyclicBufferTracker类的一个实例跟踪循环缓冲区。它是基于识别器返回的键来实现的(见上面)。如果您没有指定一个cyclicBufferTracker,那么将自动创建一个CyclicBufferTracker实例。默认情况下,该实例将事件保存在大小为256的循环缓冲区中。您可以在bufferSize选项的帮助下更改大小(参见下面)。
username String 在普通用户/密码身份验证期间使用的用户名值。默认情况下,该参数为null
password String 用于普通用户/密码身份验证的密码值。默认情况下,该参数为null
STARTTLS boolean 如果将该参数设置为true,则此附加器将发出STARTTLS命令(如果服务器支持该命令),导致连接切换到SSL。注意,连接最初是不加密的。默认情况下,该参数设置为false
SSL boolean 如果将此参数设置为true,则此追加器将打开到服务器的SSL连接。默认情况下,该参数设置为false
charsetEncoding String 发出的电子邮件将被编码在指定的字符集中。默认的字符集编码是“UTF-8”,这在大多数情况下都能很好地工作。
localhost String 如果SMTP客户机的主机名没有正确配置,例如,如果客户机主机名没有完全限定,某些SMTP服务器可能会拒绝客户机发送的HELO/EHLO命令。要克服这个问题,可以将localhost属性的值设置为客户机主机的完全限定名。参见在com.sun.mail.smtp包中的“mail.smtp.localhost”属性文档。
asynchronousSending boolean 此属性确定电子邮件传输是否异步完成。默认情况下,异步发送属性为“true”。然而,在某些情况下异步发送可能是不合适的。例如,如果应用程序使用SMTPAppender发送警报以响应致命错误,然后退出,相关线程可能没有时间发送警报电子邮件。在本例中,将用于同步电子邮件传输的异步发送属性设置为“false”
includeCallerData boolean 默认情况下,includeCallerData被设置为false。如果启用了异步发送,并且希望在日志中包含调用方数据,则应该将includeCallerData设置为true
sessionViaJNDI boolean SMTPAppender依赖于javax.mail.Session发送电子邮件消息。默认情况下,sessionViaJNDI被设置为false,因此javax.mail.Session实例由SMTPAppender本身使用用户指定的属性构建。如果将sessionViaJNDI属性设置为true,则javax.mail.Session对象将通过JNDI检索。还请参见jndiLocation属性。通过JNDI检索Session可以减少配置/重新配置相同信息所需的位置数量,从而使应用程序更加dryer。有关在Tomcat中配置资源的更多信息,请参见JNDI资源指南。如该文档中所述,在从JNDI检索Session时,请确保从web应用程序WEB-INF/lib文件夹中删除mail.jaractivation.jar
jndiLocation String javax.mail.Session位于JNDI中的位置。默认情况下,jndiLocation被设置为“java:comp/env/mail/Session”

未完待续。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • 作为Java开发人员,对于日志记录框架一定非常熟悉。而且几乎在所有应用里面,一定会用到各种各样的日志框架用来记录程...
    意识流丶阅读 13,865评论 0 13
  • 简单日志配置 logback的介绍及配置 logback的使用 logback.xml配置示例 一.简单日志配置 ...
    CoderZS阅读 1,957评论 0 16
  • from:https://www.cnblogs.com/ITtangtang/p/3926665.html一、L...
    enshunyan阅读 3,256评论 0 0
  • 在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析...
    时待吾阅读 4,944评论 0 6
  • 曼谷大皇宫——金碧辉煌的宫殿庙宇,鸟语花香的皇家庭院,叹为观止的壁画,以及涌动的人群和灼热的阳光。 四面佛——听说...
    熠一插画阅读 268评论 0 0