日誌子系統 AMQP Appender

該框架為一些流行的日誌子系統提供了日誌 Appender

  • logback(自 Spring AMQP 1.4 版本開始)

  • log4j2(自 Spring AMQP 1.6 版本開始)

可以透過日誌子系統的常規機制配置這些 Appender,可用屬性在以下章節中指定。

通用屬性

所有 Appender 均提供以下屬性

表 1. 通用 Appender 屬性
屬性 預設值 描述
 exchangeName
 logs

釋出日誌事件的目標交換器名稱。

 exchangeType
 topic

釋出日誌事件的目標交換器型別 — 僅當 Appender 宣告交換器時需要。請參閱 declareExchange

 routingKeyPattern
 %c.%p

用於生成路由鍵的日誌子系統模式格式。

 applicationId

應用 ID — 如果模式包含 %X{applicationId},則新增到路由鍵中。

 senderPoolSize
 2

用於釋出日誌事件的執行緒數。

 maxSenderRetries
 30

如果 Broker 不可用或存在其他錯誤時,重試傳送訊息的次數。重試延遲如下:N ^ log(N),其中 N 是重試次數。

 addresses

Broker 地址的逗號分隔列表,格式如下:host:port[,host:port]* - 覆蓋 hostport

 host
 localhost

要連線的 RabbitMQ 主機。

 port
 5672

要連線的 RabbitMQ 埠。

 virtualHost
 /

要連線的 RabbitMQ 虛擬主機。

 username
 guest

連線時使用的 RabbitMQ 使用者。

 password
 guest

此使用者的 RabbitMQ 密碼。

 useSsl
 false

是否對 RabbitMQ 連線使用 SSL。請參閱 RabbitConnectionFactoryBean 和配置 SSL

 verifyHostname
 true

啟用 TLS 連線的伺服器主機名驗證。請參閱 RabbitConnectionFactoryBean 和配置 SSL

 sslAlgorithm
 null

使用的 SSL 演算法。

 sslPropertiesLocation
 null

SSL 屬性檔案的位置。

 keyStore
 null

金鑰庫的位置。

 keyStorePassphrase
 null

金鑰庫的密碼。

 keyStoreType
 JKS

金鑰庫型別。

 trustStore
 null

信任庫的位置。

 trustStorePassphrase
 null

信任庫的密碼。

 trustStoreType
 JKS

信任庫型別。

 saslConfig
 null (RabbitMQ client default applies)

saslConfig - 有效值請參閱 RabbitUtils.stringToSaslConfig 的 javadoc。

 contentType
 text/plain

日誌訊息的 content-type 屬性。

 contentEncoding

日誌訊息的 content-encoding 屬性。

 declareExchange
 false

此 Appender 啟動時是否宣告配置的交換器。另請參閱 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

RabbitMQ 連線的自定義客戶端屬性的逗號分隔 key:value 對列表。

 addMdcAsHeaders
 true

在引入此屬性之前,MDC 屬性總是被新增到 RabbitMQ 訊息頭中。對於大的 MDC,這可能會導致問題,因為 RabbitMQ 對所有訊息頭的大小有限制,並且緩衝區相當小。引入此屬性是為了避免大的 MDC 導致的問題。出於向後相容性考慮,此值預設為 true。設定為 false 將關閉 MDC 序列化到訊息頭中。請注意,JsonLayout 預設會將 MDC 新增到訊息體中。

Log4j 2 Appender

以下示例展示瞭如何配置 Log4j 2 Appender

<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 Appender 在呼叫執行緒上將訊息釋出到 RabbitMQ。這是因為 Log4j 2 預設不建立執行緒安全事件。如果 Broker 關閉,將使用 maxSenderRetries 進行重試,重試之間沒有延遲。如果您希望恢復先前在單獨執行緒 (senderPoolSize) 上釋出訊息的行為,可以將 async 屬性設定為 true。但是,您還需要配置 Log4j 2 使用 DefaultLogEventFactory 而不是 ReusableLogEventFactory。一種方法是設定系統屬性 -Dlog4j2.enable.threadlocals=false。如果您使用 ReusableLogEventFactory 進行非同步釋出,由於交叉干擾,事件很有可能損壞。

Logback Appender

以下示例展示瞭如何配置 logback Appender

<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。提取呼叫者資料可能相當昂貴,因為日誌事件必須建立一個 throwable 並檢查它以確定呼叫位置。因此,預設情況下,將事件新增到事件佇列時不會提取與事件關聯的呼叫者資料。您可以透過將 includeCallerData 屬性設定為 true 來配置 Appender 以包含呼叫者資料。

從 2.0.0 版本開始,Logback 的 AmqpAppender 支援 Logback encoder,使用 encoder 選項。encoderlayout 選項是互斥的。

自定義訊息

預設情況下,AMQP Appender 會填充以下訊息屬性

  • deliveryMode

  • contentType

  • contentEncoding(如果已配置)

  • messageId(如果 generateId 已配置)

  • 日誌事件的 timestamp

  • appId(如果 applicationId 已配置)

此外,它們還會填充包含以下值的訊息頭

  • 日誌事件的 categoryName

  • 日誌事件的級別

  • thread:日誌事件發生的執行緒名稱

  • 日誌事件呼叫的堆疊跟蹤位置

  • 所有 MDC 屬性的副本(除非 addMdcAsHeaders 設定為 false

每個 Appender 都可以被繼承,以便您在釋出之前修改訊息。以下示例展示瞭如何自定義日誌訊息

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);
		}
	}

}

自定義客戶端屬性

您可以透過新增字串屬性或更復雜的屬性來新增自定義客戶端屬性。

簡單字串屬性

每個 Appender 都支援向 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 Admin UI 上。

Logback 的高階技巧

您可以繼承 Logback Appender。這樣做可以在建立連線之前修改客戶端連線屬性。以下示例展示瞭如何實現

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 中。

對於前面示例中所示的字串屬性,可以使用前一種技術。子類允許新增更豐富的屬性(例如新增 Map 或數字屬性)。

提供自定義佇列實現

AmqpAppender 使用 BlockingQueue 將日誌事件非同步釋出到 RabbitMQ。預設情況下,使用 LinkedBlockingQueue。但是,您可以提供任何自定義的 BlockingQueue 實現。

以下示例展示瞭如何為 Logback 實現

public class MyEnhancedAppender extends AmqpAppender {

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

}

Log4j 2 Appender 支援使用 BlockingQueueFactory,如下例所示

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