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