ロギングサブシステム AMQP アペンダ

フレームワークは、いくつかの一般的なログサブシステム用のログアペンダーを提供します。

  • logback (Spring AMQP バージョン 1.4 以降)

  • log4j2 (Spring AMQP バージョン 1.6 以降)

アペンダーは、ロギングサブシステムの通常のメカニズムを使用して構成されます。使用可能なプロパティは、次のセクションで指定されています。

共通プロパティ

次のプロパティは、すべてのアペンダーで使用できます。

表 1: 一般的なアペンダープロパティ
プロパティ デフォルト 説明
 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 と 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 property of log messages.

 contentEncoding

content-encoding property of log messages.

 declareExchange
 false

Whether or not to declare the configured exchange when this appender starts. See also durable and autoDelete.

 durable
 true

When declareExchange is true, the durable flag is set to this value.

 autoDelete
 false

When declareExchange is true, the auto-delete flag is set to this value.

 charset
 null

Character set to use when converting String to byte[]. Default: null (the system default charset is used). If the character set is unsupported on the current platform, we fall back to using the system character set.

 deliveryMode
 PERSISTENT

PERSISTENT or NON_PERSISTENT to determine whether or not RabbitMQ should persist the messages.

 generateId
 false

Used to determine whether the messageId property is set to a unique value.

 clientConnectionProperties
 null

A comma-delimited list of key:value pairs for custom client properties to the RabbitMQ connection.

 addMdcAsHeaders
 true

MDC properties were always added into RabbitMQ message headers until this property was introduced. It can lead to issues for big MDC as while RabbitMQ has limited buffer size for all headers and this buffer is pretty small. This property was introduced to avoid issues in cases of big MDC. By default this value set to true for backward compatibility. The false turns off serialization MDC into headers. Please note, the JsonLayout adds MDC into the message by default.

Log4j 2 Appender

The following example shows how to configure a 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>

Starting with versions 1.6.10 and 1.7.3, by default, the log4j2 appender publishes the messages to RabbitMQ on the calling thread. This is because Log4j 2 does not, by default, create thread-safe events. If the broker is down, the maxSenderRetries is used to retry, with no delay between retries. If you wish to restore the previous behavior of publishing the messages on separate threads (senderPoolSize), you can set the async property to true. However, you also need to configure Log4j 2 to use the DefaultLogEventFactory instead of the ReusableLogEventFactory. One way to do that is to set the system property -Dlog4j2.enable.threadlocals=false. If you use asynchronous publishing with the ReusableLogEventFactory, events have a high likelihood of being corrupted due to cross-talk.

Logback Appender

The following example shows how to configure a 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>

Starting with version 1.7.1, the Logback AmqpAppender provides an includeCallerData option, which is false by default. Extracting caller data can be rather expensive, because the log event has to create a throwable and inspect it to determine the calling location. Therefore, by default, caller data associated with an event is not extracted when the event is added to the event queue. You can configure the appender to include caller data by setting the includeCallerData property to true.

Starting with version 2.0.0, the Logback AmqpAppender supports Logback encoders (英語) with the encoder option. The encoder and layout options are mutually exclusive.

Customizing the Messages

By default, AMQP appenders populate the following message properties:

  • deliveryMode

  • contentType

  • contentEncoding、構成されている場合

  • messageIdgenerateId が構成されている場合

  • ログイベントの 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);
		}
	}

}

クライアントプロパティのカスタマイズ

文字列プロパティまたはより複雑なプロパティを追加することで、カスタムクライアントプロパティを追加できます。

単純な文字列プロパティ

各アペンダーは、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 管理 UI に表示されます。

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 に追加できます。

前の例に示されているような文字列プロパティの場合、前の手法を使用できます。サブクラスを使用すると、より豊富なプロパティを追加できます (Map または数値プロパティの追加など)。

カスタムキューの実装を提供する

AmqpAppenders は BlockingQueue を使用して、ロギングイベントを RabbitMQ に非同期的に発行します。デフォルトでは、LinkedBlockingQueue が使用されます。ただし、任意の種類のカスタム BlockingQueue 実装を提供できます。

次の例は、Logback でこれを行う方法を示しています。

public class MyEnhancedAppender extends AmqpAppender {

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

}

次の例に示すように、Log4j 2 アペンダーは BlockingQueueFactory [Apache] (英語) の使用をサポートします。

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