appender 输出源
appender负责将LogEvents传递到它们的目的地。每个Appender都必须实现Appender接口。
大多数appender都扩展了AbstractAppender,后者增加了生命周期和可过滤的支持。生命周期允许组件在配置完成后完成初始化,并在关闭期间执行清理。
Filterable允许组件附加过滤器,在事件处理期间对其进行评估。
appender通常只负责将事件数据写入目标目的地。在大多数情况下,他们将格式化事件的责任委托给布局。
一些Appender封装了其他Appender,这样它们就可以修改LogEvent,处理Appender中的故障,根据高级过滤器标准将事件路由到下级Appender,或者提供类似的功能,但不直接格式化事件以供查看。
appender总是有一个名称,以便可以从logger引用它们。
在下面的表中,“Type”列对应于预期的Java类型。对于非jdk类,这些通常应该在Log4j Core中,除非另有说明。
支持的种类很多,节选几个重要的学习。
AsyncAppender
AsyncAppender接受对其他appender的引用,并在单独的线程上向它们写入LogEvents。
注意,写入这些appender时的异常将对应用程序隐藏。应该在它引用的appender之后配置AsyncAppender,以允许它正确关闭。
默认情况下,AsyncAppender使用java.util.concurrent.ArrayBlockingQueue,它不需要任何外部库。
请注意,多线程应用程序在使用这个appender时应该小心:
阻塞队列容易受到锁争用的影响,我们的测试表明,当更多线程并发地记录日志时,性能可能会变得更差。考虑使用无锁的异步日志记录器以获得最佳性能。
AsyncAppender Parameters
Parameter Name | Type | Description |
---|---|---|
AppenderRef | String | 要异步调用的appender的名称。可以配置多个AppenderRef元素。 |
blocking | boolean | 如果为true,则追加器将等待,直到队列中有空闲槽。如果为false,则在队列已满时将事件写入错误追加程序。默认为true。 |
shutdownTimeout | integer | 在关闭时,Appender应该等待多少毫秒来清除队列中未完成的日志事件。默认值为0,表示永远等待。 |
bufferSize | integer | 指定可以排队的事件的最大数目。默认值是1024。注意,当使用破坏者风格的BlockingQueue时,这个缓冲区的大小必须是2的幂。当应用程序的日志记录速度超过底层appender能够跟上的足够长的时间以填充队列时,该行为由AsyncQueueFullPolicy决定。 |
errorRef | String | 如果由于Appender中的错误或队列已满而无法调用任何Appender,则要调用的Appender的名称。如果没有指定,错误将被忽略。 |
filter | Filter | 一个过滤器,用于确定事件是否应由此Appender处理。使用CompositeFilter可以使用多个过滤器。name string Appender的名称。 |
ignoreExceptions | boolean | 默认值为true,导致在附加事件时遇到的异常被内部记录,然后被忽略。当设置为false时,异常将被传播给调用者。在FailoverAppender中包装这个Appender时,必须将其设置为false。 |
includeLocation | boolean | 提取位置是一个昂贵的操作(它可以使日志记录慢5 - 20倍)。为了提高性能,在向队列中添加日志事件时,默认情况下不包括位置。你可以通过设置inclelocation =”true”来改变这一点。 |
BlockingQueueFactory | BlockingQueueFactory | 该元素覆盖要使用的BlockingQueue类型。有关详细信息,请参阅下面的文档。 |
还有一些系统属性可用于维护应用程序吞吐量,即使底层appender无法跟上日志记录速率并且队列已满。请参阅系统属性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>
BlockingQueueFactory Implementations
Log4j 附带了以下实现:
Plugin Name | Description |
---|---|
ArrayBlockingQueue | 这是使用ArrayBlockingQueue的默认实现。 |
DisruptorBlockingQueue | 这使用了BlockingQueue的Conversant Disruptor实现。这个插件有一个可选属性spinPolicy,它对应于 |
JCToolsBlockingQueue | 这使用了JCTools,特别是MPSC有界无锁队列。 |
LinkedTransferQueue | 这使用了Java 7中的新实现LinkedTransferQueue。注意,这个队列不使用AsyncAppender的bufferSize配置属性,因为LinkedTransferQueue不支持最大容量。 |
ConsoleAppender
正如人们所期望的那样,ConsoleAppender将其输出写入任一 System.out 或 System.err 是默认目标。必须提供一个Layout来格式化LogEvent。
例子
<?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>
参数
Parameter Name | Type | Description |
---|---|---|
filter | Filter | 一个过滤器,用于确定事件是否应由此Appender处理。使用CompositeFilter可以使用多个过滤器。 |
layout | Layout | 用于格式化LogEvent的布局。如果没有提供布局,则使用默认的模式布局”%m%n”。 |
follow | boolean | 标识追加程序是否遵循System的重新赋值。out或System。通过系统出错。setOut或System。setErr在配置后制作。请注意,在Windows上,不能在java中使用follow属性。不能与直接连用。 |
direct | boolean | 直接写入java.io.FileDescriptor并绕过java.lang.System.out/.err。当输出重定向到文件或其他进程时,可以提供高达10倍的性能提升。不能在Windows上与简体语言一起使用。不能与follow连用。输出将不尊重java.lang.System.setOut()/. seterr(),并且可能与java.lang.System.out/的其他输出交织在一起。多线程应用程序中的错误。2.6.2以来新增。请注意,这是一个新添加的功能,到目前为止,它只在Linux和Windows上的Oracle JVM上进行了测试。 |
name | String | Appender 名称. |
ignoreExceptions | boolean | 默认值为true,导致在附加事件时遇到的异常被内部记录,然后被忽略。当设置为false时,异常将被传播给调用者。在FailoverAppender中包装这个Appender时,必须将其设置为false。 |
target | String | “SYSTEM_OUT”或”SYSTEM_ERR”。默认值为SYSTEM_OUT。 |
FailoverAppender
FailoverAppender封装了一组追加器。如果主Appender失败,将依次尝试辅助Appender,直到一个成功或没有更多的辅助Appender可尝试。
例子
<?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>
参数
Parameter Name | Type | Description |
---|---|---|
filter | Filter | 一个过滤器,用于确定事件是否应由此Appender处理。使用CompositeFilter可以使用多个过滤器。 |
primary | String | 要使用的主Appender的名称。 |
failovers | String[] | 要使用的次要appender的名称。 |
name | String | Appender的名称。 |
retryIntervalSeconds | integer | 在重试主Appender之前应该经过的秒数。默认值为60。 |
ignoreExceptions | boolean | 默认值为true,导致在附加事件时遇到的异常被内部记录,然后被忽略。当设置为false时,异常将被传播给调用者。 |
target | String | “SYSTEM_OUT”或”SYSTEM_ERR”。默认值为SYSTEM_ERR。 |
FileAppender
FileAppender是一个OutputStreamAppender,它写入fileName参数中指定的文件。
FileAppender使用FileManager(扩展了OutputStreamManager)来实际执行文件I/O。
虽然来自不同配置的文件追加器不能被共享,但如果管理器是可访问的,则文件管理器可以被共享。
例如,servlet容器中的两个web应用程序可以有自己的配置,如果Log4j在ClassLoader中,则可以安全地写入相同的文件。
例子
<?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>
参数
Parameter Name | Type | Description |
---|---|---|
append | boolean | 当为true(默认值)时,记录将被附加到文件的末尾。当设置为false时,文件将在写入新记录之前被清除。 |
bufferedIO | boolean | 当true为默认值时,记录将被写入缓冲区,当缓冲区满时数据将被写入磁盘,或者,如果设置了immediateFlush,记录将被写入磁盘。文件锁定不能与bufferedIO一起使用。性能测试表明,即使启用了immediateFlush,使用缓冲I/O也能显著提高性能。 |
bufferSize | int | 当bufferedIO为true时,这是缓冲区大小,默认值为8192字节。 |
createOnDemand | boolean | appender按需创建文件。只有当日志事件通过所有筛选器并路由到此附加程序时,附加程序才会创建文件。默认为false。 |
filter | Filter | 一个过滤器,用于确定事件是否应由此Appender处理。使用CompositeFilter可以使用多个过滤器。 |
fileName | String | 要写入的文件的名称。如果该文件或其任何父目录不存在,则将创建它们。 |
immediateFlush | boolean | 当设置为true(默认值)时,每次写入之后都会进行一次刷新。这将保证数据被传递给操作系统进行写入;它不能保证数据确实写入了物理设备(如磁盘驱动器)。请注意,如果将此标志设置为false,并且日志记录活动稀疏,则数据最终到达操作系统时可能会有不确定的延迟,因为它被保存在缓冲区中。这可能会导致令人惊讶的结果,例如在写入日志后,日志没有立即出现在文件的尾部输出中。每次写入后刷新仅在将此appender与同步日志记录器一起使用时才有用。异步记录器和appender将在一批事件结束时自动刷新,即使immediateFlush设置为false。这也保证了数据被传递给操作系统,但效率更高。 |
layout | Layout | 用于格式化LogEvent的布局。如果没有提供布局,则使用默认的模式布局”%m%n”。 |
locking | boolean | 当设置为true时,只有在持有文件锁的情况下才会发生I/O操作,允许多个jvm中的fileappeners(可能还有多个主机)同时写入同一个文件。这将显著影响性能,因此应谨慎使用。此外,在许多系统上,文件锁是“建议的”,这意味着其他应用程序可以在不获取锁的情况下对文件执行操作。默认值为false。 |
name | String | appender 名称 |
ignoreExceptions | boolean | 默认值为true,导致在附加事件时遇到的异常被内部记录,然后被忽略。当设置为false时,异常将被传播给调用者。在FailoverAppender中包装这个Appender时,必须将其设置为false。 |
filePermissions | String | 在创建文件时应用POSIX格式的文件属性权限。底层文件系统应支持POSIX文件属性视图。例如:rw——-或rw-rw-rw-等等… |
fileOwner | String | 文件所有者,以便在创建文件时定义。由于安全原因,更改文件的所有者可能会受到限制,并且会抛出操作不允许的IOException。如果_POSIX_CHOWN_RESTRICTED对path有效,则只有具有与文件的用户ID相等的有效用户ID或具有适当特权的进程才能更改文件的所有权。底层文件系统应支持文件所有者属性视图。 |
fileGroup | String | 文件组,以便在创建文件时定义。底层文件系统应支持POSIX文件属性视图。 |
MemoryMappedFileAppender
自2.1以来新增。请注意,这是一个新添加的功能,尽管它已经在几个平台上进行了测试,但它没有其他文件追加器那么多的记录。
MemoryMappedFileAppender将指定文件的一部分映射到内存中,并将日志事件写入该内存,依赖于操作系统的虚拟内存管理器将更改同步到存储设备。
使用内存映射文件的主要好处是I/O性能。这个附加程序可以简单地修改程序的本地内存,而不是通过系统调用来写入磁盘,这要快几个数量级。
此外,在大多数操作系统中,映射的内存区域实际上是内核的页缓存(文件缓存),这意味着不需要在用户空间中创建副本。
(TODO:将此appender的性能与RandomAccessFileAppender和FileAppender进行比较的性能测试。)
将文件区域映射到内存中会有一些开销,特别是非常大的区域(0.5 gb或更多)。默认区域大小为32 MB,这应该在重新映射操作的频率和持续时间之间取得合理的平衡。
(待办事项:重新映射各种尺寸的性能测试。)
与FileAppender和RandomAccessFileAppender类似,MemoryMappedFileAppender使用MemoryMappedFileManager来实际执行文件I/O。
虽然来自不同配置的MemoryMappedFileAppender不能被共享,但如果管理器是可访问的,memorymappedfilemanager可以被共享。
例如,servlet容器中的两个web应用程序可以有自己的配置,如果Log4j在ClassLoader中,则可以安全地写入相同的文件。
配置
<?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>
RandomAccessFileAppender
RandomAccessFileAppender与标准FileAppender类似,除了它总是被缓冲(这不能被关闭),并且在内部它使用ByteBuffer + RandomAccessFile而不是BufferedOutputStream。
在我们的测量中,与“bufferedIO=true”的FileAppender相比,我们看到了20-200%的性能提升。
与FileAppender类似,RandomAccessFileAppender使用RandomAccessFileManager来实际执行文件I/O。
虽然来自不同配置的RandomAccessFileAppender不能被共享,但如果Manager是可访问的,则randomaccessfilemanager可以被共享。
例如,servlet容器中的两个web应用程序可以有自己的配置,如果Log4j在ClassLoader中,则可以安全地写入相同的文件。
例子
<?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>
RollingFileAppender
RollingFileAppender是一个OutputStreamAppender,它写入fileName参数中指定的文件,并根据TriggeringPolicy和RolloverPolicy滚动文件。
RollingFileAppender使用RollingFileManager(它扩展了OutputStreamManager)来实际执行文件I/O并执行滚转。
虽然来自不同配置的rolloverfileappeners不能被共享,但如果管理器是可访问的,rollingfilemanager可以被共享。例如,servlet容器中的两个web应用程序可以有自己的配置,如果Log4j在ClassLoader中,则可以安全地写入相同的文件。
RollingFileAppender需要一个TriggeringPolicy和一个RolloverStrategy。触发策略确定是否应该执行翻转,而RolloverStrategy定义应该如何进行翻转。如果没有配置RolloverStrategy, RollingFileAppender将使用DefaultRolloverStrategy。从log4j-2.5开始,可以在DefaultRolloverStrategy中配置自定义删除操作,以便在滚动时运行。从2.8开始,如果没有配置文件名,那么DirectWriteRolloverStrategy将被使用,而不是defaultroloverstrategy。自log4j-2.9以来,可以在DefaultRolloverStrategy中配置自定义POSIX文件属性视图操作,以便在滚动时运行,如果没有定义,则将应用从RollingFileAppender继承的POSIX文件属性视图。
RollingFileAppender不支持文件锁定。
例子
下面是一个示例配置,它使用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>
下面是一个示例配置,它使用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>
RollingRandomAccessFileAppender
RollingRandomAccessFileAppender与标准的RollingFileAppender类似,除了它总是被缓冲(这不能被关闭),并且在内部它使用ByteBuffer + RandomAccessFile而不是BufferedOutputStream。
在我们的测量中,与“bufferedIO=true”的RollingFileAppender相比,我们看到了20-200%的性能提升。RollingRandomAccessFileAppender写入fileName参数中指定的文件,并根据TriggeringPolicy和RolloverPolicy滚动文件。与RollingFileAppender类似,RollingRandomAccessFileAppender使用RollingRandomAccessFileManager来实际执行文件I/O并执行滚转。
虽然来自不同配置的RollingRandomAccessFileAppender不能被共享,但如果管理器是可访问的,则rollingrandomaccessfilemanager可以被共享。例如,servlet容器中的两个web应用程序可以有自己的配置,如果Log4j在ClassLoader中,则可以安全地写入相同的文件。
RollingRandomAccessFileAppender需要一个TriggeringPolicy和一个RolloverStrategy。
触发策略确定是否应该执行翻转,而RolloverStrategy定义应该如何进行翻转。如果没有配置RolloverStrategy, RollingRandomAccessFileAppender将使用DefaultRolloverStrategy。
从log4j-2.5开始,可以在DefaultRolloverStrategy中配置自定义删除操作,以便在滚动时运行。
RollingRandomAccessFileAppender不支持文件锁定。
例子
下面是一个示例配置,它使用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启动时运行脚本,也可以在为日志事件选择路由时运行脚本。
例子
在这个例子中,脚本将“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>
RewriteAppender
RewriteAppender允许在LogEvent被另一个Appender处理之前对其进行操作。
这可用于屏蔽密码等敏感信息,或向每个事件注入信息。
RewriteAppender必须配置RewritePolicy。RewriteAppender应该在它引用的任何appender之后配置,以允许它正确关闭。
参数
Parameter Name | Type | Description |
---|---|---|
AppenderRef | String | 在操纵LogEvent之后要调用的appeners的名称。可以配置多个AppenderRef元素。 |
filter | Filter | 一个过滤器,用于确定事件是否应由此Appender处理。使用CompositeFilter可以使用多个过滤器。 |
name | String | 名称 |
rewritePolicy | RewritePolicy | 将操作LogEvent的RewritePolicy。 |
ignoreExceptions | boolean | 默认值为true,导致在附加事件时遇到的异常被内部记录,然后被忽略。当设置为false时,异常将被传播给调用者。在FailoverAppender中包装这个Appender时,必须将其设置为false。 |
例子
<?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>
JDBCAppender
JDBC Appender使用标准JDBC将日志事件写入关系数据库表。它可以配置为使用JNDI数据源或自定义工厂方法获得JDBC连接。
使用数据源配置的JDBC Appender需要JNDI支持,因此在2.17.1版本中,除非使用log4j2,否则此Appender将无法工作。enableJndiJdbc=true被配置为系统属性或环境变量。请参阅enableJndiJdbc系统属性。
无论采用哪种方法,都必须由连接池提供支持。否则,日志记录性能将受到很大影响。如果已配置的JDBC驱动程序支持批处理语句,并且将bufferSize配置为正数,则将对日志事件进行批处理。请注意,从Log4j 2.8开始,有两种方法可以将日志事件配置为列映射:原始的ColumnConfig样式只允许字符串和时间戳,新的ColumnMapping插件使用Log4j的内置类型转换来允许更多的数据类型(这与Cassandra Appender中的插件相同)。
为了在开发过程中快速起步,使用基于JNDI的连接源的替代方法是使用非池化的DriverManager连接源。此连接源使用JDBC连接字符串、用户名和密码。您还可以选择使用属性。
例子
<?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>
SMTPAppender
当发生特定的日志事件(通常是错误或致命错误)时发送电子邮件。
在此电子邮件中传递的日志事件数量取决于BufferSize选项的值。
SMTPAppender在其循环缓冲区中只保留最后一个BufferSize日志事件。
这使内存需求保持在合理的水平,同时仍然提供有用的应用程序上下文。缓冲区中的所有事件都包含在电子邮件中。缓冲区将包含在触发电子邮件的事件之前从TRACE到WARN级别的最近事件。
默认行为是在记录ERROR或更严重的事件时触发发送电子邮件,并将其格式化为HTML。可以通过在Appender上设置一个或多个过滤器来控制何时发送电子邮件的情况。与其他Appender一样,可以通过为Appender指定Layout来控制格式。
例子
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp">
<Appenders>
<SMTP name="Mail" subject="Error Log" to="errors@logging.apache.org" from="test@logging.apache.org"
smtpHost="localhost" smtpPort="25" bufferSize="50">
</SMTP>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Mail"/>
</Root>
</Loggers>
</Configuration>
其他的
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中的时间戳列类型)。
例子:
<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>
JMS Appender
JMS Appender将格式化的日志事件发送到JMS Destination。
JMS Appender需要JNDI支持,因此在2.17.0版本中,除非log4j2,否则这个Appender将无法工作。enableJndiJms=true被配置为系统属性或环境变量。请参阅enableJndiJms系统属性。
注意,在Log4j 2.0中,这个appender被拆分为一个JMSQueueAppender和一个JMSTopicAppender。
从Log4j 2.1开始,这些Appender被组合到JMS Appender中,它对队列和主题没有区别。
但是,为2.0编写的使用 <JMS/>
或 <JMSTopic/>
元素的配置将继续使用新的 <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 MapMessages映射到JMS。MapMessages,使用 <MessageLayout />
设置appender的布局到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 Persistence API 2.1将日志事件写入关系数据库表。它要求API和提供程序实现位于类路径上。
它还需要一个经过修饰的实体,该实体被配置为持久化到所需的表。实体应该扩展org.apache.logging.log4j.core.appender.db.jpa.BasicLogEventEntity(如果您主要想使用默认映射)并至少提供一个@Id属性,或者org.apache.logging.log4j.core.appender.db.jpa.AbstractLogEventWrapperEntity(如果您想显著定制映射)。有关这两个类的更多信息,请参阅Javadoc。您还可以参考这两个类的源代码,作为如何实现实体的示例。
例子
下面是JPAAppender的一个示例配置。第一个XML示例是Log4j配置文件,第二个是persistence.xml文件。这里假设使用EclipseLink,但任何JPA 2.1或更高版本的提供程序都可以。出于两个原因,您应该始终为日志记录创建单独的持久性单元。
首先,<shared-cache-mode>
必须设置为“NONE”,这在正常的JPA使用中通常是不需要的。此外,出于性能原因,日志实体应该在其自己的持久单元中与所有其他实体隔离,并且应该使用非jta数据源。
注意,您的持久性单元还必须包含所有org.apache.log .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>
HttpAppender
HttpAppender通过HTTP发送日志事件。必须提供一个Layout来格式化LogEvent。
将根据布局设置Content-Type标头。可以使用嵌入的Property元素指定其他标头。
将等待服务器的响应,如果没有收到2xx响应则抛出错误。
使用HttpURLConnection实现。
例子
<?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记录发送。
例子
<?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>
NoSQLAppender
NoSQLAppender使用内部轻量级提供程序接口将日志事件写入NoSQL数据库。目前已有MongoDB和Apache CouchDB的提供程序实现,编写自定义提供程序非常简单。
例子
ScriptAppenderSelector
当构建配置时,ScriptAppenderSelector追加程序调用Script来计算追加程序名称。然后Log4j使用ScriptAppenderSelector的名称创建AppenderSet下列出的一个appender。配置之后,Log4j忽略ScriptAppenderSelector。Log4j只构建从配置树中选择的一个appender,而忽略其他AppenderSet子节点。
在下面的示例中,脚本返回名称“List2”。附加程序名称记录在ScriptAppenderSelector的名称下,而不是所选附加程序的名称,在本例中为“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协议的限制,这意味着当目标服务器关闭其连接时,一些日志事件可能继续看起来成功,直到引发关闭的连接异常,导致这些事件丢失。如果需要保证传递,则必须使用需要确认的协议。
例子
This is an unsecured TCP configuration:
<?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>
SyslogAppender
SyslogAppender是一个SocketAppender,它以符合BSD Syslog格式或RFC 5424格式的格式将其输出写入由主机和端口指定的远程目的地。数据可以通过TCP或UDP发送。
例子
一个示例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>
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>
参考资料
https://logging.apache.org/log4j/2.x/manual/appenders.html
- appender 输出源
- AsyncAppender
- ConsoleAppender
- FailoverAppender
- FileAppender
- MemoryMappedFileAppender
- RandomAccessFileAppender
- RollingFileAppender
- RollingRandomAccessFileAppender
- RoutingAppender
- RewriteAppender
- JDBCAppender
- SMTPAppender
- 其他的
- JMS Appender
- JPAAppender
- HttpAppender
- KafkaAppender
- NoSQLAppender
- ScriptAppenderSelector
- SocketAppender
- SyslogAppender
- ZeroMQ / JeroMQ Appender
- 参考资料