以下内容翻译整理自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
接口中的大多数方法都是setter
和getter
。只有doAppend()
方法是例外的,它将一个类型为E
的对象作为参数。E
的实际类型将根据logback
模块的不同而有所不同。在logback-classic
模块中,E
的类型是ILoggingEvent
,在logback-access
模块中,E
的类型是AccessEvent
。doAppend()
方法是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()
方法,从而确保T
对appender
的独占访问。
由于这种同步并不总是合适的,所以logback
又提供了一个ch.qos.logback.core.UnsynchronizedAppenderBase
,和AppenderBase
类非常类似。为了简洁起见,我们在本文档的其余部分只讨论UnsynchronizedAppenderBase
。
doAppend()
方法做的第一件事是检查守卫是否被设置为true
。如果是,则立即退出。如果不是,则在下一个语句中将其设置为true
。该保护确保doAppend()
方法不会递归地调用自己。假设一个在append()
方法之外调用的组件想要记录一些东西。它的调用可以直接指向刚才调用它的相同的追加器,从而导致无限循环和堆栈溢出。
在接下来的语句中,我们检查started
字段是否为true
。如果不是,doAppend()
将发送一个警告消息并返回。换句话说,一旦一个appender
被关闭了,就不可能再对它进行写入。Appender
接口继承了LifeCycle
接口,这意味着它的实现类也实现了start()
、stop()
和isStarted()
方法。设置完appender
的所有属性后,Joran
是logback
的配置框架,它会调用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
是其他三个追加器的超类,也就是ConsoleAppender
、FileAppender
、RollingFileAppender
的超类。下图展示了OutputStreamAppender
及其子类的类图。
ConsoleAppender
ConsoleAppender
,顾名思义,附加在控制台,或者更准确地说是System.out
或者System.err
。前者是默认目标。ConsoleAppender
在用户指定的编码器的帮助下格式化事件。编码器将在下一章中讨论。这两个System.out
和System.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” 。注意,Linux 和Mac 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
FileAppender
是OutputStreamAppender
的一个子类,追加日志事件到一个文件中,目标文件由File
选项指定。如果文件已经存在,根据append
属性的值,要么被追加,要么被截断。
属性名称 | 类型 | 描述 |
---|---|---|
append | boolean | 如果为true ,事件将追加到现有文件的末尾。如果append 为false ,则截断任何现有文件。append 选项默认为true 。 |
encoder | Encoder | 见OutputStreamAppender 的属性介绍。 |
file | String | 要写入的文件的名称,如果文件不存在,就创建它。在Windows 平台上,文件c:\temp\test.log 应该被写为c:/temp/test.log 或c:\\temp\\test.log 。File 选项没有默认值。如果文件的父目录不存在,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
元素接受两个强制属性key
和datePattern
,以及一个可选的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
必须同时设置RollingPolicy
和TriggeringPolicy
。但是,如果它的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)FileAppender 的file 属性必须保持空白。实际上,大多数操作系统都不允许在打开另一个进程时重命名文件。详情请参见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
同时实现了RollingPolicy
和TriggeringPolicy
接口。TimeBasedRollingPolicy
的配置采用一个强制性的fileNamePattern
属性和几个可选属性。
属性名称 | 类型 | 描述 |
---|---|---|
fileNamePattern | String |
(1)强制的fileNamePattern 属性定义了滚动(存档)日志文件的名称。它的值应该由文件名组成,加上适当放置的%d 转换说明符。%d 转换说明符可以包含java.text.SimpleDateFormat 指定的日期和时间模式。如果省略了日期和时间模式,会指定默认模式yyyy-MM-dd 。滚转周期由fileNamePattern 的值推断得出。(2)注意,可以设置或省略RollingFileAppender (TimeBasedRollingPolicy 的父类)中的file 属性。通过设置包含FileAppender 的file 属性,您可以解耦活动日志文件的位置和归档日志文件的位置。当前日志总是针对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-MM
和yyyy@MM
都指定了每月的滚动,尽管生成的归档文件将使用不同的名称。
通过设置file
属性,您可以解耦活动日志文件的位置和存档日志文件的位置。日志输出将定向到file
属性指定的文件中。因此,活动日志文件的名称不会随时间而更改。但是,如果您选择忽略file
属性,然后根据fileNamePattern
的值为每个周期重新计算活动文件。通过不设置file
选项,您可以避免文件重命名错误,这些错误发生在存在外部文件句柄在滚转期间引用日志文件时。
由于各种技术原因,滚动不是时钟驱动的,而是取决于日志事件的到来。例如,在2002年3月8日,假设fileNamePattern
设置为yyyy-MM-dd
(每日翻转),午夜后第一个事件的到来将触发翻转。如果在午夜之后的23分47秒内没有日志记录事件,那么翻转实际上将发生在3月9日凌晨00:23'47,而不是凌晨0:00。因此,根据事件的到达率,可能会触发一些延迟的滚动。但是,不管延迟如何,翻转算法是正确的,因为在某个时间段内生成的所有日志事件都将输出到分隔该时间段的正确文件中。
下面是RollingFileAppender
与TimeBasedRollingPolicy
的示例配置。
<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 ,该字符串表示将插入当前窗口索引值的位置。例如,使用与最小值和最大值为1 和3 关联的MyLogFile%i.log 将生成名为MyLogFile1.log 、MyLogFile2.log 和MyLogFile3.log 的归档文件。注意,文件压缩也是通过这个属性指定的。例如,fileNamePattern 设置为MyLogFile%i.log.zip ,这意味着存档文件必须使用zip 格式进行压缩;还支持gz 格式。 |
由于固定窗口滚动策略需要的文件重命名操作与窗口大小一样多,因此强烈建议不要使用较大的窗口大小。当用户指定较大的值时,当前实现将自动将窗口大小减小到20。
让我们来看一个关于固定窗口翻转策略的更具体的例子。假设minIndex
设置为1
,maxIndex
设置为3
,fileNamePattern
属性设置为foo%i.log
。file
属性被设置为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.log 。foo.log 被重命名为foo1.log 。创建一个新的foo.log 文件并成为活动输出目标。 |
3 | foo.log | foo1.log, foo2.log, foo3.log | 第三个翻转。将foo2.log 重命名为foo3.log 。将foo1.log 重命名为foo2.log 。foo.log 被重命名为foo1.log 。创建一个新的foo.log 文件并成为活动输出目标。 |
4 | foo.log | foo1.log, foo2.log, foo3.log | 在这轮和随后的几轮中,滚动从删除log.foo3.log 开始。其他文件通过增加索引重命名,如前面的步骤所示。在接下来的滚动中,将一直有三个归档日志和一个活动日志文件。 |
下面的配置文件给出了一个配置RollingFileAppender
和FixedWindowRollingPolicy
的示例。注意,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
选项可以用字节、千字节、兆字节或千兆字节来指定,方法是分别用KB
、MB
和GB
作为数字值的后缀。例如,5000000
、5000KB
、5MB
和2GB
都是有效值,前三个值是等价的。
下面是一个带有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
实例,应该注意这个垃圾收集问题。大多数其他应用程序可以安全地忽略它。如果托管SocketAppender
的JVM
在SocketAppender
关闭之前(显式关闭或垃圾收集之后关闭)退出,那么管道中可能会丢失未传输的数据。这是基于Windows
系统的常见问题。为了避免丢失数据,通常可以显式地关闭SocketAppender()
,或者在退出应用程序之前调用LoggerContext
的stop()
方法。
远程服务器由remoteHost
和port
属性标识。下表列出了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
为服务器提供了两个选项,用于接收来自SocketAppender
或SSLSocketAppender
的日志事件。
-
ServerSocketReceiver
及其支持SSL-enabled
程序的SSLServerSocketReceiver
是接收器组件,可以在应用程序的logback.xml
配置文件中配置这些组件,以便从远程套接字追加器接收事件。有关配置细节和使用示例,请参见接收器Receivers
的介绍。 -
SimpleSocketServer
及其支持SSL-enabled
程序的SimpleSSLSocketServer
都提供了易于使用的独立Java
应用程序,该应用程序的设计目的是配置并从shell
的命令行接口运行。这些应用程序只是等待来自SocketAppender
或SSLSocketAppender
客户机的日志事件。每个接收到的事件都根据本地服务器策略进行日志记录。下面给出了使用示例。
使用 SimpleSocketServer
SimpleSocketServer
应用程序接受两个命令行参数:port
和configFile
;其中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.SocketClient1
和chapters.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>
注意,在上面的配置脚本中,remoteHost
、port
和includeCallerData
属性的值不是直接给出的,而是作为替代变量键给出的。变量的值可以指定为系统属性:
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
SimpleSSLSocketServer
和SimpleSocketServer
一样,也需要port
和configFile
命令行参数。此外,必须使用命令行中指定的系统属性为日志服务器的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>
注意,与前面的示例一样,remoteHost
、port
的值是使用替换的变量键指定的。此外,请注意ssl
属性及其嵌套的trustStore
属性的存在,该属性指定存储的位置和密码。这个配置是必要的,因为我们的示例服务器使用的是自签名证书。有关SSLSocketAppender
的SSL
配置属性的更多信息,请参见“使用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
,它使用一个安全加密的通道将日志事件分发给每个连接的客户机。此外,启用ssl
的appender
完全支持基于证书的相互认证,可以使用这种认证确保只有经过授权的客户端才能连接到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>
此配置与前一个配置之间的主要区别在于,appender
的class
属性标识了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 |
SMTPAppende r依赖于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.jar 和activation.jar 。 |
jndiLocation | String |
javax.mail.Session 位于JNDI中的位置。默认情况下,jndiLocation 被设置为“java:comp/env/mail/Session” 。 |
未完待续。。。
网友评论