附加器
附加器负责将 LogEvents 传递到其目标位置。每个附加器都必须实现 Appender 接口。大多数附加器将扩展 AbstractAppender,它添加了 Lifecycle 和 Filterable 支持。Lifecycle 允许组件在配置完成后完成初始化,并在关闭期间执行清理。Filterable 允许组件附加过滤器,这些过滤器在事件处理期间进行评估。
附加器通常只负责将事件数据写入目标位置。在大多数情况下,它们将格式化事件的责任委托给 布局。一些附加器包装其他附加器,以便它们可以修改 LogEvent、处理附加器中的故障、根据高级过滤器条件将事件路由到下级附加器,或提供类似的功能,这些功能不会直接格式化事件以供查看。
附加器始终具有名称,以便可以从记录器中引用它们。
在下表中,“类型”列对应于预期的 Java 类型。对于非 JDK 类,这些类通常应该在 Log4j Core 中,除非另有说明。
AsyncAppender
AsyncAppender 接受对其他附加器的引用,并导致 LogEvents 在单独的线程上写入这些附加器。请注意,写入这些附加器时发生的异常将隐藏在应用程序中。AsyncAppender 应该在它引用的附加器之后配置,以允许它正确关闭。
默认情况下,AsyncAppender 使用 java.util.concurrent.ArrayBlockingQueue,它不需要任何外部库。请注意,多线程应用程序在使用此附加器时应谨慎,例如:阻塞队列容易受到锁争用的影响,我们的 测试表明 当更多线程同时记录时,性能可能会变差。考虑使用 无锁异步记录器 以获得最佳性能。
参数名称 | 类型 | 描述 |
---|---|---|
AppenderRef | 字符串 | 要异步调用的附加器的名称。可以配置多个 AppenderRef 元素。 |
blocking | 布尔值 | 如果为 true,附加器将等待直到队列中有空闲插槽。如果为 false,如果队列已满,则事件将写入错误附加器。默认值为 true。 |
shutdownTimeout | 整数 | 附加器在关闭时应等待多少毫秒以刷新队列中未完成的日志事件。默认值为零,这意味着永远等待。 |
bufferSize | 整数 | 指定可以排队的事件的最大数量。默认值为 1024。请注意,当使用 disruptor 样式的 BlockingQueue 时,此缓冲区大小必须是 2 的幂。当应用程序的日志记录速度快于底层附加器能够跟上的速度,并且持续时间足够长以填满队列时,行为由 AsyncQueueFullPolicy 决定。 |
errorRef | 字符串 | 附加器的名称,如果所有附加器都无法调用,则调用该附加器,无论是由于附加器中的错误还是因为队列已满。如果未指定,则错误将被忽略。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
name | 字符串 | 附加器的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
includeLocation | 布尔值 | 提取位置是一个昂贵的操作(它可以使日志记录速度降低 5-20 倍)。为了提高性能,默认情况下,在将日志事件添加到队列时不会包含位置。可以通过设置 includeLocation="true" 来更改此设置。 |
BlockingQueueFactory | BlockingQueueFactory | 此元素覆盖要使用的 BlockingQueue 或 TransferQueue 的类型。有关更多详细信息,请参阅 下面的文档。 |
还有一些系统属性可用于即使底层附加器无法跟上日志记录速度并且队列正在填满时也能保持应用程序吞吐量。有关系统属性 log4j2.AsyncQueueFullPolicy
和 log4j2.DiscardThreshold
的详细信息,请参阅详细信息。
典型的 AsyncAppender 配置可能如下所示
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <File name="MyFile" fileName="logs/app.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> <Async name="Async"> <AppenderRef ref="MyFile"/> </Async> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Async"/> </Root> </Loggers> </Configuration>
从 Log4j 2.7 开始,可以使用 BlockingQueueFactory 插件指定 BlockingQueue
或 TransferQueue
的自定义实现。要覆盖默认的 BlockingQueueFactory
,请在 <Async/>
元素中指定插件,如下所示
<Configuration name="LinkedTransferQueueExample"> <Appenders> <List name="List"/> <Async name="Async" bufferSize="262144"> <AppenderRef ref="List"/> <LinkedTransferQueue/> </Async> </Appenders> <Loggers> <Root> <AppenderRef ref="Async"/> </Root> </Loggers> </Configuration>
Log4j 附带以下实现
插件名称 | 描述 |
---|---|
ArrayBlockingQueue | 这是使用 ArrayBlockingQueue 的默认实现。 |
DisruptorBlockingQueue | 此插件使用 Conversant Disruptor 实现的 BlockingQueue 。此插件接受一个可选属性 spinPolicy ,它对应于 |
JCToolsBlockingQueue | 此插件使用 JCTools,特别是 MPSC 有界无锁队列。 |
LinkedTransferQueue | 此插件使用 Java 7 中的新实现 LinkedTransferQueue。请注意,此队列不使用 AsyncAppender 中的 bufferSize 配置属性,因为 LinkedTransferQueue 不支持最大容量。 |
CassandraAppender
CassandraAppender 将其输出写入 Apache Cassandra 数据库。必须提前配置键空间和表,并且该表的列在配置文件中映射。每个列可以指定 StringLayout(例如,PatternLayout)以及可选的转换类型,或者仅为 org.apache.logging.log4j.spi.ThreadContextMap
或 org.apache.logging.log4j.spi.ThreadContextStack
指定转换类型,以分别将 MDC 或 NDC 存储在映射或列表列中。与 java.util.Date
兼容的转换类型将使用转换为该类型的日志事件时间戳(例如,使用 java.util.Date
填充 Cassandra 中的 timestamp
列类型)。
参数名称 | 类型 | 描述 |
---|---|---|
batched | 布尔值 | 是否使用批处理语句将日志消息写入 Cassandra。默认情况下,此值为 false 。 |
batchType | BatchStatement.Type | 使用批处理写入时要使用的批处理类型。默认情况下,此值为 LOGGED 。 |
bufferSize | int | 在写入之前要缓冲或批处理的日志消息数量。默认情况下,不会进行缓冲。 |
clusterName | 字符串 | 要连接的 Cassandra 集群的名称。 |
columns | ColumnMapping[] | 列映射配置列表。每个列必须指定一个列名。每个列都可以通过其完全限定类名指定转换类型。默认情况下,转换类型为 String 。如果配置的类型与 ReadOnlyStringMap / ThreadContextMap 或 ThreadContextStack 兼容,则该列将分别填充 MDC 或 NDC。如果配置的类型与 java.util.Date 兼容,则日志时间戳将转换为该配置的日期类型。如果给出了 literal 属性,则其值将按原样用于 INSERT 查询,不会进行任何转义。否则,将指定的布局或模式转换为配置的类型并存储在该列中。 |
contactPoints | SocketAddress[] | 要连接的 Cassandra 节点的主机和端口列表。这些必须是有效的主机名或 IP 地址。默认情况下,如果未为主机指定端口或将其设置为 0,则将使用默认的 Cassandra 端口 9042。默认情况下,将使用 localhost:9042 。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
keyspace | 字符串 | 包含将写入日志消息的表的键空间的名称。 |
name | 字符串 | 附加器的名称。 |
password | 字符串 | 用于连接到 Cassandra 的密码(以及用户名)。 |
table | 字符串 | 要写入日志消息的表的名称。 |
useClockForTimestampGenerator | 布尔值 | 是否使用配置的 org.apache.logging.log4j.core.util.Clock 作为 TimestampGenerator。默认情况下,此值为 false 。 |
username | 字符串 | 用于连接到 Cassandra 的用户名。默认情况下,不使用用户名或密码。 |
useTls | 布尔值 | 是否使用 TLS/SSL 连接到 Cassandra。默认情况下,此值为 false 。 |
以下是一个 CassandraAppender 配置示例
<Configuration name="CassandraAppenderTest"> <Appenders> <Cassandra name="Cassandra" clusterName="Test Cluster" keyspace="test" table="logs" bufferSize="10" batched="true"> <SocketAddress host="localhost" port="9042"/> <ColumnMapping name="id" pattern="%uuid{TIME}" type="java.util.UUID"/> <ColumnMapping name="timeid" literal="now()"/> <ColumnMapping name="message" pattern="%message"/> <ColumnMapping name="level" pattern="%level"/> <ColumnMapping name="marker" pattern="%marker"/> <ColumnMapping name="logger" pattern="%logger"/> <ColumnMapping name="timestamp" type="java.util.Date"/> <ColumnMapping name="mdc" type="org.apache.logging.log4j.spi.ThreadContextMap"/> <ColumnMapping name="ndc" type="org.apache.logging.log4j.spi.ThreadContextStack"/> </Cassandra> </Appenders> <Loggers> <Logger name="org.apache.logging.log4j.cassandra" level="DEBUG"> <AppenderRef ref="Cassandra"/> </Logger> <Root level="ERROR"/> </Loggers> </Configuration>
此配置示例使用以下表模式
CREATE TABLE logs ( id timeuuid PRIMARY KEY, timeid timeuuid, message text, level text, marker text, logger text, timestamp timestamp, mdc map<text,text>, ndc list<text> );
ConsoleAppender
正如预期的那样,ConsoleAppender 将其输出写入 System.out 或 System.err,其中 System.out 是默认目标。必须提供布局来格式化 LogEvent。
参数名称 | 类型 | 描述 |
---|---|---|
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
follow | 布尔值 | 标识 Appender 是否在配置后通过 System.setOut 或 System.setErr 尊重 System.out 或 System.err 的重新分配。请注意,follow 属性不能与 Windows 上的 Jansi 一起使用。不能与 direct 一起使用。 |
direct | 布尔值 | 直接写入 java.io.FileDescriptor 并绕过 java.lang.System.out/.err 。当输出重定向到文件或其他进程时,可以提高高达 10 倍的性能。不能与 Windows 上的 Jansi 一起使用。不能与 follow 一起使用。输出将不尊重 java.lang.System.setOut()/.setErr() ,并且可能会在多线程应用程序中与其他输出到 java.lang.System.out/.err 交织在一起。从 2.6.2 开始新增。请注意,这是一个新添加的功能,目前仅在 Linux 和 Windows 上的 Oracle JVM 上进行了测试。 |
name | 字符串 | 附加器的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
target | 字符串 | "SYSTEM_OUT" 或 "SYSTEM_ERR"。默认值为 "SYSTEM_OUT"。 |
典型的 Console 配置可能如下所示
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
FailoverAppender
FailoverAppender 包装了一组 Appender。如果主 Appender 失败,则将按顺序尝试辅助 Appender,直到其中一个成功或没有更多辅助 Appender 可供尝试。
参数名称 | 类型 | 描述 |
---|---|---|
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
primary | 字符串 | 要使用的主 Appender 的名称。 |
failovers | String[] | 要使用的辅助 Appender 的名称。 |
name | 字符串 | 附加器的名称。 |
retryIntervalSeconds | 整数 | 在重试主 Appender 之前应经过的秒数。默认值为 60。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将传播到调用者,而不是。 |
target | 字符串 | "SYSTEM_OUT" 或 "SYSTEM_ERR"。默认值为 "SYSTEM_ERR"。 |
Failover 配置可能如下所示
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{MM-dd-yyyy}.log.gz" ignoreExceptions="false"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <TimeBasedTriggeringPolicy /> </RollingFile> <Console name="STDOUT" target="SYSTEM_OUT" ignoreExceptions="false"> <PatternLayout pattern="%m%n"/> </Console> <Failover name="Failover" primary="RollingFile"> <Failovers> <AppenderRef ref="Console"/> </Failovers> </Failover> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Failover"/> </Root> </Loggers> </Configuration>
FileAppender
FileAppender 是一个 OutputStreamAppender,它将写入 fileName 参数中命名的文件。FileAppender 使用 FileManager(扩展 OutputStreamManager)来实际执行文件 I/O。虽然来自不同配置的 FileAppender 不能共享,但如果 Manager 可访问,则 FileManager 可以共享。例如,servlet 容器中的两个 Web 应用程序可以拥有自己的配置并安全地写入同一个文件,如果 Log4j 位于对它们都通用的 ClassLoader 中。
参数名称 | 类型 | 描述 |
---|---|---|
append | 布尔值 | 当为 true 时 - 默认情况下,记录将追加到文件的末尾。当设置为 false 时,文件将在写入新记录之前被清除。 |
bufferedIO | 布尔值 | 当为 true 时 - 默认情况下,记录将写入缓冲区,数据将在缓冲区满时或(如果 immediateFlush 设置为 true)在写入记录时写入磁盘。文件锁定不能与 bufferedIO 一起使用。性能测试表明,使用缓冲 I/O 可以显着提高性能,即使启用了 immediateFlush。 |
bufferSize | int | 当 bufferedIO 为 true 时,这是缓冲区大小,默认值为 8192 字节。 |
createOnDemand | 布尔值 | Appender 按需创建文件。Appender 仅在日志事件通过所有过滤器并路由到此 Appender 时才创建文件。默认为 false。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
fileName | 字符串 | 要写入的文件的名称。如果文件或其任何父目录不存在,则将创建它们。 |
immediateFlush | 布尔值 |
当设置为 true 时 - 默认情况下,每次写入后都会进行刷新。这将保证数据被传递到操作系统以进行写入;它不保证数据实际写入物理设备,例如磁盘驱动器。 请注意,如果此标志设置为 false,并且日志活动稀疏,则数据最终传递到操作系统的延迟可能是无限的,因为它被阻塞在缓冲区中。这会导致令人惊讶的效果,例如日志不会在写入日志后立即出现在文件的尾部输出中。 每次写入后刷新仅在将此 Appender 与同步记录器一起使用时才有用。异步记录器和 Appender 将在事件批处理结束时自动刷新,即使 immediateFlush 设置为 false。这也保证数据被传递到操作系统,但效率更高。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
locking | 布尔值 | 当设置为 true 时,I/O 操作仅在持有文件锁时发生,允许来自多个 JVM 和可能多个主机的 FileAppender 同时写入同一个文件。这将显着影响性能,因此应谨慎使用。此外,在许多系统上,文件锁是“建议性”的,这意味着其他应用程序可以在不获取锁的情况下对文件执行操作。默认值为 false。 |
name | 字符串 | 附加器的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
filePermissions | 字符串 |
每次创建文件时要应用的 POSIX 格式的文件属性权限。 底层文件系统应支持 POSIX 文件属性视图。 示例:rw------- 或 rw-rw-rw- 等... |
fileOwner | 字符串 |
每次创建文件时要定义的文件所有者。 出于安全原因,更改文件的拥有者可能会受到限制,并且会抛出 Operation not permitted IOException。如果 _POSIX_CHOWN_RESTRICTED 对路径有效,则只有有效用户 ID 等于文件用户 ID 或具有适当权限的进程才能更改文件的拥有权。 底层文件系统应支持文件 所有者 属性视图。 |
fileGroup | 字符串 |
每次创建文件时要定义的文件组。 底层文件系统应支持 POSIX 文件属性视图。 |
以下是一个文件配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <File name="MyFile" fileName="logs/app.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="MyFile"/> </Root> </Loggers> </Configuration>
FlumeAppender
这是一个在单独的 jar 中提供的可选组件。
Apache Flume 是一个分布式、可靠且可用的系统,用于高效地从许多不同的来源收集、聚合和移动大量日志数据到集中式数据存储。FlumeAppender 接收 LogEvents 并将其作为序列化后的 Avro 事件发送到 Flume 代理,供其使用。
Flume Appender 支持三种操作模式。
- 它可以充当远程 Flume 客户端,通过 Avro 将 Flume 事件发送到配置了 Avro Source 的 Flume 代理。
- 它可以充当嵌入式 Flume 代理,其中 Flume 事件直接传递到 Flume 进行处理。
- 它可以将事件持久化到本地 BerkeleyDB 数据存储,然后异步将事件发送到 Flume,类似于嵌入式 Flume 代理,但没有大多数 Flume 依赖项。
作为嵌入式代理使用会导致消息直接传递到 Flume Channel,然后立即将控制权返回给应用程序。与远程代理的所有交互将异步发生。将“type”属性设置为“Embedded”将强制使用嵌入式代理。此外,在 appender 配置中配置代理属性也会导致使用嵌入式代理。
参数名称 | 类型 | 描述 |
---|---|---|
agents | Agent[] | 要将日志事件发送到的代理数组。如果指定了多个代理,则第一个代理将是主代理,后续代理将按指定顺序用作备用代理,如果主代理出现故障。 |
agentRetries | 整数 | 在失败到备用代理之前应重试代理的次数。当指定 type="persistent" 时,此参数将被忽略(在失败到下一个代理之前,代理只尝试一次)。 |
batchSize | 整数 | 指定应作为批次发送的事件数。默认值为 1。此参数仅适用于 Flume Appender。 |
compress | 布尔值 | 当设置为 true 时,消息主体将使用 gzip 压缩。 |
connectTimeoutMillis | 整数 | Flume 在连接超时之前等待的毫秒数。 |
dataDir | 字符串 | Flume 预写日志应写入的目录。仅在 embedded 设置为 true 且使用 Agent 元素而不是 Property 元素时有效。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
eventPrefix | 字符串 | 要添加到每个事件属性之前的字符字符串,以便将其与 MDC 属性区分开来。默认值为空字符串。 |
flumeEventFactory | FlumeEventFactory | 从 Log4j 事件生成 Flume 事件的工厂。默认工厂是 FlumeAvroAppender 本身。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果没有指定布局,将使用 RFC5424Layout。 |
lockTimeoutRetries | 整数 | 写入 Berkeley DB 时,如果发生 LockConflictException,重试的次数。默认值为 5。 |
maxDelayMillis | 整数 | 在发布批次之前,等待 batchSize 事件的最大毫秒数。 |
mdcExcludes | 字符串 | 应从 FlumeEvent 中排除的 mdc 密钥的逗号分隔列表。这与 mdcIncludes 属性互斥。 |
mdcIncludes | 字符串 | 应包含在 FlumeEvent 中的 mdc 密钥的逗号分隔列表。MDC 中未找到的任何密钥都将被排除。此选项与 mdcExcludes 属性互斥。 |
mdcRequired | 字符串 | MDC 中必须存在的 mdc 密钥的逗号分隔列表。如果密钥不存在,将抛出 LoggingException。 |
mdcPrefix | 字符串 | 应添加到每个 MDC 密钥之前的字符串,以便将其与事件属性区分开来。默认字符串为“mdc:”。 |
name | 字符串 | 附加器的名称。 |
properties | Property[] |
用于配置 Flume 代理的一个或多个 Property 元素。必须在没有代理名称的情况下配置属性(使用 appender 名称),并且不能配置任何源。可以使用“sources.log4j-source.interceptors”为源指定拦截器。允许所有其他 Flume 配置属性。指定 Agent 和 Property 元素会导致错误。 在持久模式下配置时,有效的属性是
|
requestTimeoutMillis | 整数 | Flume 在请求超时之前等待的毫秒数。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
type | 枚举 | “Avro”、“Embedded”或“Persistent”之一,用于指示所需的 Appender 变体。 |
一个示例 FlumeAppender 配置,该配置使用主代理和备用代理,压缩主体,并使用 RFC5424Layout 格式化主体
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Flume name="eventLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="eventLogger"/> </Root> </Loggers> </Configuration>
一个示例 FlumeAppender 配置,该配置使用主代理和备用代理,压缩主体,使用 RFC5424Layout 格式化主体,并将加密的事件持久化到磁盘
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Flume name="eventLogger" compress="true" type="persistent" dataDir="./logData"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> <Property name="keyProvider">MySecretProvider</Property> </Flume> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="eventLogger"/> </Root> </Loggers> </Configuration>
一个示例 FlumeAppender 配置,该配置使用主代理和备用代理,压缩主体,使用 RFC5424Layout 格式化主体,并将事件传递到嵌入式 Flume 代理。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Flume name="eventLogger" compress="true" type="Embedded"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Console name="STDOUT"> <PatternLayout pattern="%d [%p] %c %m%n"/> </Console> </Appenders> <Loggers> <Logger name="EventLogger" level="info"> <AppenderRef ref="eventLogger"/> </Logger> <Root level="warn"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
一个示例 FlumeAppender 配置,该配置使用主代理和备用代理,使用 Flume 配置属性,压缩主体,使用 RFC5424Layout 格式化主体,并将事件传递到嵌入式 Flume 代理。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error" name="MyApp"> <Appenders> <Flume name="eventLogger" compress="true" type="Embedded"> <Property name="channels">file</Property> <Property name="channels.file.type">file</Property> <Property name="channels.file.checkpointDir">target/file-channel/checkpoint</Property> <Property name="channels.file.dataDirs">target/file-channel/data</Property> <Property name="sinks">agent1 agent2</Property> <Property name="sinks.agent1.channel">file</Property> <Property name="sinks.agent1.type">avro</Property> <Property name="sinks.agent1.hostname">192.168.10.101</Property> <Property name="sinks.agent1.port">8800</Property> <Property name="sinks.agent1.batch-size">100</Property> <Property name="sinks.agent2.channel">file</Property> <Property name="sinks.agent2.type">avro</Property> <Property name="sinks.agent2.hostname">192.168.10.102</Property> <Property name="sinks.agent2.port">8800</Property> <Property name="sinks.agent2.batch-size">100</Property> <Property name="sinkgroups">group1</Property> <Property name="sinkgroups.group1.sinks">agent1 agent2</Property> <Property name="sinkgroups.group1.processor.type">failover</Property> <Property name="sinkgroups.group1.processor.priority.agent1">10</Property> <Property name="sinkgroups.group1.processor.priority.agent2">5</Property> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Console name="STDOUT"> <PatternLayout pattern="%d [%p] %c %m%n"/> </Console> </Appenders> <Loggers> <Logger name="EventLogger" level="info"> <AppenderRef ref="eventLogger"/> </Logger> <Root level="warn"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
JDBCAppender
JDBC Appender 使用标准 JDBC 将日志事件写入关系数据库表。它可以配置为使用 JNDI DataSource
或自定义工厂方法获取 JDBC 连接。
使用 DataSource
配置的 JDBC Appender 需要 JNDI 支持,因此从 2.17.1 版本开始,除非将 log4j2.enableJndiJdbc=true
配置为系统属性或环境变量,否则此 appender 将无法正常工作。请参阅 enableJndiJdbc 系统属性。
无论您采用哪种方法,它必须由连接池支持。否则,日志记录性能会大大下降。如果配置的 JDBC 驱动程序支持批处理语句,并且配置的 bufferSize
为正数,则日志事件将被批处理。请注意,从 Log4j 2.8 开始,有两种方法可以配置日志事件到列的映射:原始 ColumnConfig
样式,它只允许字符串和时间戳,以及新的 ColumnMapping
插件,它使用 Log4j 的内置类型转换来允许更多数据类型(这与 Cassandra Appender 中的插件相同)。
为了在开发期间快速入门,使用基于 JNDI 的连接源的替代方法是使用非池化 DriverManager
连接源。此连接源使用 JDBC 连接字符串、用户名和密码。或者,您也可以使用属性。
参数名称 | 类型 | 描述 | |
---|---|---|---|
name | 字符串 | 必需。Appender 的名称。 | |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
|
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 | |
bufferSize | int | 如果是一个大于 0 的整数,则会导致 appender 缓冲日志事件,并在缓冲区达到此大小时刷新。 | |
connectionSource | ConnectionSource | 必需。应从中检索数据库连接的连接源。 | |
tableName | 字符串 | 必需。要将日志事件插入的数据库表的名称。 | |
columnConfigs | ColumnConfig[] | 必需(和/或 columnMappings)。有关应将日志事件数据插入的列以及如何插入该数据的的信息。这用多个 <Column> 元素表示。 |
|
columnMappings | ColumnMapping[] | 必需(和/或 columnConfigs)。列映射配置列表。每列必须指定一个列名。每列都可以通过其完全限定的类名指定一个转换类型。默认情况下,转换类型为 String 。如果配置的类型与 ReadOnlyStringMap / ThreadContextMap 或 ThreadContextStack 兼容,则该列将使用 MDC 或 NDC 分别填充(这取决于数据库如何处理插入 Map 或 List 值)。如果配置的类型与 java.util.Date 兼容,则日志时间戳将转换为该配置的日期类型。如果配置的类型与 java.sql.Clob 或 java.sql.NClob 兼容,则格式化的事件将分别设置为 Clob 或 NClob(类似于传统的 ColumnConfig 插件)。如果给出了 literal 属性,则其值将按原样在 INSERT 查询中使用,不会进行任何转义。否则,指定的布局或模式将转换为配置的类型并存储在该列中。 |
|
immediateFail | 布尔值 | false | 当设置为 true 时,日志事件将不会等待尝试重新连接,如果 JDBC 资源不可用,将立即失败。2.11.2 中的新功能 |
reconnectIntervalMillis | long | 5000 | 如果设置为大于 0 的值,则在发生错误后,JDBCDatabaseManager 将尝试在等待指定的毫秒数后重新连接到数据库。如果重新连接失败,则会抛出异常(如果 ignoreExceptions 设置为 false ,则应用程序可以捕获该异常)。2.11.2 中的新功能。 |
配置 JDBCAppender 时,您必须指定一个 ConnectionSource
实现,Appender 从中获取 JDBC 连接。您必须使用以下嵌套元素中的一个
<DataSource>
: 使用 JNDI。不要与其他客户端共享此连接。<ConnectionFactory>
: 指向类-方法对以提供 JDBC 连接。<DriverManager>
: 一种快速简便的入门方法,没有连接池。<PoolingDriver>
: 使用 Apache Commons DBCP 提供连接池。
参数名称 | 类型 | 描述 |
---|---|---|
jndiName | 字符串 | 必需。javax.sql.DataSource 绑定到的完整、带前缀的 JNDI 名称,例如 java:/comp/env/jdbc/LoggingDatabase 。DataSource 必须由连接池支持;否则,日志记录速度会非常慢。 |
参数名称 | 类型 | 描述 |
---|---|---|
class | Class | 必需。包含用于获取 JDBC 连接的静态工厂方法的类的完全限定名称。 |
method | Method | 必需。用于获取 JDBC 连接的静态工厂方法的名称。此方法必须没有参数,其返回类型必须是 java.sql.Connection 或 DataSource 。如果方法返回 Connection ,则它必须从连接池中获取它们(并在 Log4j 完成使用它们后将它们返回到池中);否则,日志记录速度会非常慢。如果方法返回 DataSource ,则 DataSource 只会检索一次,并且出于相同的原因,它必须由连接池支持。 |
参数名称 | 类型 | 描述 |
---|---|---|
connectionString | 字符串 | 必需。特定于驱动程序的 JDBC 连接字符串。 |
userName | 字符串 | 数据库用户名。您不能同时指定属性和用户名或密码。 |
password | 字符串 | 数据库密码。您不能同时指定属性和用户名或密码。 |
driverClassName | 字符串 | JDBC 驱动程序类名。一些旧的 JDBC 驱动程序只能通过按类名显式加载它们来发现。 |
properties | Property[] | 属性列表。您不能同时指定属性和用户名或密码。 |
参数名称 | 类型 | 描述 |
---|---|---|
DriverManager 参数 | DriverManager 参数 | 此连接源继承了 DriverManager 连接源的所有参数。 |
poolName | 字符串 | 用于池化 JDBC 连接的池名称。默认为 example 。如果您想在其他地方使用池化连接,可以使用 JDBC 连接字符串前缀 jdbc:apache:commons:dbcp: 后跟池名称。例如:jdbc:apache:commons:dbcp:example 。 |
PoolableConnectionFactory | PoolableConnectionFactory 元素 | 定义 PoolableConnectionFactory。 |
在配置 JDBCAppender 时,使用嵌套的 <Column>
元素指定应写入表中的哪些列以及如何写入它们。JDBCAppender 使用此信息来制定一个 PreparedStatement
以插入记录,而不会出现 SQL 注入漏洞。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 必需。 数据库列的名称。 |
pattern | 字符串 | 使用此属性使用 PatternLayout 模式在此列中插入日志事件中的值或值。只需在此属性中指定任何合法模式即可。必须指定此属性、literal 或 isEventTimestamp="true" ,但不能同时指定多个。 |
literal | 字符串 |
使用此属性在此列中插入文字值。该值将直接包含在插入 SQL 中,没有任何引号(这意味着如果您希望它是一个字符串,您的值应该包含单引号,例如: |
parameter | 字符串 |
使用此属性在此列中插入带有参数标记 '?' 的表达式。该值将直接包含在插入 SQL 中,没有任何引号(这意味着如果您希望它是一个字符串,您的值应该包含单引号,例如
您只能指定 |
isEventTimestamp | 布尔值 | 使用此属性在此列中插入事件时间戳,该时间戳应为 SQL 日期时间。该值将作为 java.sql.Types.TIMESTAMP 插入。必须指定此属性(等于 true )、pattern 或 isEventTimestamp ,但不能同时指定多个。 |
isUnicode | 布尔值 | 除非指定 pattern ,否则此属性将被忽略。如果为 true 或省略(默认),则该值将作为 unicode 插入(setNString 或 setNClob )。否则,该值将作为非 unicode 插入(setString 或 setClob )。 |
isClob | 布尔值 | 除非指定 pattern ,否则此属性将被忽略。使用此属性来指示该列存储字符大对象 (CLOB)。如果为 true ,则该值将作为 CLOB 插入(setClob 或 setNClob )。如果为 false 或省略(默认),则该值将作为 VARCHAR 或 NVARCHAR 插入(setString 或 setNString )。 |
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 必需。 数据库列的名称。 |
pattern | 字符串 | 使用此属性使用 PatternLayout 模式在此列中插入日志事件中的值或值。只需在此属性中指定任何合法模式即可。必须指定此属性、literal 或 isEventTimestamp="true" ,但不能同时指定多个。 |
literal | 字符串 | 使用此属性在此列中插入文字值。该值将直接包含在插入 SQL 中,没有任何引号(这意味着如果您希望它是一个字符串,您的值应该包含单引号,例如:literal="'Literal String'" )。这对于不支持标识列的数据库特别有用。例如,如果您使用的是 Oracle,您可以指定 literal="NAME_OF_YOUR_SEQUENCE.NEXTVAL" 以在 ID 列中插入唯一 ID。必须指定此属性、pattern 或 isEventTimestamp="true" ,但不能同时指定多个。 |
layout | Layout | 用于格式化 LogEvent 的布局。 |
type | 字符串 | 转换类型名称,一个完全限定的类名。 |
以下是一些 JDBCAppender 的示例配置,以及使用 Commons Pooling 和 Commons DBCP 来池化数据库连接的示例工厂实现
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <JDBC name="databaseAppender" tableName="dbo.application_log"> <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" /> <Column name="eventDate" isEventTimestamp="true" /> <Column name="level" pattern="%level" /> <Column name="logger" pattern="%logger" /> <Column name="message" pattern="%message" /> <Column name="exception" pattern="%ex{full}" /> </JDBC> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <JDBC name="databaseAppender" tableName="LOGGING.APPLICATION_LOG"> <ConnectionFactory class="net.example.db.ConnectionFactory" method="getDatabaseConnection" /> <Column name="EVENT_ID" literal="LOGGING.APPLICATION_LOG_SEQUENCE.NEXTVAL" /> <Column name="EVENT_DATE" isEventTimestamp="true" /> <Column name="LEVEL" pattern="%level" /> <Column name="LOGGER" pattern="%logger" /> <Column name="MESSAGE" pattern="%message" /> <Column name="THROWABLE" pattern="%ex{full}" /> </JDBC> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
package net.example.db; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnection; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.dbcp.PoolingDataSource; import org.apache.commons.pool.impl.GenericObjectPool; public class ConnectionFactory { private static interface Singleton { final ConnectionFactory INSTANCE = new ConnectionFactory(); } private final DataSource dataSource; private ConnectionFactory() { Properties properties = new Properties(); properties.setProperty("user", "logging"); properties.setProperty("password", "abc123"); // or get properties from some configuration file GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>(); DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory( "jdbc:mysql://example.org:3306/exampleDb", properties ); new PoolableConnectionFactory( connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED ); this.dataSource = new PoolingDataSource(pool); } public static Connection getDatabaseConnection() throws SQLException { return Singleton.INSTANCE.dataSource.getConnection(); } }
此追加器是 MapMessage 意识的。
以下配置使用 MessageLayout
来指示追加器应将 MapMessage
的键与 ColumnMapping
的名称匹配,以便在设置追加器的 SQL INSERT 语句的值时。这使您可以根据 Log4j MapMessage
而不是 LogEvent
中的值在数据库表中插入自定义值的行。
<Configuration status="debug"> <Appenders> <Console name="STDOUT"> <PatternLayout pattern="%C{1.} %m %level MDC%X%n"/> </Console> <Jdbc name="databaseAppender" tableName="dsLogEntry" ignoreExceptions="false"> <DataSource jndiName="java:/comp/env/jdbc/TestDataSourceAppender" /> <ColumnMapping name="Id" /> <ColumnMapping name="ColumnA" /> <ColumnMapping name="ColumnB" /> <MessageLayout /> </Jdbc> </Appenders> <Loggers> <Logger name="org.apache.logging.log4j.core.appender.db" level="debug" additivity="false"> <AppenderRef ref="databaseAppender" /> </Logger> <Root level="fatal"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
JMS 追加器
JMS 追加器将格式化的日志事件发送到 JMS 目标。
JMS 追加器需要 JNDI 支持,因此从 2.17.0 版本开始,除非将 log4j2.enableJndiJms=true
配置为系统属性或环境变量,否则此追加器将无法正常工作。请参阅 enableJndiJms 系统属性。
请注意,在 Log4j 2.0 中,此追加器被拆分为 JMSQueueAppender 和 JMSTopicAppender。从 Log4j 2.1 开始,这些追加器被合并到 JMS 追加器中,该追加器不区分队列和主题。但是,为 2.0 编写的使用 <JMSQueue/>
或 <JMSTopic/>
元素的配置将继续与新的 <JMS/>
配置元素一起使用。
参数名称 | 类型 | 默认 | 描述 |
---|---|---|---|
factoryBindingName | 字符串 | 必需 | 在上下文中查找以提供 ConnectionFactory 的名称。这也可以是 ConnectionFactory 的任何子接口。 |
factoryName | 字符串 | 必需 | 应用于定义初始上下文工厂的完全限定类名,如 INITIAL_CONTEXT_FACTORY 中所定义。如果在没有 providerURL 的情况下指定了 factoryName,则会记录警告消息,因为这可能会导致问题。 |
filter | 过滤器 | null | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
layout | Layout | 必需 | 用于格式化 LogEvent 的布局。从 2.9 版本开始,在以前的版本中,SerializedLayout 是默认值。 |
name | 字符串 | 必需 | 附加器的名称。 |
password | 字符串 | null | 用于创建 JMS 连接的密码。 |
providerURL | 字符串 | 必需 | 要使用的提供程序的 URL,如 PROVIDER_URL 中所定义。从 Log4j 2.17 开始,仅支持 java: 协议。 |
destinationBindingName | 字符串 | 必需 | 用于查找 Destination 的名称。这可以是 Queue 或 Topic ,因此,属性名称 queueBindingName 和 topicBindingName 是别名,以保持与 Log4j 2.0 JMS 追加器的兼容性。 |
securityPrincipalName | 字符串 | null | 主体身份的名称,如 SECURITY_PRINCIPAL 中所指定。如果在没有 securityCredentials 的情况下指定了 securityPrincipalName,则会记录警告消息,因为这可能会导致问题。 |
securityCredentials | 字符串 | null | 主体的安全凭据,如 SECURITY_CREDENTIALS 中所指定。 |
ignoreExceptions | 布尔值 | true | 当为 true 时,在追加事件时捕获的异常将在内部记录,然后忽略。当为 false 时,异常将传播到调用者。在将此追加器包装在 FailoverAppender 中时,您必须将其设置为 false 。 |
immediateFail | 布尔值 | false | 当设置为 true 时,日志事件不会等待尝试重新连接,如果 JMS 资源不可用,则会立即失败。从 2.9 版本开始新增。 |
reconnectIntervalMillis | long | 5000 | 如果设置为大于 0 的值,则在发生错误后,JMSManager 将尝试在等待指定毫秒数后重新连接到代理。如果重新连接失败,则会抛出异常(如果 ignoreExceptions 设置为 false ,则应用程序可以捕获该异常)。从 2.9 版本开始新增。 |
urlPkgPrefixes | 字符串 | null | 用于创建 URL 上下文工厂的工厂类的类名的冒号分隔的包前缀列表,如 URL_PKG_PREFIXES 中所定义。 |
userName | 字符串 | null | 用于创建 JMS 连接的用户 ID。 |
以下是一个 JMS 追加器配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <JMS name="jmsQueue" destinationBindingName="MyQueue" factoryBindingName="MyQueueConnectionFactory"> <JsonLayout properties="true"/> </JMS> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="jmsQueue"/> </Root> </Loggers> </Configuration>
要将您的 Log4j MapMessage
映射到 JMS javax.jms.MapMessage
,请将追加器的布局设置为 MessageLayout
,并使用 <MessageLayout />
(从 2.9 版本开始)。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <JMS name="jmsQueue" destinationBindingName="MyQueue" factoryBindingName="MyQueueConnectionFactory"> <MessageLayout /> </JMS> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="jmsQueue"/> </Root> </Loggers> </Configuration>
JPAAppender
从 Log4j 2.11.0 开始,JPA 支持已从现有模块 log4j-core
移动到新模块 log4j-jpa
。
JPAAppender 使用 Java 持久性 API 2.1 将日志事件写入关系数据库表。它要求 API 和提供程序实现位于类路径中。它还需要一个装饰的实体,该实体配置为持久到所需的表。该实体应该扩展 org.apache.logging.log4j.core.appender.db.jpa.BasicLogEventEntity
(如果您主要想使用默认映射)并至少提供一个 @Id
属性,或者扩展 org.apache.logging.log4j.core.appender.db.jpa.AbstractLogEventWrapperEntity
(如果您想显着自定义映射)。有关更多信息,请参阅这两个类的 Javadoc。您还可以参考这两个类的源代码作为实现实体的示例。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 必需。Appender 的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
bufferSize | int | 如果是一个大于 0 的整数,则会导致 appender 缓冲日志事件,并在缓冲区达到此大小时刷新。 |
entityClassName | 字符串 | 必需。 具有 JPA 注释将其映射到数据库表的具体 LogEventWrapperEntity 实现的完全限定名称。 |
persistenceUnitName | 字符串 | 必需。 应用于持久化日志事件的 JPA 持久性单元的名称。 |
以下是一个 JPAAppender 的示例配置。第一个 XML 示例是 Log4j 配置文件,第二个是 persistence.xml
文件。这里假设使用 EclipseLink,但任何 JPA 2.1 或更高版本的提供程序都可以。您应该始终为日志记录创建单独的持久性单元,原因有两个。首先,<shared-cache-mode>
必须设置为 "NONE",这通常不是正常 JPA 使用中所期望的。此外,出于性能原因,日志记录实体应与其自身的持久性单元隔离,远离所有其他实体,并且您应该使用非 JTA 数据源。请注意,您的持久性单元还必须包含所有 org.apache.logging.log4j.core.appender.db.jpa.converter
转换器类的 <class>
元素。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <JPA name="databaseAppender" persistenceUnitName="loggingPersistenceUnit" entityClassName="com.example.logging.JpaLogEntity" /> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1"> <persistence-unit name="loggingPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.MarkerAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.MessageAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.StackTraceElementAttributeConverter</class> <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ThrowableAttributeConverter</class> <class>com.example.logging.JpaLogEntity</class> <non-jta-data-source>jdbc/LoggingDataSource</non-jta-data-source> <shared-cache-mode>NONE</shared-cache-mode> </persistence-unit> </persistence>
package com.example.logging; ... @Entity @Table(name="application_log", schema="dbo") public class JpaLogEntity extends BasicLogEventEntity { private static final long serialVersionUID = 1L; private long id = 0L; public TestEntity() { super(null); } public TestEntity(LogEvent wrappedEvent) { super(wrappedEvent); } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") public long getId() { return this.id; } public void setId(long id) { this.id = id; } // If you want to override the mapping of any properties mapped in BasicLogEventEntity, // just override the getters and re-specify the annotations. }
package com.example.logging; ... @Entity @Table(name="application_log", schema="dbo") public class JpaLogEntity extends AbstractLogEventWrapperEntity { private static final long serialVersionUID = 1L; private long id = 0L; public TestEntity() { super(null); } public TestEntity(LogEvent wrappedEvent) { super(wrappedEvent); } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "logEventId") public long getId() { return this.id; } public void setId(long id) { this.id = id; } @Override @Enumerated(EnumType.STRING) @Column(name = "level") public Level getLevel() { return this.getWrappedEvent().getLevel(); } @Override @Column(name = "logger") public String getLoggerName() { return this.getWrappedEvent().getLoggerName(); } @Override @Column(name = "message") @Convert(converter = MyMessageConverter.class) public Message getMessage() { return this.getWrappedEvent().getMessage(); } ... }
HttpAppender
HttpAppender 通过 HTTP 发送日志事件。必须提供布局来格式化 LogEvent。
将根据布局设置 Content-Type
标头。可以使用嵌入的 Property 元素指定其他标头。
将等待来自服务器的响应,如果未收到 2xx 响应,则会抛出错误。
使用 HttpURLConnection 实现。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 附加器的名称。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
layout | Layout | 用于格式化 LogEvent 的布局。 |
Ssl | SslConfiguration | 包含 https 的 KeyStore 和 TrustStore 的配置。可选,如果未指定,则使用 Java 运行时默认值。请参阅 SSL |
verifyHostname | 布尔值 | 是否将服务器主机名与证书进行验证。仅适用于 https。可选,默认为 true |
url | string | 要使用的 URL。URL 方案必须为 "http" 或 "https"。 |
method | string | 要使用的 HTTP 方法。可选,默认为 "POST"。 |
connectTimeoutMillis | 整数 | 连接超时时间(以毫秒为单位)。可选,默认为 0(无限超时)。 |
readTimeoutMillis | 整数 | 套接字读取超时时间(以毫秒为单位)。可选,默认为 0(无限超时)。 |
headers | Property[] | 要使用的其他 HTTP 标头。这些值支持 查找。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
以下是一个 HttpAppender 配置片段示例
<?xml version="1.0" encoding="UTF-8"?> ... <Appenders> <Http name="Http" url="https://localhost:9200/test/log4j/"> <Property name="X-Java-Runtime" value="$${java:runtime}" /> <JsonLayout properties="true"/> <SSL> <KeyStore location="log4j2-keystore.jks" passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> <TrustStore location="truststore.jks" passwordFile="${sys:user.home}/truststore.pwd"/> </SSL> </Http> </Appenders>
KafkaAppender
KafkaAppender 将事件记录到 Apache Kafka 主题。每个日志事件都作为 Kafka 记录发送。
参数名称 | 类型 | 描述 |
---|---|---|
topic | 字符串 | 要使用的 Kafka 主题。必需。 |
key | 字符串 | 将与每条消息一起发送到 Kafka 的键。可选值,默认为 null 。可以包含任何 查找)。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
layout | Layout | 用于格式化 LogEvent 的布局。必需,没有默认值。从 2.9 版本开始,在以前的版本中,<PatternLayout pattern="%m"/> 是默认值。 |
name | 字符串 | 追加器的名称。必需。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
syncSend | 布尔值 | 默认值为 true ,导致发送阻塞,直到记录被 Kafka 服务器确认。当设置为 false 时,发送会立即返回,从而实现更低的延迟和更高的吞吐量。从 2.8 版本开始新增。请注意,这是一个新增功能,尚未经过广泛测试。任何发送到 Kafka 的失败都将作为错误报告给 StatusLogger,并且日志事件将被丢弃(ignoreExceptions 参数将无效)。日志事件可能会以乱序到达 Kafka 服务器。 |
properties | Property[] | 您可以在 Kafka 生产者属性 中设置属性。您需要设置 bootstrap.servers 属性,其他属性有合理的默认值。请勿设置 value.serializer 或 key.serializer 属性。 |
以下是一个 KafkaAppender 配置片段示例
<?xml version="1.0" encoding="UTF-8"?> ... <Appenders> <Kafka name="Kafka" topic="log-test"> <PatternLayout pattern="%date %message"/> <Property name="bootstrap.servers">localhost:9092</Property> </Kafka> </Appenders>
默认情况下,此追加器是同步的,并且会阻塞,直到 Kafka 服务器确认记录,此操作的超时时间可以通过 `timeout.ms` 属性设置(默认为 30 秒)。使用 异步追加器 包装,或将 syncSend 设置为 `false` 以异步记录。
此追加器需要 Kafka 客户端库。请注意,您需要使用与所用 Kafka 服务器匹配版本的 Kafka 客户端库。
注意:确保不要让 `org.apache.kafka` 在 DEBUG 级别记录到 Kafka 追加器,因为这会导致递归记录。
<?xml version="1.0" encoding="UTF-8"?> ... <Loggers> <Root level="DEBUG"> <AppenderRef ref="Kafka"/> </Root> <Logger name="org.apache.kafka" level="INFO" /> <!-- avoid recursive logging --> </Loggers>
MemoryMappedFileAppender
自 2.1 版起新增。请注意,这是一个新功能,虽然它已经在多个平台上进行了测试,但其使用记录不如其他文件追加器多。
MemoryMappedFileAppender 将指定文件的一部分映射到内存中,并将日志事件写入此内存,依赖于操作系统的虚拟内存管理器将更改同步到存储设备。使用内存映射文件的主要好处是 I/O 性能。此追加器无需进行系统调用来写入磁盘,只需更改程序的本地内存即可,这要快得多。此外,在大多数操作系统中,映射的内存区域实际上是内核的 页面缓存(文件缓存),这意味着无需在用户空间中创建副本。(待办事项:比较此追加器与 RandomAccessFileAppender 和 FileAppender 的性能测试。)
将文件区域映射到内存中会产生一些开销,尤其是对于非常大的区域(512 MB 或更大)。默认区域大小为 32 MB,这应该在重新映射操作的频率和持续时间之间取得合理的平衡。(待办事项:重新映射不同大小的性能测试。)
与 FileAppender 和 RandomAccessFileAppender 类似,MemoryMappedFileAppender 使用 MemoryMappedFileManager 来执行实际的文件 I/O。虽然来自不同配置的 MemoryMappedFileAppender 不能共享,但如果管理器可访问,则 MemoryMappedFileManagers 可以共享。例如,如果 Log4j 位于两个 Web 应用程序都共有的类加载器中,则 servlet 容器中的两个 Web 应用程序可以拥有自己的配置并安全地写入同一个文件。
参数名称 | 类型 | 描述 |
---|---|---|
append | 布尔值 | 当为 true 时 - 默认情况下,记录将追加到文件的末尾。当设置为 false 时,文件将在写入新记录之前被清除。 |
fileName | 字符串 | 要写入的文件的名称。如果文件或其任何父目录不存在,则将创建它们。 |
filters | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
immediateFlush | 布尔值 |
设置为 true 时,每次写入后都会调用 MappedByteBuffer.force()。这将保证数据写入存储设备。 此参数的默认值为 `false`。这意味着即使 Java 进程崩溃,数据也会写入存储设备,但如果操作系统崩溃,可能会丢失数据。 请注意,在每个日志事件上手动强制同步会失去使用内存映射文件的大部分性能优势。 只有在将此追加器与同步记录器一起使用时,每次写入后刷新才有用。异步记录器和追加器会在事件批处理结束时自动刷新,即使 immediateFlush 设置为 false 也是如此。这也保证了数据写入磁盘,但效率更高。 |
regionLength | int | 映射区域的长度,默认为 32 MB(32 * 1024 * 1024 字节)。此参数必须介于 256 和 1,073,741,824(1 GB 或 2^30)之间;超出此范围的值将调整为最接近的有效值。Log4j 将将指定的值向上舍入到最接近的 2 的幂。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
name | 字符串 | 附加器的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
以下是一个 MemoryMappedFile 配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <MemoryMappedFile name="MyFile" fileName="logs/app.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </MemoryMappedFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="MyFile"/> </Root> </Loggers> </Configuration>
NoSQLAppender
NoSQLAppender 使用内部轻量级提供程序接口将日志事件写入 NoSQL 数据库。目前存在用于 MongoDB 和 Apache CouchDB 的提供程序实现,编写自定义提供程序非常简单。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 必需。Appender 的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
bufferSize | int | 如果是一个大于 0 的整数,则会导致 appender 缓冲日志事件,并在缓冲区达到此大小时刷新。 |
NoSqlProvider | NoSQLProvider<C extends NoSQLConnection<W, T extends NoSQLObject<W>>> | 必需。提供与所选 NoSQL 数据库连接的 NoSQL 提供程序。 |
您可以通过在 `<NoSql>` 元素中指定相应的配置元素来指定要使用的 NoSQL 提供程序。目前支持的类型为 `<MongoDb>` 和 `<CouchDb>`。要创建自己的自定义提供程序,请阅读 `NoSQLProvider`、`NoSQLConnection` 和 `NoSQLObject` 类的 JavaDoc 以及有关创建 Log4j 插件的文档。我们建议您查看 MongoDB 和 CouchDB 提供程序的源代码,作为创建自己的提供程序的指南。
以下示例演示了如何将以 JSON 格式表示的日志事件持久化到 NoSQL 数据库中
{ "level": "WARN", "loggerName": "com.example.application.MyClass", "message": "Something happened that you might want to know about.", "source": { "className": "com.example.application.MyClass", "methodName": "exampleMethod", "fileName": "MyClass.java", "lineNumber": 81 }, "marker": { "name": "SomeMarker", "parent" { "name": "SomeParentMarker" } }, "threadName": "Thread-1", "millis": 1368844166761, "date": "2013-05-18T02:29:26.761Z", "thrown": { "type": "java.sql.SQLException", "message": "Could not insert record. Connection lost.", "stackTrace": [ { "className": "org.example.sql.driver.PreparedStatement$1", "methodName": "responder", "fileName": "PreparedStatement.java", "lineNumber": 1049 }, { "className": "org.example.sql.driver.PreparedStatement", "methodName": "executeUpdate", "fileName": "PreparedStatement.java", "lineNumber": 738 }, { "className": "com.example.application.MyClass", "methodName": "exampleMethod", "fileName": "MyClass.java", "lineNumber": 81 }, { "className": "com.example.application.MainClass", "methodName": "main", "fileName": "MainClass.java", "lineNumber": 52 } ], "cause": { "type": "java.io.IOException", "message": "Connection lost.", "stackTrace": [ { "className": "java.nio.channels.SocketChannel", "methodName": "write", "fileName": null, "lineNumber": -1 }, { "className": "org.example.sql.driver.PreparedStatement$1", "methodName": "responder", "fileName": "PreparedStatement.java", "lineNumber": 1032 }, { "className": "org.example.sql.driver.PreparedStatement", "methodName": "executeUpdate", "fileName": "PreparedStatement.java", "lineNumber": 738 }, { "className": "com.example.application.MyClass", "methodName": "exampleMethod", "fileName": "MyClass.java", "lineNumber": 81 }, { "className": "com.example.application.MainClass", "methodName": "main", "fileName": "MainClass.java", "lineNumber": 52 } ] } }, "contextMap": { "ID": "86c3a497-4e67-4eed-9d6a-2e5797324d7b", "username": "JohnDoe" }, "contextStack": [ "topItem", "anotherItem", "bottomItem" ] }
NoSQLAppender for MongoDB
从 Log4 2.11.0 开始,我们提供以下 MongoDB 模块
- 在 v2.11.0 中添加,在 v2.14.0 中删除:`log4j-mongodb2` 定义了与 MongoDB 驱动程序版本 2 匹配的配置元素 `MongoDb2`。
- 在 v2.11.0 中添加:`log4j-mongodb3` 定义了与 MongoDB 驱动程序版本 3 匹配的配置元素
MongoDb3
。 - 在 v2.14.0 中添加:`log4j-mongodb4` 定义了与 MongoDB 驱动程序版本 4 匹配的配置元素
MongoDb4
。
我们不再提供模块 `log4j-mongodb`。
模块 `log4j-mongodb2` 将旧的配置元素 `MongoDb` 映射到 MongoDb2
。
NoSQLAppender for MongoDB 3
本节详细介绍了使用 MongoDB 驱动程序版本 3 的 NoSQLAppender 提供程序的专门化。NoSQLAppender 追加器使用内部轻量级提供程序接口将日志事件写入 NoSQL 数据库。
参数名称 | 类型 | 描述 |
---|---|---|
collectionName | 字符串 | 必需。要将事件插入其中的 MongoDB 集合的名称。 |
writeConcernConstant | 字段 | 默认情况下,MongoDB 提供程序使用 `com.mongodb.WriteConcern.ACKNOWLEDGED` 指令插入记录。使用此可选属性指定除 `ACKNOWLEDGED` 之外的常量的名称。 |
writeConcernConstantClass | Class | 如果您指定了 `writeConcernConstant`,则可以使用此属性指定除 `com.mongodb.WriteConcern` 之外的类来查找常量(以创建自己的自定义指令)。 |
factoryClassName | Class | 要提供与 MongoDB 数据库的连接,您可以使用此属性和 `factoryMethodName` 指定一个类和静态方法来获取连接。该方法必须返回 `com.mongodb.client.MongoDatabase` 或 `com.mongodb.MongoClient`。如果 `com.mongodb.client.MongoDatabase` 未经身份验证,则还必须指定 `username` 和 `password`。如果您使用工厂方法来提供连接,则不得指定 `databaseName`、`server` 或 `port` 属性。 |
factoryMethodName | Method | 请参阅属性 `factoryClassName` 的文档。 |
databaseName | 字符串 | 如果您未指定用于提供 MongoDB 连接的 `factoryClassName` 和 `factoryMethodName`,则必须使用此属性指定 MongoDB 数据库名称。您还必须指定 `username` 和 `password`。您还可以选择指定 `server`(默认为 localhost)和 `port`(默认为 MongoDB 默认端口)。 |
server | 字符串 | 请参阅属性 `databaseName` 的文档。 |
port | int | 请参阅属性 `databaseName` 的文档。 |
username | 字符串 | 请参阅属性 `databaseName` 和 `factoryClassName` 的文档。 |
password | 字符串 | 请参阅属性 `databaseName` 和 `factoryClassName` 的文档。 |
capped | 布尔值 | 启用对 固定大小集合 的支持 |
collectionSize | int | 指定要使用的固定大小集合的大小(以字节为单位),如果已启用。最小大小为 4096 字节,更大的大小将增加到最接近的 256 的整数倍。有关更多信息,请参阅上面链接的固定大小集合文档。 |
此追加器是 MapMessage 意识的。
以下是一些 NoSQLAppender 和 MongoDB3 提供程序的配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <NoSql name="databaseAppender"> <MongoDb3 databaseName="applicationDb" collectionName="applicationLog" server="mongo.example.org" username="loggingUser" password="abc123" /> </NoSql> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <NoSql name="databaseAppender"> <MongoDb3 collectionName="applicationLog" factoryClassName="org.example.db.ConnectionFactory" factoryMethodName="getNewMongoClient" /> </NoSql> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
您可以使用 `KeyValuePair` 元素定义要记录的其他字段,例如
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <NoSql name="MongoDbAppender"> <MongoDb3 databaseName="testDb" collectionName="testCollection" server="localhost" port="${sys:MongoDBTestPort:-27017}" /> <KeyValuePair key="A" value="1" /> <KeyValuePair key="B" value="2" /> <KeyValuePair key="env1" value="${env:PATH}" /> <KeyValuePair key="env2" value="$${env:PATH}" /> </NoSql> </Appenders> <Loggers> <Root level="ALL"> <AppenderRef ref="MongoDbAppender" /> </Root> </Loggers> </Configuration>
NoSQLAppender for MongoDB 4
本节详细介绍了使用 MongoDB 驱动程序版本 4 的 NoSQLAppender 提供程序的专门化。NoSQLAppender 追加器使用内部轻量级提供程序接口将日志事件写入 NoSQL 数据库。
参数名称 | 类型 | 描述 |
---|---|---|
connection | 字符串 | 必需。MongoDB 连接字符串,格式为 `mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database.collection][?options]]` |
capped | 布尔值 | 启用对 固定大小集合 的支持 |
collectionSize | long | 指定要使用的固定大小集合的大小(以字节为单位),如果已启用。最小大小为 4096 字节,更大的大小将增加到最接近的 256 的整数倍。有关更多信息,请参阅上面链接的固定大小集合文档。 |
此追加器是 MapMessage 意识的。
以下是一些 NoSQLAppender 和 MongoDB4 提供程序的配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <NoSql name="MongoDbAppender"> <MongoDb4 connection="mongodb://log4jUser:12345678@localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" /> </NoSql> </Appenders> <Loggers> <Root level="ALL"> <AppenderRef ref="MongoDbAppender" /> </Root> </Loggers> </Configuration>
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <NoSql name="MongoDbAppender"> <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" capped="true" collectionSize="1073741824"/> </NoSql> </Appenders> <Loggers> <Root level="ALL"> <AppenderRef ref="MongoDbAppender" /> </Root> </Loggers> </Configuration>
您可以使用 `KeyValuePair` 元素定义要记录的其他字段,例如
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <NoSql name="MongoDbAppender"> <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" /> <KeyValuePair key="A" value="1" /> <KeyValuePair key="B" value="2" /> <KeyValuePair key="env1" value="${env:PATH}" /> <KeyValuePair key="env2" value="$${env:PATH}" /> </NoSql> </Appenders> <Loggers> <Root level="ALL"> <AppenderRef ref="MongoDbAppender" /> </Root> </Loggers> </Configuration>
NoSQLAppender for Apache CouchDB
本节详细介绍了用于 CouchDB 的 NoSQLAppender 提供程序的专门化。NoSQLAppender 追加器使用内部轻量级提供程序接口将日志事件写入 NoSQL 数据库。
参数名称 | 类型 | 描述 |
---|---|---|
factoryClassName | Class | 要提供与 CouchDB 数据库的连接,您可以使用此属性和 `factoryMethodName` 指定一个类和静态方法来获取连接。该方法必须返回 `org.lightcouch.CouchDbClient` 或 `org.lightcouch.CouchDbProperties`。如果您使用工厂方法来提供连接,则不得指定 `databaseName`、`protocol`、`server`、`port`、`username` 或 `password` 属性。 |
factoryMethodName | Method | 请参阅属性 `factoryClassName` 的文档。 |
databaseName | 字符串 | 如果您未指定用于提供 CouchDB 连接的 `factoryClassName` 和 `factoryMethodName`,则必须使用此属性指定 CouchDB 数据库名称。您还必须指定 `username` 和 `password`。您还可以选择指定 `protocol`(默认为 http)、`server`(默认为 localhost)和 `port`(默认为 http 的 80 和 https 的 443)。 |
protocol | 字符串 | 必须为 "http" 或 "https"。请参阅属性 `databaseName` 的文档。 |
server | 字符串 | 请参阅属性 `databaseName` 的文档。 |
port | int | 请参阅属性 `databaseName` 的文档。 |
username | 字符串 | 请参阅属性 `databaseName` 的文档。 |
password | 字符串 | 请参阅属性 `databaseName` 的文档。 |
以下是一些 NoSQLAppender 和 CouchDB 提供程序的配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <NoSql name="databaseAppender"> <CouchDb databaseName="applicationDb" protocol="https" server="couch.example.org" username="loggingUser" password="abc123" /> </NoSql> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
OutputStreamAppender
OutputStreamAppender 为许多其他追加器(如将事件写入输出流的文件和套接字追加器)提供了基础。它不能直接配置。OutputStreamAppender 提供了对 immediateFlush 和缓冲的支持。OutputStreamAppender 使用 OutputStreamManager 来处理实际的 I/O,允许多个配置中的追加器共享流。
RandomAccessFileAppender
RandomAccessFileAppender 与标准的 FileAppender 类似,但它始终被缓冲(无法关闭),并且在内部使用 ByteBuffer + RandomAccessFile
而不是 BufferedOutputStream
。在我们的 测量 中,与带有 "bufferedIO=true" 的 FileAppender 相比,我们看到了 20-200% 的性能提升。与 FileAppender 类似,RandomAccessFileAppender 使用 RandomAccessFileManager 来实际执行文件 I/O。虽然来自不同配置的 RandomAccessFileAppender 不能共享,但如果 Manager 可访问,则可以共享 RandomAccessFileManagers。例如,如果 Log4j 位于两个 Web 应用程序都共有的 ClassLoader 中,则 servlet 容器中的两个 Web 应用程序可以拥有自己的配置并安全地写入同一个文件。
参数名称 | 类型 | 描述 |
---|---|---|
append | 布尔值 | 当为 true 时 - 默认情况下,记录将追加到文件的末尾。当设置为 false 时,文件将在写入新记录之前被清除。 |
fileName | 字符串 | 要写入的文件的名称。如果文件或其任何父目录不存在,则将创建它们。 |
filters | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
immediateFlush | 布尔值 |
当设置为 true 时 - 默认情况下,每次写入后都会进行刷新。这将保证数据被传递到操作系统以进行写入;它不保证数据实际写入物理设备,例如磁盘驱动器。 请注意,如果此标志设置为 false,并且日志活动稀疏,则数据最终传递到操作系统的延迟可能是无限的,因为它被阻塞在缓冲区中。这会导致令人惊讶的效果,例如日志不会在写入日志后立即出现在文件的尾部输出中。 每次写入后刷新仅在将此 Appender 与同步记录器一起使用时才有用。异步记录器和 Appender 将在事件批处理结束时自动刷新,即使 immediateFlush 设置为 false。这也保证数据被传递到操作系统,但效率更高。 |
bufferSize | int | 缓冲区大小,默认为 262,144 字节(256 * 1024)。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
name | 字符串 | 附加器的名称。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
这是一个 RandomAccessFile 配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RandomAccessFile name="MyFile" fileName="logs/app.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </RandomAccessFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="MyFile"/> </Root> </Loggers> </Configuration>
RewriteAppender
RewriteAppender 允许在 LogEvent 被另一个 Appender 处理之前对其进行操作。这可以用来屏蔽敏感信息,例如密码,或者向每个事件注入信息。RewriteAppender 必须与 RewritePolicy 配合使用。RewriteAppender 应该配置在它引用的任何 Appender 之后,以允许它正常关闭。
参数名称 | 类型 | 描述 |
---|---|---|
AppenderRef | 字符串 | 在 LogEvent 被操作后要调用的 Appender 的名称。可以配置多个 AppenderRef 元素。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
name | 字符串 | 附加器的名称。 |
rewritePolicy | RewritePolicy | 将操作 LogEvent 的 RewritePolicy。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
RewritePolicy
RewritePolicy 是一个接口,允许实现检查并可能修改 LogEvent,然后再将其传递给 Appender。RewritePolicy 声明了一个名为 rewrite 的单一方法,该方法必须被实现。该方法传递了 LogEvent,并且可以返回相同的事件或创建一个新的事件。
MapRewritePolicy
MapRewritePolicy 将评估包含 MapMessage 的 LogEvent,并将添加或更新 Map 的元素。
参数名称 | 类型 | 描述 |
---|---|---|
mode | 字符串 | "Add" 或 "Update" |
keyValuePair | KeyValuePair[] | 键及其值的数组。 |
以下配置显示了一个 RewriteAppender,它被配置为将产品密钥及其值添加到 MapMessage 中。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Rewrite name="rewrite"> <AppenderRef ref="STDOUT"/> <MapRewritePolicy mode="Add"> <KeyValuePair key="product" value="TestProduct"/> </MapRewritePolicy> </Rewrite> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Rewrite"/> </Root> </Loggers> </Configuration>
PropertiesRewritePolicy
PropertiesRewritePolicy 将将策略上配置的属性添加到正在记录的 ThreadContext Map 中。这些属性不会添加到实际的 ThreadContext Map 中。属性值可能包含在处理配置时以及记录事件时将被评估的变量。
参数名称 | 类型 | 描述 |
---|---|---|
properties | Property[] | 一个或多个 Property 元素,用于定义要添加到 ThreadContext Map 中的键和值。 |
以下配置显示了一个 RewriteAppender,它被配置为将产品密钥及其值添加到 MapMessage 中
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Rewrite name="rewrite"> <AppenderRef ref="STDOUT"/> <PropertiesRewritePolicy> <Property name="user">${sys:user.name}</Property> <Property name="env">${sys:environment}</Property> </PropertiesRewritePolicy> </Rewrite> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Rewrite"/> </Root> </Loggers> </Configuration>
LoggerNameLevelRewritePolicy
您可以使用此策略通过更改事件级别来使第三方代码中的记录器不那么冗长。LoggerNameLevelRewritePolicy 将为给定的记录器名称前缀重写日志事件级别。您可以使用记录器名称前缀和级别对来配置 LoggerNameLevelRewritePolicy,其中一对定义了源级别和目标级别。
参数名称 | 类型 | 描述 |
---|---|---|
logger | 字符串 | 用作测试每个事件的记录器名称的前缀的记录器名称。 |
LevelPair | KeyValuePair[] | 键及其值的数组,每个键都是一个源级别,每个值都是一个目标级别。 |
以下配置显示了一个 RewriteAppender,它被配置为将级别 INFO 映射到 DEBUG,并将级别 WARN 映射到 INFO,适用于所有以 com.foo.bar
开头的记录器。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Rewrite name="rewrite"> <AppenderRef ref="STDOUT"/> <LoggerNameLevelRewritePolicy logger="com.foo.bar"> <KeyValuePair key="INFO" value="DEBUG"/> <KeyValuePair key="WARN" value="INFO"/> </LoggerNameLevelRewritePolicy> </Rewrite> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Rewrite"/> </Root> </Loggers> </Configuration>
RollingFileAppender
RollingFileAppender 是一个 OutputStreamAppender,它写入 fileName 参数中命名的文件,并根据 TriggeringPolicy 和 RolloverPolicy 对文件进行滚动。RollingFileAppender 使用 RollingFileManager(它扩展了 OutputStreamManager)来实际执行文件 I/O 并执行滚动。虽然来自不同配置的 RolloverFileAppenders 不能共享,但如果 Manager 可访问,则可以共享 RollingFileManagers。例如,如果 Log4j 位于两个 Web 应用程序都共有的 ClassLoader 中,则 servlet 容器中的两个 Web 应用程序可以拥有自己的配置并安全地写入同一个文件。
RollingFileAppender 需要一个 TriggeringPolicy 和一个 RolloverStrategy。触发策略决定是否应该执行滚动,而滚动策略定义了如何执行滚动。如果没有配置 RolloverStrategy,RollingFileAppender 将使用 DefaultRolloverStrategy。从 log4j-2.5 开始,可以在 DefaultRolloverStrategy 中配置一个 自定义删除操作,以便在滚动时运行。从 2.8 开始,如果没有配置文件名,则将使用 DirectWriteRolloverStrategy 而不是 DefaultRolloverStrategy。从 log4j-2.9 开始,可以在 DefaultRolloverStrategy 中配置一个 自定义 POSIX 文件属性视图操作,以便在滚动时运行,如果未定义,则将应用从 RollingFileAppender 继承的 POSIX 文件属性视图。
RollingFileAppender 不支持文件锁定。
参数名称 | 类型 | 描述 |
---|---|---|
append | 布尔值 | 当为 true 时 - 默认情况下,记录将追加到文件的末尾。当设置为 false 时,文件将在写入新记录之前被清除。 |
bufferedIO | 布尔值 | 当为 true 时 - 默认情况下,记录将写入缓冲区,数据将在缓冲区满时或(如果 immediateFlush 设置为 true)在写入记录时写入磁盘。文件锁定不能与 bufferedIO 一起使用。性能测试表明,使用缓冲 I/O 可以显着提高性能,即使启用了 immediateFlush。 |
bufferSize | int | 当 bufferedIO 为 true 时,这是缓冲区大小,默认值为 8192 字节。 |
createOnDemand | 布尔值 | Appender 按需创建文件。Appender 仅在日志事件通过所有过滤器并路由到此 Appender 时才创建文件。默认为 false。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
fileName | 字符串 | 要写入的文件的名称。如果文件或其任何父目录不存在,则将创建它们。 |
filePattern | 字符串 | 存档日志文件的名称模式。模式的格式取决于所使用的 RolloverPolicy。DefaultRolloverPolicy 将接受与 SimpleDateFormat 兼容的日期/时间模式和/或表示整数计数器的 %i。该模式还支持在运行时进行插值,因此任何查找(例如 DateLookup)都可以包含在模式中。 |
immediateFlush | 布尔值 |
当设置为 true 时 - 默认情况下,每次写入后都会进行刷新。这将保证数据被传递到操作系统以进行写入;它不保证数据实际写入物理设备,例如磁盘驱动器。 请注意,如果此标志设置为 false,并且日志活动稀疏,则数据最终传递到操作系统的延迟可能是无限的,因为它被阻塞在缓冲区中。这会导致令人惊讶的效果,例如日志不会在写入日志后立即出现在文件的尾部输出中。 每次写入后刷新仅在将此 Appender 与同步记录器一起使用时才有用。异步记录器和 Appender 将在事件批处理结束时自动刷新,即使 immediateFlush 设置为 false。这也保证数据被传递到操作系统,但效率更高。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
name | 字符串 | 附加器的名称。 |
policy | TriggeringPolicy | 用于确定是否应该发生滚动的策略。 |
strategy | RolloverStrategy | 用于确定存档文件名称和位置的策略。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
filePermissions | 字符串 |
每次创建文件时要应用的 POSIX 格式的文件属性权限。 底层文件系统应支持 POSIX 文件属性视图。 示例:rw------- 或 rw-rw-rw- 等... |
fileOwner | 字符串 |
每次创建文件时要定义的文件所有者。 出于安全原因,更改文件的拥有者可能会受到限制,并且会抛出 Operation not permitted IOException。如果 _POSIX_CHOWN_RESTRICTED 对路径有效,则只有有效用户 ID 等于文件用户 ID 或具有适当权限的进程才能更改文件的拥有权。 底层文件系统应支持文件 所有者 属性视图。 |
fileGroup | 字符串 |
每次创建文件时要定义的文件组。 底层文件系统应支持 POSIX 文件属性视图。 |
触发策略
组合触发策略
CompositeTriggeringPolicy
组合了多个触发策略,如果任何配置的策略返回 true,则返回 true。CompositeTriggeringPolicy
的配置只需将其他策略包装在 Policies
元素中即可。
例如,以下 XML 片段定义了在 JVM 启动时、日志大小达到 20 兆字节时以及当前日期不再与日志的开始日期匹配时滚动日志的策略。
<Policies> <OnStartupTriggeringPolicy /> <SizeBasedTriggeringPolicy size="20 MB" /> <TimeBasedTriggeringPolicy /> </Policies>
Cron 触发策略
CronTriggeringPolicy
根据 cron 表达式触发滚动。此策略由计时器控制,并且与处理日志事件是异步的,因此,来自先前或下一个时间段的日志事件可能出现在日志文件开头或结尾。Appender 的 filePattern 属性应该包含时间戳,否则目标文件将在每次滚动时被覆盖。
参数名称 | 类型 | 描述 |
---|---|---|
schedule | 字符串 | cron 表达式。表达式与 Quartz 调度程序中允许的表达式相同。有关表达式的完整描述,请参阅 CronExpression。 |
evaluateOnStartup | 布尔值 | 在启动时,cron 表达式将根据文件的最后修改时间戳进行评估。如果 cron 表达式指示在该时间和当前时间之间应该发生滚动,则该文件将立即滚动。 |
OnStartup 触发策略
OnStartupTriggeringPolicy
策略如果日志文件比当前 JVM 的启动时间早,并且最小文件大小已达到或超过,则会导致滚动。
参数名称 | 类型 | 描述 |
---|---|---|
minSize | long | 文件必须具有的最小大小才能滚动。大小为零将导致滚动,无论文件大小如何。默认值为 1,这将阻止滚动空文件。 |
Google App Engine 注意
在 Google App Engine 中运行时,OnStartup 策略如果日志文件比Log4J 初始化的时间早,则会导致滚动。(Google App Engine 限制对某些类的访问,因此 Log4J 无法使用 java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()
确定 JVM 启动时间,而是回退到 Log4J 初始化时间。)
基于大小的触发策略
SizeBasedTriggeringPolicy
在文件达到指定大小后会导致滚动。大小可以用字节指定,后缀为 KB、MB、GB 或 TB,例如 20MB
。大小也可以包含小数,例如 1.5 MB
。大小使用 Java 根区域设置进行评估,因此小数单位始终必须使用句点。当与基于时间的触发策略结合使用时,文件模式必须包含 %i
,否则目标文件将在每次滚动时被覆盖,因为 SizeBased Triggering Policy 不会导致文件名中的时间戳值发生变化。当不与基于时间的触发策略一起使用时,SizeBased Triggering Policy 将导致时间戳值发生变化。
基于时间的触发策略
TimeBasedTriggeringPolicy
在日期/时间模式不再适用于活动文件时会导致滚动。此策略接受一个 interval
属性,该属性指示滚动应该根据时间模式发生的频率,以及一个 modulate
布尔属性。
参数名称 | 类型 | 描述 |
---|---|---|
interval | 整数 | 根据日期模式中最具体的时间单位,滚动应该发生的频率。例如,对于以小时为最具体项目的日期模式,增量为 4,则每 4 小时会发生一次滚动。默认值为 1。 |
modulate | 布尔值 | 指示是否应该调整间隔以使下次滚动发生在间隔边界。例如,如果项目是小时,当前时间是凌晨 3 点,间隔是 4,则第一次滚动将在凌晨 4 点发生,然后接下来的滚动将在上午 8 点、中午、下午 4 点等发生。默认值为 false。 |
maxRandomDelay | 整数 | 指示随机延迟滚动的最大秒数。默认情况下,此值为 0,表示没有延迟。此设置在多个应用程序配置为在同一时间滚动日志文件的服务器上很有用,可以将执行此操作的负载分散到不同时间。 |
滚动策略
默认滚动策略
默认滚动策略接受来自 RollingFileAppender 本身指定的 filePattern 属性的日期/时间模式和整数。如果存在日期/时间模式,它将被替换为当前日期和时间值。如果模式包含整数,它将在每次滚动时递增。如果模式在模式中同时包含日期/时间和整数,则整数将递增,直到日期/时间模式的结果发生变化。如果文件名以 ".gz"、".zip"、".bz2"、".deflate"、".pack200"、".zst" 或 ".xz" 结尾,则生成的存档将使用与后缀匹配的压缩方案进行压缩。bzip2、Deflate、Pack200、XZ 和 ZStandard 格式需要 Apache Commons Compress。此外
该模式还可以包含可以在运行时解析的查找引用,如下面的示例所示。默认滚动策略支持三种递增计数器的变体。为了说明它是如何工作的,假设 min 属性设置为 1,max 属性设置为 3,文件名是 "foo.log",文件名模式是 "foo-%i.log"。
滚动次数 | 活动输出目标 | 存档日志文件 | 描述 |
---|---|---|---|
0 | foo.log | - | 所有日志将写入初始文件。 |
1 | foo.log | foo-1.log | 在第一次滚动时,foo.log 将重命名为 foo-1.log。将创建一个新的 foo.log 文件并开始写入。 |
2 | foo.log | foo-2.log, foo-1.log | 在第二次滚动时,foo.log 将重命名为 foo-2.log。将创建一个新的 foo.log 文件并开始写入。 |
3 | foo.log | foo-3.log, foo-2.log, foo-1.log | 在第三次滚动时,foo.log 将重命名为 foo-3.log。将创建一个新的 foo.log 文件并开始写入。 |
4 | foo.log | foo-3.log, foo-2.log, foo-1.log | 在第四次及后续滚动时,foo-1.log 将被删除,foo-2.log 将重命名为 foo-1.log,foo-3.log 将重命名为 foo-2.log,foo.log 将重命名为 foo-3.log。将创建一个新的 foo.log 文件并开始写入。 |
相比之下,当 fileIndex 属性设置为 "min" 但其他所有设置都相同,将执行 "固定窗口" 策略。
滚动次数 | 活动输出目标 | 存档日志文件 | 描述 |
---|---|---|---|
0 | foo.log | - | 所有日志将写入初始文件。 |
1 | foo.log | foo-1.log | 在第一次滚动时,foo.log 将重命名为 foo-1.log。将创建一个新的 foo.log 文件并开始写入。 |
2 | foo.log | foo-1.log, foo-2.log | 在第二次滚动时,foo-1.log 将重命名为 foo-2.log,foo.log 将重命名为 foo-1.log。将创建一个新的 foo.log 文件并开始写入。 |
3 | foo.log | foo-1.log, foo-2.log, foo-3.log | 在第三次滚动时,foo-2.log 将重命名为 foo-3.log,foo-1.log 将重命名为 foo-2.log,foo.log 将重命名为 foo-1.log。将创建一个新的 foo.log 文件并开始写入。 |
4 | foo.log | foo-1.log, foo-2.log, foo-3.log | 在第四次及后续滚动时,foo-3.log 将被删除,foo-2.log 将重命名为 foo-3.log,foo-1.log 将重命名为 foo-2.log,foo.log 将重命名为 foo-1.log。将创建一个新的 foo.log 文件并开始写入。 |
最后,从 2.8 版本开始,如果 fileIndex 属性设置为 "nomax",则 min 和 max 值将被忽略,文件编号将递增 1,每次滚动将具有递增更高的值,且没有最大文件数。
参数名称 | 类型 | 描述 |
---|---|---|
fileIndex | 字符串 | 如果设置为 "max"(默认值),则索引较高的文件将比索引较小的文件更新。如果设置为 "min",则文件重命名和计数器将遵循上面描述的固定窗口策略。 |
min | 整数 | 计数器的最小值。默认值为 1。 |
max | 整数 | 计数器的最大值。一旦达到此值,在后续滚动时将删除较旧的存档。默认值为 7。 |
compressionLevel | 整数 | 设置压缩级别,0-9,其中 0 = 无,1 = 最快速度,到 9 = 最佳压缩。仅针对 ZIP 文件实现。 |
tempCompressedFilePattern | 字符串 | 压缩期间存档日志文件的名称模式。 |
直接写入滚动策略
DirectWriteRolloverStrategy 使日志事件直接写入由文件模式表示的文件。使用此策略不会执行文件重命名。如果基于大小的触发策略导致在指定时间段内写入多个文件,则它们将从 1 开始编号,并持续递增,直到发生基于时间的滚动。
警告:如果文件模式具有表示应执行压缩的后缀,则应用程序关闭时不会压缩当前文件。此外,如果时间发生变化,使得文件模式不再与当前文件匹配,则在启动时也不会压缩它。
参数名称 | 类型 | 描述 |
---|---|---|
maxFiles | 字符串 | 在与文件模式匹配的时间段内允许的最大文件数。如果文件数超过此值,将删除最旧的文件。如果指定,则该值必须大于 1。如果该值小于零或省略,则文件数将不受限制。 |
compressionLevel | 整数 | 设置压缩级别,0-9,其中 0 = 无,1 = 最快速度,到 9 = 最佳压缩。仅针对 ZIP 文件实现。 |
tempCompressedFilePattern | 字符串 | 压缩期间存档日志文件的名称模式。 |
以下是一个示例配置,它使用 RollingFileAppender 同时使用基于时间和基于大小的触发策略,将在同一天(1-7)创建最多 7 个存档,这些存档存储在基于当前年份和月份的目录中,并将使用 gzip 压缩每个存档
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
第二个示例显示了一个滚动策略,该策略将在删除它们之前最多保留 20 个文件。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DefaultRolloverStrategy max="20"/> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
以下是一个示例配置,它使用 RollingFileAppender 同时使用基于时间和基于大小的触发策略,将在同一天(1-7)创建最多 7 个存档,这些存档存储在基于当前年份和月份的目录中,并将使用 gzip 压缩每个存档,并且每 6 小时滚动一次,当小时数可被 6 整除时。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="6" modulate="true"/> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
此示例配置使用 RollingFileAppender 同时使用 cron 和基于大小的触发策略,并直接写入无限数量的存档文件。cron 触发器每小时导致滚动一次,而文件大小限制为 250MB。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <CronTriggeringPolicy schedule="0 0 * * * ?"/> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
此示例配置与上一个相同,但将每小时保存的文件数限制为 10 个。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <CronTriggeringPolicy schedule="0 0 * * * ?"/> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DirectWriteRolloverStrategy maxFiles="10"/> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
日志存档保留策略:滚动时删除
Log4j-2.5 引入了一个 Delete
操作,它允许用户比使用 DefaultRolloverStrategy max
属性时更灵活地控制在滚动时删除哪些文件。Delete 操作允许用户配置一个或多个条件,这些条件选择相对于基本目录要删除的文件。
请注意,可以删除任何文件,而不仅仅是滚动的日志文件,因此请谨慎使用此操作!使用 testMode
参数,您可以在不意外删除错误文件的情况下测试您的配置。
参数名称 | 类型 | 描述 |
---|---|---|
basePath | 字符串 | 必需。从哪里开始扫描要删除的文件的基本路径。 |
maxDepth | int | 要访问的目录级别的最大数量。值为 0 表示仅访问起始文件(基本路径本身),除非被安全管理器拒绝。值为 Integer.MAX_VALUE 表示应访问所有级别。默认值为 1,表示仅访问指定基本目录中的文件。 |
followLinks | 布尔值 | 是否遵循符号链接。默认值为 false。 |
testMode | 布尔值 | 如果为 true,则不会删除文件,而是将一条消息打印到 状态记录器,级别为 INFO。使用此功能进行试运行,以测试配置是否按预期工作。默认值为 false。 |
pathSorter | PathSorter | 实现 PathSorter 接口的插件,用于在选择要删除的文件之前对文件进行排序。默认情况下,按最近修改时间对文件进行排序,最近修改的文件排在最前面。 |
pathConditions | PathCondition[] |
如果未指定 ScriptCondition,则必需。一个或多个 PathCondition 元素。 如果指定了多个条件,则它们都需要接受一个路径,然后才能删除该路径。条件可以嵌套,在这种情况下,只有当外部条件接受该路径时,才会评估内部条件。如果条件未嵌套,则可以按任何顺序评估它们。 条件还可以使用 用户可以创建自定义条件或使用内置条件
|
scriptCondition | ScriptCondition |
如果未指定 PathConditions,则必需。指定脚本的 ScriptCondition 元素。 ScriptCondition 应包含一个 Script、ScriptRef 或 ScriptFile 元素,该元素指定要执行的逻辑。(另请参阅 ScriptFilter 文档以获取有关配置 ScriptFiles 和 ScriptRefs 的更多示例。) 脚本传递给它一些 参数,包括在基本路径下找到的路径列表(最多 |
参数名称 | 类型 | 描述 |
---|---|---|
glob | 字符串 | 如果未指定 regex,则必需。使用类似于正则表达式但语法更 简单 的有限模式语言匹配相对路径(相对于基本路径)。 |
regex | 字符串 | 如果未指定 glob,则必需。使用由 Pattern 类定义的正则表达式匹配相对路径(相对于基本路径)。 |
nestedConditions | PathCondition[] | 一组可选的嵌套 PathConditions。如果存在任何嵌套条件,则它们都需要接受文件,然后才能删除该文件。只有当外部条件接受文件(如果路径名匹配)时,才会评估嵌套条件。 |
参数名称 | 类型 | 描述 |
---|---|---|
age | 字符串 | 必需。指定一个 持续时间。该条件接受与指定持续时间一样旧或更旧的文件。 |
nestedConditions | PathCondition[] | 一组可选的嵌套 PathConditions。如果存在任何嵌套条件,则它们都需要接受文件,然后才能删除该文件。只有当外部条件接受文件(如果文件足够旧)时,才会评估嵌套条件。 |
参数名称 | 类型 | 描述 |
---|---|---|
exceeds | int | 必需。将从该阈值计数开始删除文件。 |
nestedConditions | PathCondition[] | 一组可选的嵌套 PathConditions。如果存在任何嵌套条件,则它们都需要接受文件,然后才能删除该文件。只有当外部条件接受文件(如果超过阈值计数)时,才会评估嵌套条件。 |
参数名称 | 类型 | 描述 |
---|---|---|
exceeds | 字符串 | 必需。将从该阈值累积文件大小开始删除文件。大小可以用字节指定,后缀为 KB、MB、GB 或 TB,例如 20MB 。 |
nestedConditions | PathCondition[] | 可选的一组嵌套的 PathConditions。如果存在任何嵌套条件,则它们都需要接受文件才能删除该文件。只有在外层条件接受文件(如果累积的文件大小阈值已超过)时,才会评估嵌套条件。 |
以下是一个示例配置,它使用 RollingFileAppender,其中 cron 触发策略配置为每天午夜触发。存档存储在基于当前年份和月份的目录中。在基本目录下匹配“*/app-*.log.gz”通配符且年龄在 60 天或更旧的所有文件将在滚动时删除。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Properties> <Property name="baseDir">logs</Property> </Properties> <Appenders> <RollingFile name="RollingFile" fileName="${baseDir}/app.log" filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}.log.gz"> <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" /> <CronTriggeringPolicy schedule="0 0 0 * * ?"/> <DefaultRolloverStrategy> <Delete basePath="${baseDir}" maxDepth="2"> <IfFileName glob="*/app-*.log.gz" /> <IfLastModified age="P60D" /> </Delete> </DefaultRolloverStrategy> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
以下是一个示例配置,它使用 RollingFileAppender,其中同时使用基于时间和大小的触发策略,将在同一天(1-100)创建最多 100 个存档,这些存档存储在基于当前年份和月份的目录中,并将使用 gzip 压缩每个存档,并将每小时滚动一次。在每次滚动期间,此配置将删除与“*/app-*.log.gz”匹配且年龄在 30 天或更旧的文件,但保留最近的 100 GB 或最近的 10 个文件,以先到者为准。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Properties> <Property name="baseDir">logs</Property> </Properties> <Appenders> <RollingFile name="RollingFile" fileName="${baseDir}/app.log" filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz"> <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" /> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DefaultRolloverStrategy max="100"> <!-- Nested conditions: the inner condition is only evaluated on files for which the outer conditions are true. --> <Delete basePath="${baseDir}" maxDepth="2"> <IfFileName glob="*/app-*.log.gz"> <IfLastModified age="P30D"> <IfAny> <IfAccumulatedFileSize exceeds="100 GB" /> <IfAccumulatedFileCount exceeds="10" /> </IfAny> </IfLastModified> </IfFileName> </Delete> </DefaultRolloverStrategy> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
参数名称 | 类型 | 描述 |
---|---|---|
script | Script、ScriptFile 或 ScriptRef | 指定要执行的逻辑的 Script 元素。脚本传递给基本路径下找到的路径列表,并且必须返回要删除的路径,作为 java.util.List<PathWithAttributes> 。另请参阅 ScriptFilter 文档,了解如何配置 ScriptFiles 和 ScriptRefs 的示例。 |
参数名称 | 类型 | 描述 |
---|---|---|
basePath | java.nio.file.Path |
Delete 操作开始扫描要删除的文件的目录。可用于将路径列表中的路径相对化。 |
pathList | java.util.List<PathWithAttributes> |
在基本路径下找到的路径列表,直到指定的最大深度,按最近修改时间排序,最近修改的文件排在最前面。脚本可以随意修改和返回此列表。 |
statusLogger | StatusLogger | 可用于在脚本执行期间记录内部事件的 StatusLogger。 |
configuration | Configuration | 拥有此 ScriptCondition 的 Configuration。 |
substitutor | StrSubstitutor | 用于替换查找变量的 StrSubstitutor。 |
? | 字符串 | 配置中声明的任何属性。 |
以下是一个示例配置,它使用 RollingFileAppender,其中 cron 触发策略配置为每天午夜触发。存档存储在基于当前年份和月份的目录中。脚本返回基本目录下日期为 13 号星期五的已滚动文件的列表。Delete 操作将删除脚本返回的所有文件。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="trace" name="MyApp"> <Properties> <Property name="baseDir">logs</Property> </Properties> <Appenders> <RollingFile name="RollingFile" fileName="${baseDir}/app.log" filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz"> <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" /> <CronTriggeringPolicy schedule="0 0 0 * * ?"/> <DefaultRolloverStrategy> <Delete basePath="${baseDir}" maxDepth="2"> <ScriptCondition> <Script name="superstitious" language="groovy"><![CDATA[ import java.nio.file.*; def result = []; def pattern = ~/\d*\/app-(\d*)\.log\.gz/; pathList.each { pathWithAttributes -> def relative = basePath.relativize pathWithAttributes.path statusLogger.trace 'SCRIPT: relative path=' + relative + " (base=$basePath)"; // remove files dated Friday the 13th def matcher = pattern.matcher(relative.toString()); if (matcher.find()) { def dateString = matcher.group(1); def calendar = Date.parse("yyyyMMdd", dateString).toCalendar(); def friday13th = calendar.get(Calendar.DAY_OF_MONTH) == 13 \ && calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY; if (friday13th) { result.add pathWithAttributes; statusLogger.trace 'SCRIPT: deleting path ' + pathWithAttributes; } } } statusLogger.trace 'SCRIPT: returning ' + result; result; ]] > </Script> </ScriptCondition> </Delete> </DefaultRolloverStrategy> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
日志存档文件属性视图策略:滚动时的自定义文件属性
Log4j-2.9 引入了一个 PosixViewAttribute
操作,它使用户可以更好地控制应应用哪些文件属性权限、所有者和组。PosixViewAttribute 操作允许用户配置一个或多个条件,这些条件选择相对于基本目录的合格文件。
参数名称 | 类型 | 描述 |
---|---|---|
basePath | 字符串 | 必需。从哪里开始扫描要应用属性的文件的基本路径。 |
maxDepth | int | 要访问的目录级别的最大数量。值为 0 表示仅访问起始文件(基本路径本身),除非被安全管理器拒绝。值为 Integer.MAX_VALUE 表示应访问所有级别。默认值为 1,表示仅访问指定基本目录中的文件。 |
followLinks | 布尔值 | 是否遵循符号链接。默认值为 false。 |
pathConditions | PathCondition[] | 参见 DeletePathCondition |
filePermissions | 字符串 |
执行操作时要应用的 POSIX 格式的文件属性权限。 底层文件系统应支持 POSIX 文件属性视图。 示例:rw------- 或 rw-rw-rw- 等... |
fileOwner | 字符串 |
执行操作时要定义的文件所有者。 出于安全原因,更改文件的拥有者可能会受到限制,并且会抛出 Operation not permitted IOException。如果 _POSIX_CHOWN_RESTRICTED 对路径有效,则只有有效用户 ID 等于文件用户 ID 或具有适当权限的进程才能更改文件的拥有权。 底层文件系统应支持文件 所有者 属性视图。 |
fileGroup | 字符串 |
执行操作时要定义的文件组。 底层文件系统应支持 POSIX 文件属性视图。 |
以下是一个示例配置,它使用 RollingFileAppender 并为当前日志文件和已滚动日志文件定义不同的 POSIX 文件属性视图。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="trace" name="MyApp"> <Properties> <Property name="baseDir">logs</Property> </Properties> <Appenders> <RollingFile name="RollingFile" fileName="${baseDir}/app.log" filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz" filePermissions="rw-------"> <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" /> <CronTriggeringPolicy schedule="0 0 0 * * ?"/> <DefaultRolloverStrategy stopCustomActionsOnError="true"> <PosixViewAttribute basePath="${baseDir}/$${date:yyyy-MM}" filePermissions="r--r--r--"> <IfFileName glob="*.gz" /> </PosixViewAttribute> </DefaultRolloverStrategy> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
RollingRandomAccessFileAppender
RollingRandomAccessFileAppender 与标准 RollingFileAppender 类似,只是它始终被缓冲(这无法关闭),并且在内部它使用 ByteBuffer + RandomAccessFile
而不是 BufferedOutputStream
。我们在 测量 中发现,与“bufferedIO=true”的 RollingFileAppender 相比,性能提高了 20-200%。RollingRandomAccessFileAppender 写入 fileName 参数中命名的文件,并根据 TriggeringPolicy 和 RolloverPolicy 滚动文件。与 RollingFileAppender 类似,RollingRandomAccessFileAppender 使用 RollingRandomAccessFileManager 来实际执行文件 I/O 并执行滚动。虽然来自不同 Configuration 的 RollingRandomAccessFileAppender 无法共享,但如果 Manager 可访问,则 RollingRandomAccessFileManagers 可以共享。例如,如果 Log4j 位于对两者都通用的 ClassLoader 中,则 servlet 容器中的两个 Web 应用程序可以拥有自己的配置并安全地写入同一个文件。
RollingRandomAccessFileAppender 需要一个 TriggeringPolicy 和一个 RolloverStrategy。触发策略决定是否应执行滚动,而滚动策略定义如何执行滚动。如果未配置 RolloverStrategy,则 RollingRandomAccessFileAppender 将使用 DefaultRolloverStrategy。从 log4j-2.5 开始,可以在 DefaultRolloverStrategy 中配置一个 自定义删除操作,以便在滚动时运行。
RollingRandomAccessFileAppender 不支持文件锁定。
参数名称 | 类型 | 描述 |
---|---|---|
append | 布尔值 | 当为 true 时 - 默认情况下,记录将追加到文件的末尾。当设置为 false 时,文件将在写入新记录之前被清除。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
fileName | 字符串 | 要写入的文件的名称。如果文件或其任何父目录不存在,则将创建它们。 |
filePattern | 字符串 | 存档日志文件的名称模式。模式的格式应取决于使用的 RolloverStrategy。DefaultRolloverStrategy 将接受与 SimpleDateFormat 兼容的日期/时间模式和/或表示整数计数器的 %i。整数计数器允许指定填充,例如 %3i 用于将计数器空格填充到 3 位数字,或者(通常更有用)%03i 用于将计数器零填充到 3 位数字。该模式还支持在运行时进行插值,因此任何查找(例如 DateLookup)都可以包含在模式中。 |
immediateFlush | 布尔值 |
设置为 true 时(默认值),每次写入后都会进行刷新。这将保证数据写入磁盘,但可能会影响性能。 只有在将此追加器与同步记录器一起使用时,每次写入后刷新才有用。异步记录器和追加器会在事件批处理结束时自动刷新,即使 immediateFlush 设置为 false 也是如此。这也保证了数据写入磁盘,但效率更高。 |
bufferSize | int | 缓冲区大小,默认为 262,144 字节(256 * 1024)。 |
layout | Layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
name | 字符串 | 附加器的名称。 |
policy | TriggeringPolicy | 用于确定是否应该发生滚动的策略。 |
strategy | RolloverStrategy | 用于确定存档文件名称和位置的策略。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
filePermissions | 字符串 |
每次创建文件时要应用的 POSIX 格式的文件属性权限。 底层文件系统应支持 POSIX 文件属性视图。 示例: |
fileOwner | 字符串 |
每次创建文件时要定义的文件所有者。 出于安全原因,更改文件的拥有者可能会受到限制,并且会抛出 Operation not permitted IOException。如果 _POSIX_CHOWN_RESTRICTED 对路径有效,则只有有效用户 ID 等于文件用户 ID 或具有适当权限的进程才能更改文件的拥有权。 底层文件系统应支持文件 所有者 属性视图。 |
fileGroup | 字符串 |
每次创建文件时要定义的文件组。 底层文件系统应支持 POSIX 文件属性视图。 |
触发策略
滚动策略
以下是一个示例配置,它使用 RollingRandomAccessFileAppender,其中同时使用基于时间和大小的触发策略,将在同一天(1-7)创建最多 7 个存档,这些存档存储在基于当前年份和月份的目录中,并将使用 gzip 压缩每个存档
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> </RollingRandomAccessFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingRandomAccessFile"/> </Root> </Loggers> </Configuration>
第二个示例显示了一个滚动策略,该策略将在删除它们之前最多保留 20 个文件。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DefaultRolloverStrategy max="20"/> </RollingRandomAccessFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingRandomAccessFile"/> </Root> </Loggers> </Configuration>
以下是一个示例配置,它使用 RollingRandomAccessFileAppender,其中同时使用基于时间和大小的触发策略,将在同一天(1-7)创建最多 7 个存档,这些存档存储在基于当前年份和月份的目录中,并将使用 gzip 压缩每个存档,并将每 6 小时滚动一次,当小时数可被 6 整除时
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="6" modulate="true"/> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> </RollingRandomAccessFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingRandomAccessFile"/> </Root> </Loggers> </Configuration>
RoutingAppender
RoutingAppender 评估 LogEvents,然后将它们路由到下级 Appender。目标 Appender 可以是先前配置的 Appender,并且可以通过其名称引用,或者可以根据需要动态创建 Appender。RoutingAppender 应在它引用的任何 Appender 之后配置,以允许它正常关闭。
您还可以使用脚本配置 RoutingAppender:您可以在 Appender 启动时以及为日志事件选择路由时运行脚本。
参数名称 | 类型 | 描述 | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
过滤器 | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 | |||||||||
name | 字符串 | 附加器的名称。 | |||||||||
RewritePolicy | RewritePolicy | 将操作 LogEvent 的 RewritePolicy。 | |||||||||
Routes | Routes | 包含一个或多个 Route 声明,以标识选择 Appender 的条件。 | |||||||||
Script | Script |
此 Script 在 Log4j 启动 RoutingAppender 时运行,并返回一个 String Route 密钥以确定默认 Route。 此脚本传递以下变量
|
|||||||||
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
在此示例中,脚本导致“ServiceWindows”路由成为 Windows 上的默认路由,而“ServiceOther”成为所有其他操作系统上的默认路由。请注意,List Appender 是我们的测试 Appender 之一,可以使用任何 Appender,它仅用作简写。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN" name="RoutingTest"> <Appenders> <Routing name="Routing"> <Script name="RoutingInit" language="JavaScript"><![CDATA[ java.lang.System.getProperty("os.name").search("Windows") > -1 ? "ServiceWindows" : "ServiceOther";]]> </Script> <Routes> <Route key="ServiceOther"> <List name="List1" /> </Route> <Route key="ServiceWindows"> <List name="List2" /> </Route> </Routes> </Routing> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Routing" /> </Root> </Loggers> </Configuration>
Routes
Routes 元素接受名为“pattern”的单个属性。该模式针对所有注册的查找进行评估,结果用于选择 Route。每个 Route 都可以配置一个密钥。如果密钥与评估模式的结果匹配,则将选择该 Route。如果 Route 上未指定密钥,则该 Route 为默认 Route。只能配置一个 Route 作为默认 Route。
Routes 元素可能包含一个 Script 子元素。如果指定,则脚本将为每个日志事件运行,并返回要使用的 String Route 密钥。
您必须指定 pattern 属性或 Script 元素,但不能同时指定两者。
每个 Route 必须引用一个 Appender。如果 Route 包含 ref 属性,则 Route 将引用在配置中定义的 Appender。如果 Route 包含 Appender 定义,则将在 RoutingAppender 的上下文中创建一个 Appender,并且每次通过 Route 引用匹配的 Appender 名称时都会重复使用该 Appender。
此脚本传递以下变量
参数名称 | 类型 | 描述 |
---|---|---|
configuration | Configuration | 活动的 Configuration。 |
staticVariables | Map | 此 Appender 实例的所有脚本调用之间共享的 Map。这是传递给 Routes Script 的同一个 Map。 |
logEvent | LogEvent | 日志事件。 |
在此示例中,脚本将为每个日志事件运行,并根据是否存在名为“AUDIT”的标记来选择路由。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN" name="RoutingTest"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT" /> <Flume name="AuditLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Routing name="Routing"> <Routes> <Script name="RoutingInit" language="JavaScript"><![CDATA[ if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("AUDIT")) { return "AUDIT"; } else if (logEvent.getContextMap().containsKey("UserId")) { return logEvent.getContextMap().get("UserId"); } return "STDOUT";]]> </Script> <Route> <RollingFile name="Rolling-${mdc:UserId}" fileName="${mdc:UserId}.log" filePattern="${mdc:UserId}.%i.log.gz"> <PatternLayout> <pattern>%d %p %c{1.} [%t] %m%n</pattern> </PatternLayout> <SizeBasedTriggeringPolicy size="500" /> </RollingFile> </Route> <Route ref="AuditLogger" key="AUDIT"/> <Route ref="STDOUT" key="STDOUT"/> </Routes> <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> </Routing> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Routing" /> </Root> </Loggers> </Configuration>
清除策略
RoutingAppender 可以配置一个 PurgePolicy,其目的是停止并删除由 RoutingAppender 动态创建的处于休眠状态的 Appender。Log4j 目前提供 IdlePurgePolicy 作为唯一可用于清理 Appender 的 PurgePolicy。IdlePurgePolicy 接受 2 个属性;timeToLive,即 Appender 在没有事件发送到它时应存活的时间单位数,以及 timeUnit,即 java.util.concurrent.TimeUnit 的字符串表示形式,它与 timeToLive 属性一起使用。
以下是一个示例配置,它使用 RoutingAppender 将所有 Audit 事件路由到 FlumeAppender,并将所有其他事件路由到仅捕获特定事件类型的 RollingFileAppender。请注意,AuditAppender 是预定义的,而 RollingFileAppenders 是根据需要创建的。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Flume name="AuditLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Routing name="Routing"> <Routes pattern="$${sd:type}"> <Route> <RollingFile name="Rolling-${sd:type}" fileName="${sd:type}.log" filePattern="${sd:type}.%i.log.gz"> <PatternLayout> <pattern>%d %p %c{1.} [%t] %m%n</pattern> </PatternLayout> <SizeBasedTriggeringPolicy size="500" /> </RollingFile> </Route> <Route ref="AuditLogger" key="Audit"/> </Routes> <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> </Routing> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Routing"/> </Root> </Loggers> </Configuration>
SMTPAppender
在发生特定日志事件时发送电子邮件,通常是在错误或致命错误时。
此电子邮件中传递的日志事件数量取决于BufferSize选项的值。SMTPAppender
在其循环缓冲区中仅保留最后BufferSize
个日志事件。这将内存需求保持在合理水平,同时仍能提供有用的应用程序上下文。缓冲区中的所有事件都包含在电子邮件中。缓冲区将包含在触发电子邮件的事件之前从 TRACE 到 WARN 的级别中最新的事件。
默认行为是在记录 ERROR 或更高严重性的事件时触发发送电子邮件,并将其格式化为 HTML。可以通过在 Appender 上设置一个或多个过滤器来控制何时发送电子邮件。与其他 Appender 一样,可以通过为 Appender 指定一个 Layout 来控制格式。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 附加器的名称。 |
from | 字符串 | 发件人的电子邮件地址。 |
replyTo | 字符串 | 回复地址的逗号分隔列表。 |
to | 字符串 | 收件人电子邮件地址的逗号分隔列表。 |
cc | 字符串 | 抄送电子邮件地址的逗号分隔列表。 |
bcc | 字符串 | 密件抄送电子邮件地址的逗号分隔列表。 |
subject | 字符串 | 电子邮件的主题。 |
bufferSize | 整数 | 要缓冲的最大日志事件数量,以便将其包含在消息中。默认为 512。 |
layout | Layout | 用于格式化 LogEvent 的 Layout。如果没有提供 Layout,将使用HTML Layout。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
smtpDebug | 布尔值 | 设置为 true 时,将在 STDOUT 上启用会话调试。默认为 false。 |
smtpHost | 字符串 | 要发送到的 SMTP 主机名。此参数是必需的。 |
smtpPassword | 字符串 | 用于对 SMTP 服务器进行身份验证所需的密码。 |
smtpPort | 整数 | 要发送到的 SMTP 端口。 |
smtpProtocol | 字符串 | SMTP 传输协议(例如“smtps”,默认为“smtp”)。 |
smtpUsername | 字符串 | 用于对 SMTP 服务器进行身份验证所需的用户名。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
SSL | SslConfiguration | 包含 KeyStore 和 TrustStore 的配置。请参阅SSL。 |
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <SMTP name="Mail" subject="Error Log" to="[email protected]" from="[email protected]" smtpHost="localhost" smtpPort="25" bufferSize="50"> </SMTP> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Mail"/> </Root> </Loggers> </Configuration>
ScriptAppenderSelector
在构建配置时,ScriptAppenderSelector
appender 会调用一个Script
来计算 appender 名称。然后,Log4j 会使用ScriptAppenderSelector
的名称创建一个AppenderSet
下列出的 appender 名称之一。配置完成后,Log4j 会忽略ScriptAppenderSelector
。Log4j 只会从配置树中构建一个选定的 appender,并忽略其他AppenderSet
子节点。
在以下示例中,脚本返回名称“List2”。Appender 名称记录在ScriptAppenderSelector
的名称下,而不是选定 appender 的名称下,在本例中为“SelectIt”。
<Configuration status="WARN" name="ScriptAppenderSelectorExample"> <Appenders> <ScriptAppenderSelector name="SelectIt"> <Script language="JavaScript"><![CDATA[ java.lang.System.getProperty("os.name").search("Windows") > -1 ? "MyCustomWindowsAppender" : "MySyslogAppender";]]> </Script> <AppenderSet> <MyCustomWindowsAppender name="MyAppender" ... /> <SyslogAppender name="MySyslog" ... /> </AppenderSet> </ScriptAppenderSelector> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="SelectIt" /> </Root> </Loggers> </Configuration>
SocketAppender
SocketAppender
是一个 OutputStreamAppender,它将输出写入由主机和端口指定的远程目标。数据可以通过 TCP 或 UDP 发送,并且可以以任何格式发送。您可以选择使用SSL 来保护通信。请注意,TCP 和 SSL 变体将数据作为流写入套接字,并且不期望从目标目的地收到响应。由于 TCP 协议的限制,这意味着当目标服务器关闭其连接时,一些日志事件可能会继续显示为成功,直到出现关闭连接异常,导致这些事件丢失。如果需要保证传递,则必须使用需要确认的协议。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 附加器的名称。 |
host | 字符串 | 正在侦听日志事件的系统的名称或地址。此参数是必需的。如果主机名解析为多个 IP 地址,则 TCP 和 SSL 变体将在连接丢失时故障转移到下一个 IP 地址。 |
port | 整数 | 主机上正在侦听日志事件的端口。必须指定此参数。 |
protocol | 字符串 | "TCP"(默认)、"SSL" 或 "UDP"。 |
SSL | SslConfiguration | 包含 KeyStore 和 TrustStore 的配置。请参阅SSL。 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
immediateFail | 布尔值 | 设置为 true 时,日志事件不会等待尝试重新连接,如果套接字不可用,则会立即失败。 |
immediateFlush | 布尔值 | 设置为 true 时(默认值),每次写入后都会进行刷新。这将保证数据写入磁盘,但可能会影响性能。 |
bufferedIO | 布尔值 | 设置为 true 时(默认值),事件将写入缓冲区,并且当缓冲区已满或(如果 immediateFlush 设置为 true)当记录写入时,数据将写入套接字。 |
bufferSize | int | 当 bufferedIO 为 true 时,这是缓冲区大小,默认值为 8192 字节。 |
layout | Layout | 用于格式化 LogEvent 的 Layout。必需,没有默认值。从 2.9 版本开始新增,在之前的版本中,SerializedLayout 是默认值。 |
reconnectionDelayMillis | 整数 | 如果设置为大于 0 的值,则在发生错误后,SocketManager 将尝试在等待指定毫秒数后重新连接到服务器。如果重新连接失败,则会抛出异常(如果ignoreExceptions 设置为false ,则应用程序可以捕获该异常)。 |
connectTimeoutMillis | 整数 | 连接超时时间(毫秒)。默认值为 0(无限超时,如 Socket.connect() 方法)。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
这是一个不安全的 TCP 配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Socket name="socket" host="localhost" port="9500"> <JsonLayout properties="true"/> </Socket> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="socket"/> </Root> </Loggers> </Configuration>
这是一个安全的SSL配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Socket name="socket" host="localhost" port="9500"> <JsonLayout properties="true"/> <SSL> <KeyStore location="log4j2-keystore.jks" passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> <TrustStore location="truststore.jks" passwordFile="${sys:user.home}/truststore.pwd"/> </SSL> </Socket> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="socket"/> </Root> </Loggers> </Configuration>
SSL 配置
几个 appender 可以配置为使用普通网络连接或安全套接字层 (SSL) 连接。本节介绍 SSL 配置中可用的参数。
参数名称 | 类型 | 描述 |
---|---|---|
protocol | 字符串 | 要使用的 SSL 协议,如果省略则为TLS 。单个值可以启用多个协议,有关详细信息,请参阅JVM 文档。 |
KeyStore | KeyStore | 包含您的私钥和证书,并确定要发送到远程主机的身份验证凭据。 |
TrustStore | TrustStore | 包含远程对端的 CA 证书。确定是否应信任远程身份验证凭据(以及连接)。 |
verifyHostName | 布尔值 | 切换是否执行主机名验证。默认为false 。 |
KeyStore
密钥库旨在包含您的私钥和证书,并确定要发送到远程主机的身份验证凭据。
参数名称 | 类型 | 描述 |
---|---|---|
location | 字符串 | 密钥库文件的路径。 |
password | char[] | 访问密钥库的纯文本密码。不能与passwordEnvironmentVariable 或passwordFile 结合使用。 |
passwordEnvironmentVariable | 字符串 | 保存密码的环境变量的名称。不能与password 或passwordFile 结合使用。 |
passwordFile | 字符串 | 保存密码的文件的路径。不能与password 或passwordEnvironmentVariable 结合使用。 |
type | 字符串 | 可选的 KeyStore 类型,例如JKS 、PKCS12 、PKCS11 、BKS 、Windows-MY/Windows-ROOT 、KeychainStore 等。默认值为 JKS。另请参阅标准类型。 |
keyManagerFactoryAlgorithm | 字符串 | 可选的 KeyManagerFactory 算法。默认值为SunX509 。另请参阅标准算法。 |
TrustStore
信任库旨在包含您在远程方提供其证书时愿意信任的 CA 证书。确定是否应信任远程身份验证凭据(以及连接)。
在某些情况下,它们可以是同一个存储库,尽管使用不同的存储库(尤其是当它们基于文件时)通常是最佳实践。
参数名称 | 类型 | 描述 |
---|---|---|
location | 字符串 | 密钥库文件的路径。 |
password | char[] | 访问密钥库的纯文本密码。不能与passwordEnvironmentVariable 或passwordFile 结合使用。 |
passwordEnvironmentVariable | 字符串 | 保存密码的环境变量的名称。不能与password 或passwordFile 结合使用。 |
passwordFile | 字符串 | 保存密码的文件的路径。不能与password 或passwordEnvironmentVariable 结合使用。 |
type | 字符串 | 可选的 KeyStore 类型,例如JKS 、PKCS12 、PKCS11 、BKS 、Windows-MY/Windows-ROOT 、KeychainStore 等。默认值为 JKS。另请参阅标准类型。 |
trustManagerFactoryAlgorithm | 字符串 | 可选的 TrustManagerFactory 算法。默认值为SunX509 。另请参阅标准算法。 |
示例
... <SSL> <KeyStore location="log4j2-keystore.jks" passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> <TrustStore location="truststore.jks" passwordFile="${sys:user.home}/truststore.pwd"/> </SSL> ...
SyslogAppender
SyslogAppender
是一个SocketAppender
,它将输出写入由主机和端口指定的远程目标,格式符合 BSD Syslog 格式或 RFC 5424 格式。数据可以通过 TCP 或 UDP 发送。
参数名称 | 类型 | 描述 |
---|---|---|
advertise | 布尔值 | 指示 appender 是否应被宣传。 |
appName | 字符串 | 用作 RFC 5424 syslog 记录中 APP-NAME 的值。 |
charset | 字符串 | 将 syslog 字符串转换为字节数组时使用的字符集。字符串必须是有效的Charset。如果未指定,将使用默认系统字符集。 |
connectTimeoutMillis | 整数 | 连接超时时间(毫秒)。默认值为 0(无限超时,如 Socket.connect() 方法)。 |
enterpriseNumber | 整数 | IANA 企业编号,如RFC 5424中所述 |
filter | 过滤器 | 一个过滤器,用于确定是否应由此附加器处理事件。可以使用复合过滤器使用多个过滤器。 |
facility | 字符串 | 该设施用于尝试对消息进行分类。facility 选项必须设置为以下值之一:"KERN"、"USER"、"MAIL"、"DAEMON"、"AUTH"、"SYSLOG"、"LPR"、"NEWS"、"UUCP"、"CRON"、"AUTHPRIV"、"FTP"、"NTP"、"AUDIT"、"ALERT"、"CLOCK"、"LOCAL0"、"LOCAL1"、"LOCAL2"、"LOCAL3"、"LOCAL4"、"LOCAL5"、"LOCAL6" 或 "LOCAL7"。这些值可以指定为大写或小写字符。 |
format | 字符串 | 如果设置为 "RFC5424",则数据将根据 RFC 5424 进行格式化。否则,它将被格式化为 BSD Syslog 记录。请注意,尽管 BSD Syslog 记录必须不超过 1024 字节,但 SyslogLayout 不会截断它们。RFC5424Layout 也不会截断记录,因为接收方必须接受最多 2048 字节的记录,并且可能接受更长的记录。 |
host | 字符串 | 正在侦听日志事件的系统的名称或地址。此参数是必需的。 |
id | 字符串 | 根据 RFC 5424 进行格式化时使用的默认结构化数据 ID。如果 LogEvent 包含 StructuredDataMessage,则将使用 Message 中的 ID 而不是此值。 |
ignoreExceptions | 布尔值 | 默认值为 true ,导致在追加事件时遇到的异常在内部记录,然后忽略。当设置为 false 时,异常将改为传播到调用者。在将此附加器包装在 FailoverAppender 中时,必须将其设置为 false 。 |
immediateFail | 布尔值 | 设置为 true 时,日志事件不会等待尝试重新连接,如果套接字不可用,则会立即失败。 |
immediateFlush | 布尔值 | 设置为 true 时(默认值),每次写入后都会进行刷新。这将保证数据写入磁盘,但可能会影响性能。 |
includeMDC | 布尔值 | 指示是否将 ThreadContextMap 中的数据包含在 RFC 5424 Syslog 记录中。默认为 true。 |
Layout | Layout | 覆盖format 设置的自定义 Layout。 |
loggerFields | KeyValuePairs 列表 | 允许将任意 PatternLayout 模式包含为指定的 ThreadContext 字段;没有指定默认值。要使用,请包含一个>LoggerFields<嵌套元素,其中包含一个或多个>KeyValuePair<元素。每个>KeyValuePair<必须具有一个 key 属性,该属性指定用于标识 MDC 结构化数据元素中字段的键名,以及一个 value 属性,该属性指定用作值的 PatternLayout 模式。 |
mdcExcludes | 字符串 | 应从 LogEvent 中排除的 mdc 键的逗号分隔列表。这与 mdcIncludes 属性互斥。此属性仅适用于 RFC 5424 syslog 记录。 |
mdcIncludes | 字符串 | 应包含在 FlumeEvent 中的 mdc 键的逗号分隔列表。列表中未找到的 MDC 中的任何键都将被排除。此选项与 mdcExcludes 属性互斥。此属性仅适用于 RFC 5424 syslog 记录。 |
mdcRequired | 字符串 | MDC 中必须存在的 mdc 键的逗号分隔列表。如果键不存在,则会抛出 LoggingException。此属性仅适用于 RFC 5424 syslog 记录。 |
mdcPrefix | 字符串 | 应附加到每个 MDC 键的字符串,以便将其与事件属性区分开来。默认字符串为 "mdc:"。此属性仅适用于 RFC 5424 syslog 记录。 |
messageId | 字符串 | 用于 RFC 5424 syslog 记录的 MSGID 字段中的默认值。 |
name | 字符串 | 附加器的名称。 |
newLine | 布尔值 | 如果为 true,则会在 syslog 记录的末尾附加一个换行符。默认值为 false。 |
port | 整数 | 主机上正在侦听日志事件的端口。必须指定此参数。 |
protocol | 字符串 | "TCP" 或 "UDP"。此参数是必需的。 |
SSL | SslConfiguration | 包含 KeyStore 和 TrustStore 的配置。请参阅SSL。 |
reconnectionDelayMillis | 整数 | 如果设置为大于 0 的值,则在发生错误后,SocketManager 将尝试在等待指定毫秒数后重新连接到服务器。如果重新连接失败,则会抛出异常(如果ignoreExceptions 设置为false ,则应用程序可以捕获该异常)。 |
一个 syslogAppender 配置示例,该示例配置了两个SyslogAppender
,一个使用 BSD 格式,另一个使用 RFC 5424。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Syslog name="bsd" host="localhost" port="514" protocol="TCP"/> <Syslog name="RFC5424" format="RFC5424" host="localhost" port="8514" protocol="TCP" appName="MyApp" includeMDC="true" facility="LOCAL0" enterpriseNumber="18060" newLine="true" messageId="Audit" id="App"/> </Appenders> <Loggers> <Logger name="com.mycorp" level="error"> <AppenderRef ref="RFC5424"/> </Logger> <Root level="error"> <AppenderRef ref="bsd"/> </Root> </Loggers> </Configuration>
对于SSL,此 appender 将其输出写入由主机和端口指定的远程目标,通过 SSL 以符合 BSD Syslog 格式或 RFC 5424 格式的格式。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="MyApp"> <Appenders> <Syslog name="bsd" host="localhost" port="6514" protocol="SSL"> <SSL> <KeyStore location="log4j2-keystore.jks" passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> <TrustStore location="truststore.jks" passwordFile="${sys:user.home}/truststore.pwd"/> </SSL> </Syslog> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="bsd"/> </Root> </Loggers> </Configuration>
ZeroMQ/JeroMQ Appender
ZeroMQ appender 使用JeroMQ库将日志事件发送到一个或多个 ZeroMQ 端点。
这是一个简单的 JeroMQ 配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration name="JeroMQAppenderTest" status="TRACE"> <Appenders> <JeroMQ name="JeroMQAppender"> <Property name="endpoint">tcp://*:5556</Property> <Property name="endpoint">ipc://info-topic</Property> </JeroMQ> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="JeroMQAppender"/> </Root> </Loggers> </Configuration>
下表描述了所有选项。有关详细信息,请参阅 JeroMQ 和 ZeroMQ 文档。
参数名称 | 类型 | 描述 |
---|---|---|
name | 字符串 | 追加器的名称。必需。 |
Layout | layout | 用于格式化 LogEvent 的布局。如果未提供布局,则将使用默认的模式布局 "%m%n"。 |
Filters | 过滤器 | Appender 的 Filter(s)。 |
属性 | Property[] | 一个或多个名为endpoint 的属性元素。 |
ignoreExceptions | 布尔值 | 如果为真,则异常将被记录并抑制。如果为假,则错误将被记录,然后传递给应用程序。 |
亲和性 | long | ZMQ_AFFINITY 选项。默认值为 0。 |
积压 | long | ZMQ_BACKLOG 选项。默认值为 100。 |
连接时延迟附加 | 布尔值 | ZMQ_DELAY_ATTACH_ON_CONNECT 选项。默认值为 false。 |
身份 | 字节数组 | ZMQ_IDENTITY 选项。默认值为无。 |
仅 IPv4 | 布尔值 | ZMQ_IPV4ONLY 选项。默认值为 true。 |
延迟 | long | ZMQ_LINGER 选项。默认值为 -1。 |
最大消息大小 | long | ZMQ_MAXMSGSIZE 选项。默认值为 -1。 |
接收高水位 | long | ZMQ_RCVHWM 选项。默认值为 1000。 |
接收缓冲区大小 | long | ZMQ_RCVBUF 选项。默认值为 0。 |
接收超时 | int | ZMQ_RCVTIMEO 选项。默认值为 -1。 |
重新连接间隔 | long | ZMQ_RECONNECT_IVL 选项。默认值为 100。 |
重新连接间隔最大值 | long | ZMQ_RECONNECT_IVL_MAX 选项。默认值为 0。 |
发送缓冲区大小 | long | ZMQ_SNDBUF 选项。默认值为 0。 |
发送超时 | int | ZMQ_SNDTIMEO 选项。默认值为 -1。 |
发送高水位 | long | ZMQ_SNDHWM 选项。默认值为 1000。 |
TCP 保持活动 | int | ZMQ_TCP_KEEPALIVE 选项。默认值为 -1。 |
TCP 保持活动计数 | long | ZMQ_TCP_KEEPALIVE_CNT 选项。默认值为 -1。 |
TCP 保持活动空闲 | long | ZMQ_TCP_KEEPALIVE_IDLE 选项。默认值为 -1。 |
TCP 保持活动间隔 | long | ZMQ_TCP_KEEPALIVE_INTVL 选项。默认值为 -1。 |
xpub 详细 | 布尔值 | ZMQ_XPUB_VERBOSE 选项。默认值为 false。 |