Logging Subsystem AMQP Appenders

该框架为一些流行的日志子系统提供日志记录追加程序:

  • logback(自 Spring AMQP 的 1.4 版本起)

  • log4j2(自 Spring AMQP 1.6 版起)

可以通过使用日志子系统的正常机制来配置追加程序,可用的属性在以下章节中指定。

Common properties

所有追加程序都提供以下属性:

Table 1. Common Appender Properties
Property Default Description
  exchangeName
  logs

要发布日志事件的兑换名称。

  exchangeType
  topic

将日志事件发布到的交换机类型 - 仅在追加器声明交换机时需要。请参见`declareExchange`。

  routingKeyPattern
  %c.%p

用于生成路由密钥的日志子系统模式格式。

  applicationId

应用程序 ID - 如果模式包含 %X{applicationId},则将其添加到路由密钥。

  senderPoolSize
  2

用于发布日志事件的线程数。

  maxSenderRetries
  30

如果代理不可用或出现其他错误,重试发送消息的次数。重试按照以下方式延迟:N ^ log(N),其中`N`是重试次数。

  addresses

以下形式的分隔符地址逗号分隔列表: host:port[,host:port]* - 覆盖 host`和 `port

  host
  localhost

要连接到的 RabbitMQ 主机。

  port
  5672

要连接到的 RabbitMQ 端口。

  virtualHost
  /

要连接到的 RabbitMQ 虚拟主机。

  username
  guest

连接时要使用的 RabbitMQ 用户。

  password
  guest

此用户的 RabbitMQ 密码。

  useSsl
  false

是否对 RabbitMQ 连接使用 SSL。请参阅 RabbitConnectionFactoryBean and Configuring SSL

  verifyHostname
  true

为 TLS 连接启用服务器主机名验证。请参阅 RabbitConnectionFactoryBean and Configuring SSL

  sslAlgorithm
  null

使用的 SSL 算法。

  sslPropertiesLocation
  null

SSL 属性文件的位置。

  keyStore
  null

Location of the keystore.

  keyStorePassphrase
  null

Passphrase for the keystore.

  keyStoreType
  JKS

The keystore type.

  trustStore
  null

Location of the truststore.

  trustStorePassphrase
  null

Passphrase for the truststore.

  trustStoreType
  JKS

The truststore type.

  saslConfig
 null(应用 RabbitMQ 客户端默认设置)

saslConfig - 请参阅 RabbitUtils.stringToSaslConfig 的 javadoc,了解有效值。

  contentType
  text/plain

日志消息的 content-type 属性。

  contentEncoding

日志消息的 content-encoding 属性。

  declareExchange
  false

在该追加器启动后,是否声明配置的 exchange。请另见 durableautoDelete

  durable
  true

declareExchangetrue 时,durable 标记设置为该值。

  autoDelete
  false

declareExchangetrue 时,auto-delete 标记设置为该值。

  charset
  null

将 `String`转换为 `byte[]`时使用的字符集。默认值:null(使用系统默认字符集)。如果当前平台不支持此字符集,我们将回退到使用系统字符集。

  deliveryMode
  PERSISTENT

PERSISTENTNON_PERSISTENT 用于确定 RabbitMQ 是否应永久保存消息。

  generateId
  false

用于确定 messageId 属性是否设置为唯一值。

  clientConnectionProperties
  null

以逗号分隔的 key:value 对列表,用于自定义客户端属性到 RabbitMQ 连接。

  addMdcAsHeaders
  true

直到引入这个属性,MDC 属性始终被添加到 RabbitMQ 消息头中。由于 RabbitMQ 为所有标头限制了缓冲区大小,并且该缓冲区非常小,这可能导致较大的 MDC 出现问题。引入这个属性是为了避免在大型 MDC 的情况下出现问题。默认情况下,该值设置为 true 以保持向后兼容性。false 关闭将 MDC 序列化到标头。请注意,JsonLayout 默认情况下将 MDC 添加到消息中。

Log4j 2 Appender

以下示例展示了如何配置一个 Log4j 2 追加程序:

<Appenders>
    ...
    <RabbitMQ name="rabbitmq"
        addresses="foo:5672,bar:5672" user="guest" password="guest" virtualHost="/"
        exchange="log4j2" exchangeType="topic" declareExchange="true" durable="true" autoDelete="false"
        applicationId="myAppId" routingKeyPattern="%X{applicationId}.%c.%p"
        contentType="text/plain" contentEncoding="UTF-8" generateId="true" deliveryMode="NON_PERSISTENT"
        charset="UTF-8"
        senderPoolSize="3" maxSenderRetries="5"
        addMdcAsHeaders="false">
    </RabbitMQ>
</Appenders>

从版本 1.6.10 和 1.7.3 开始,默认情况下,log4j2 追加程序在调用线程上发布消息到 RabbitMQ。这是因为 Log4j 2 默认情况下不创建线程安全的事件。如果代理已关闭,maxSenderRetries 用于重试,在重试之间没有延迟。如果您希望恢复在单独线程 (senderPoolSize) 上发布消息的以前行为,您可以将 async 属性设置为 true。但是,您还需要将 Log4j 2 配置为使用 DefaultLogEventFactory 而不是 ReusableLogEventFactory。一种方法是设置系统属性 -Dlog4j2.enable.threadlocals=false。如果您在使用 ReusableLogEventFactory 进行异步发布,由于串扰,事件极有可能损坏。

Logback Appender

以下示例展示了如何配置一个 logback 追加程序:

<appender name="AMQP" class="org.springframework.amqp.rabbit.logback.AmqpAppender">
    <layout>
        <pattern><![CDATA[ %d %p %t [%c] - <%m>%n ]]></pattern>
    </layout>
    <addresses>foo:5672,bar:5672</addresses>
    <abbreviation>36</abbreviation>
    <includeCallerData>false</includeCallerData>
    <applicationId>myApplication</applicationId>
    <routingKeyPattern>%property{applicationId}.%c.%p</routingKeyPattern>
    <generateId>true</generateId>
    <charset>UTF-8</charset>
    <durable>false</durable>
    <deliveryMode>NON_PERSISTENT</deliveryMode>
    <declareExchange>true</declareExchange>
    <addMdcAsHeaders>false</addMdcAsHeaders>
</appender>

从版本 1.7.1 开始,Logback AmqpAppender 提供一个 includeCallerData 选项,默认值为 false。提取调用程序数据可能会相当昂贵,因为日志事件必须创建一个可抛出对象并检查它来确定调用位置。因此,在将事件添加到事件队列时,默认情况下不会提取与事件关联的调用程序数据。您可以通过将 includeCallerData 属性设置为 true 来配置追加程序以包含调用程序数据。

从 2.0.0 版本开始,Logback AmqpAppender 使用 encoder 选项来支持 Logback encodersencoderlayout 选项是互斥的。

Customizing the Messages

默认情况下,AMQP 追加程序填充以下消息属性:

  • deliveryMode

  • contentType

  • contentEncoding, if configured

  • messageId,如果 generateId 已配置

  • timestamp 的日志事件

  • appId,如果 applicationId 已配置

此外,它们还会使用以下值填充头字段:

  • categoryName 的日志事件

  • 日志事件级别

  • thread:发生日志事件的线程名称

  • 日志事件调用的堆栈跟踪位置

  • 所有 MDC 属性的副本(除非 addMdcAsHeaders 已设置为 false

每个追加程序都可以被子类化,让您在发布之前修改消息。以下示例展示了如何定制日志消息:

public class MyEnhancedAppender extends AmqpAppender {

    @Override
    public Message postProcessMessageBeforeSend(Message message, Event event) {
        message.getMessageProperties().setHeader("foo", "bar");
        return message;
    }

}

从 2.2.4 开始,log4j2 AmqpAppender 可以使用 @PluginBuilderFactory 扩展,还可以扩展 AmqpAppender.Builder

@Plugin(name = "MyEnhancedAppender", category = "Core", elementType = "appender", printObject = true)
public class MyEnhancedAppender extends AmqpAppender {

	public MyEnhancedAppender(String name, Filter filter, Layout<? extends Serializable> layout,
			boolean ignoreExceptions, AmqpManager manager, BlockingQueue<Event> eventQueue, String foo, String bar) {
		super(name, filter, layout, ignoreExceptions, manager, eventQueue);

	@Override
	public Message postProcessMessageBeforeSend(Message message, Event event) {
			message.getMessageProperties().setHeader("foo", "bar");
		return message;
	}

	@PluginBuilderFactory
	public static Builder newBuilder() {
		return new Builder();
	}

	protected static class Builder extends AmqpAppender.Builder {

		@Override
		protected AmqpAppender buildInstance(String name, Filter filter, Layout<? extends Serializable> layout,
				boolean ignoreExceptions, AmqpManager manager, BlockingQueue<Event> eventQueue) {
			return new MyEnhancedAppender(name, filter, layout, ignoreExceptions, manager, eventQueue);
		}
	}

}

Customizing the Client Properties

您可以通过添加字符串属性或更复杂属性来添加自定义客户端属性。

Simple String Properties

每个追加程序都支持向 RabbitMQ 连接添加客户端属性。

以下示例展示了如何为 logback 添加一个自定义客户端属性:

<appender name="AMQP" ...>
    ...
    <clientConnectionProperties>thing1:thing2,cat:hat</clientConnectionProperties>
    ...
</appender>
log4j2
<Appenders>
    ...
    <RabbitMQ name="rabbitmq"
        ...
        clientConnectionProperties="thing1:thing2,cat:hat"
        ...
    </RabbitMQ>
</Appenders>

这些属性是一个由 key:value 对组成的逗号分隔列表。键和值不能包含逗号或冒号。

在查看连接时,这些属性会显示在 RabbitMQ 管理员界面上。

Advanced Technique for Logback

您可以对 Logback 追加程序进行子类化。这样做可以让您在建立连接之前修改客户端连接属性。以下示例展示了如何执行此操作:

public class MyEnhancedAppender extends AmqpAppender {

    private String thing1;

    @Override
    protected void updateConnectionClientProperties(Map<String, Object> clientProperties) {
        clientProperties.put("thing1", this.thing1);
    }

    public void setThing1(String thing1) {
        this.thing1 = thing1;
    }

}

然后,您可以将 <thing1>thing2</thing1> 添加到 logback.xml。

对于如上例所示的 String 属性,可以使用前面的技术。子类允许添加更丰富的属性(例如添加 Map 或数字属性)。

Providing a Custom Queue Implementation

AmqpAppenders 使用 BlockingQueue 异步将日志事件发布到 RabbitMQ。默认情况下,使用了 LinkedBlockingQueue。但是,您可以提供任何类型的自定义 BlockingQueue 实现。

以下示例展示了 Logback 的使用方法:

public class MyEnhancedAppender extends AmqpAppender {

    @Override
    protected BlockingQueue<Event> createEventQueue() {
        return new ArrayBlockingQueue();
    }

}

Log4j 2 编写器支持使用 BlockingQueueFactory,如下例所示:

<Appenders>
    ...
    <RabbitMQ name="rabbitmq"
              bufferSize="10" ... >
        <ArrayBlockingQueue/>
    </RabbitMQ>
</Appenders>