介绍
appender主要负责将日志事件传递到目的地。每个Appender都必须实现Appender接口。如果你想要支持生命周期、过滤器等功能,那么可以实现AbstractAppender类。
下面介绍一下有哪些appender。
AsyncAppender
异步输出日志,默认使用 java.util.concurrent.ArrayBlockingQueue 来实现的,不需要其他的外部库,这个配置在多线程的情况下需要小心,可能会出现锁竞争,如果在多线程下,可以使用Disruptor库(一个无锁的线程间通信库,而不是队列,从而产生更高的吞吐量和更低的延迟),可以使用<asyncRoot>或者<asyncLogger>来进行配置。
AsyncAppender的参数:
参数名 | 类型 | 描述 |
---|---|---|
AppenderRef | String | 需要加入异步输出的appender,可以配置多个元素。 |
blocking | boolean | 如果是true,输出将等待直到队列中有空的slot;如果设置为false,当队列满的时候,将用error appender来输出日志,默认值为true。 |
shutdownTimeout | integer | 在关闭时,Appender应该等待多少毫秒来刷新队列中未完成的日志事件。默认值是0,意味着永远等待。 |
bufferSize | integer | 指定可以排队处理的最大事件数量。默认是1024。注意:如果使用了disruptor的BlockingQueue,那么必须设置为2的幂等。 |
errorRef | String | 指定错误输出,如果没有配置,那么会忽略错误。 |
filter | Filter | 配置拦截器,如果配置多个,可以使用 Filters标签。 |
name | String | appender的名称 |
ignoreExceptions | boolean | 默认是true,错误将被忽略,如果设置为false,异常被传递给调用者。在用FailoverAppender包装这个Appender时,必须将其设置为false。 |
includeLocation | boolean | 输出文件路径,性能会下降5-20倍,默认是关闭的。 |
BlockingQueueFactory | BlockingQueueFactory | 指定需要使用的BlockingQueue。包括:ArrayBlockingQueue、DisruptorBlockingQueue、JCToolsBlockingQueue、LinkedTransferQueue |
示例:
<Async name="Async" bufferSize="262144">
<AppenderRef ref="List"/>
<LinkedTransferQueue/>
</Async>
CassandraAppender
输出日志到Apache Cassandra数据库。
示例:
<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>
表结构
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
输出日志到控制台,标签里必须配置Layout。
ConsoleAppender参数:
参数名 | 类型 | 描述 |
---|---|---|
filter | Filter | 配置拦截器,如果配置多个,可以使用 Filters标签。 |
name | String | appender的名称 |
ignoreExceptions | boolean | 默认是true,错误将被忽略,如果设置为false,异常被传递给调用者。在用FailoverAppender包装这个Appender时,必须将其设置为false。 |
layout | Layout | 对日志事件格式化,如果没有提供布局,将使用“%m%n”的默认布局。 |
target | String | 可以使用"SYSTEM_OUT" 或者 "SYSTEM_ERR",默认是"SYSTEM_OUT" |
示例:
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
FailoverAppender
appender的包装,优先执行配置了primary的appender,如果失败,按顺序执行配置了failovers的appender,直到执行成功为止。
FailoverAppender参数:
参数名 | 类型 | 描述 |
---|---|---|
filter | Filter | 配置拦截器,如果配置多个,可以使用 Filters标签。 |
name | String | appender的名称 |
ignoreExceptions | boolean | 默认是true,错误将被忽略,如果设置为false,异常被传递给调用者。在用FailoverAppender包装这个Appender时,必须将其设置为false。 |
target | String | 可以使用"SYSTEM_OUT" 或者 "SYSTEM_ERR",默认是"SYSTEM_OUT" |
primary | String | 设置为主appender |
failovers | String[] | 设置辅助appender |
retryIntervalSeconds | integer | 默认是60秒。多少秒之后对主appender进行重试。 |
示例:
<Failover name="Failover" primary="RollingFile">
<Failovers>
<AppenderRef ref="Console"/>
</Failovers>
</Failover>
FileAppender
输出日志文件。实际是使用FileManager(实现OutputStreamManager)去生成文件。
FileAppender参数:
参数名 | 类型 | 描述 |
---|---|---|
filter | Filter | 配置拦截器,如果配置多个,可以使用 Filters标签。 |
name | String | appender的名称 |
ignoreExceptions | boolean | 默认是true,错误将被忽略,如果设置为false,异常被传递给调用者。在用FailoverAppender包装这个Appender时,必须将其设置为false。 |
append | boolean | 默认为true,追加到文件后面,设置为false,新日志被写之前会清掉原来的内容。 |
bufferedIO | boolean | 默认为true,记录将被写入缓冲区,数据将在缓冲区写满时写入磁盘,如果设置了immediateFlush,则在写入记录时写入磁盘。性能测试表明,使用缓冲I/O可以显著提高性能,即使启用了immediateFlush。 |
bufferSize | int | 缓存区大小,默认为8192 字节。 |
createOnDemand | boolean | 按需创建文件,只有当日志事件通过所有过滤器并路由到这个appender时,appender才会创建文件。默认值为false。 |
fileName | String | 需要写入的文件名,如果文件或者目录不存在,那么将创建该文件或者目录。 |
immediateFlush | boolean | 默认为true,每次写入都会刷新。这将确保数据被写入磁盘,但是会影响一定的性能。异步日志记录器和appender将在一批事件结束时自动刷新,即使immediateFlush设置为false。这也保证了数据被写入磁盘,但是效率更高。 |
layout | Layout | 对日志事件格式化,如果没有提供布局,将使用“%m%n”的默认布局。 |
locking | boolean | 默认是false,设置为true,表示多个虚拟机或者多个应用去写同一个文件时,会加锁。这会影响性能。 |
filePermissions | String | 创建文件时应用POSIX格式的文件属性权限。基础文件系统应支持POSIX文件属性视图。例子:rw——或者rw-rw-rw- |
fileOwner | String | 创建文件时定义文件所有者。 |
fileGroup | String | 创建文件时定义的文件组。 |
示例:
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
FlumeAppender
把日志传输到Apache Flume(Flume是一种分布式的、可靠的、可用的服务,用于有效地收集、聚合和移动大量日志数据)系统里,进行日志展示。
示例:
<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>
<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>
<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>
JDBCAppender
使用标准JDBC将日志事件写入关系数据库表。
示例:
<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>
JMS Appender
发送日志到JMS服务。
示例:
<JMS name="jmsQueue" destinationBindingName="MyQueue"
factoryBindingName="MyQueueConnectionFactory">
<JsonLayout properties="true"/>
</JMS>
JPAAppender
使用JPA把日志输出到数据库。
示例:
<JPA name="databaseAppender" persistenceUnitName="loggingPersistenceUnit"
entityClassName="com.example.logging.JpaLogEntity" />
HttpAppender
通过Http发送日志。
示例:
<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>
KafkaAppender
把日志发送到kafka里。
示例:
<Kafka name="Kafka" topic="log-test">
<PatternLayout pattern="%date %message"/>
<Property name="bootstrap.servers">localhost:9092</Property>
</Kafka>
MemoryMappedFileAppender
MemoryMappedFileAppender将指定文件的一部分映射到内存中,并将日志事件写到该内存中,这依赖于操作系统的虚拟内存管理器将更改同步到存储设备。使用内存可以提供I/O性能。
示例:
<MemoryMappedFile name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</MemoryMappedFile>
NoSQLAppender
输出日志到Nosql数据库中。
示例:
集成MongoDb
<NoSql name="databaseAppender">
<MongoDb2 databaseName="applicationDb" collectionName="applicationLog" server="mongo.example.org"
username="loggingUser" password="abc123" />
</NoSql>
<NoSql name="databaseAppender">
<MongoDb3 databaseName="applicationDb" collectionName="applicationLog" server="mongo.example.org"
username="loggingUser" password="abc123" />
</NoSql>
集成Apache CouchDB
<NoSql name="databaseAppender">
<CouchDb databaseName="applicationDb" protocol="https" server="couch.example.org"
username="loggingUser" password="abc123" />
</NoSql>
RandomAccessFileAppender
跟FileAppender类似,但是他总是被缓存。在内部他使用ByteBuffer + RandomAccessFile来代替BufferedOutputStream。性能比配置了bufferedIO的FileAppender高出20-200%。
示例:
<RandomAccessFile name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</RandomAccessFile>
RewriteAppender
RewriteAppender允许在LogEvent被另一个Appender处理之前对其进行操作。他可以屏蔽敏感信息,如密码;或将信息注入每个事件。RewriteAppender必须配置RewritePolicy。RewriteAppender应该在任何appender引用之后配置,以允许它正确地关闭。
示例:
<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>
RollingFileAppender
RollingFileAppender是一个OutputStreamAppender,它写入文件名参数中指定的文件,并根据TriggeringPolicy和RolloverPolicy将文件进行切分。RollingFileAppender使用RollingFileManager(它扩展了OutputStreamManager)来实际执行文件I/O并执行切分。
示例:
<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>
RollingRandomAccessFileAppender
与RollingFileAppender类似,只是他总是使用缓存,内部使用ByteBuffer + RandomAccessFile来代替BufferedOutputStream。性能有很大的提升。
示例:
<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>
RoutingAppender
经过计算决定要使用哪个Appender。目标Appender可以是以前配置的Appender,可以通过其名称引用它,也可以根据需要动态创建Appender。
示例:
<Routing name="Routing">
<Script name="RoutingInit" language="JavaScript"><![CDATA[
importPackage(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>
SMTPAppender
日志以邮件的形式进行输出,通常是对错误或者异常进行发送。示例
示例:
<SMTP name="Mail" subject="Error Log" to="errors@logging.apache.org" from="test@logging.apache.org"
smtpHost="localhost" smtpPort="25" bufferSize="50">
</SMTP>
SocketAppender
通过host和port来输出日志。可以通过TCP或者UDP来发送。
示例:
<Socket name="socket" host="localhost" port="9500">
<JsonLayout properties="true"/>
</Socket>
<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>
SyslogAppender
跟SocketAppender类似,但是他是以BSD Syslog格式或RFC 5424格式输出。
示例:
<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"/>
ZeroMQ/JeroMQ Appender
把日志输出到JeroMQ里。
示例:
<JeroMQ name="JeroMQAppender">
<Property name="endpoint">tcp://*:5556</Property>
<Property name="endpoint">ipc://info-topic</Property>
</JeroMQ>
注意:本文归作者所有,未经作者允许,不得转载