事象
fluent-plugin-cloudwatch-logs を使用して複数の AWS EC2 インスタンスから CloudWatch Logs の同一 LogStream へ転送していた際、下記の様な WARNING によりログ転送が行われませんでした。
2016-05-14 02:08:24 +0000 [warn]: temporarily failed to flush the buffer. next_retry=2016-05-14 02:42:45 +0000 error_class="Aws::CloudWatchLogs::Errors::InvalidSequenceTokenException" error="The given sequenceToken is invalid. The next expected sequenceToken is: 99999999999999999999999999999999999999999999999999999999" plugin_id="object:XXXXXXXXX1dc"
原因
仕様のようで、複数の転送元から同一 LogStream への転送時は発生するとのことです。
回避策
LogStream を各インスタンスで固有にします。
source 部例
例として nginx のログを取得します。
<source>
@type tail
format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<forwarder>[^\"]*)")?/
time_format %d/%b/%Y:%H:%M:%S %z
tag nginx.access
path /var/log/nginx/access.log
</source>
<source>
@type tail
format /^(?<time>\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) \[(?<log_level>\w+)\] (?<pid>\d+).(?<tid>\d+): (?<message>.*)$/
tag nginx.error
path /var/log/nginx/error.log
</source>
インスタンスIDの取得
LogStream を固有にできれば良いのでIDやホスト名等を付与します。今回は InstanceId を付けました。
- fluent-plugin-ec2-metadata で InstanceId を取得
- 出力タグに InstanceId 付与
<match nginx.*>
type ec2_metadata
output_tag ${instance_id}.${tag}
<record>
instance_id ${instance_id}
hostname ${tagset_name}
</record>
</match>
ログストリームへインスタンスIDを付与
- fluent-plugin-forest で fluent-plugin-cloudwatch-logs の log_stream_name に InstanceId を付与
<match *.nginx.*>
type forest
subtype cloudwatch_logs
<template>
log_group_name ${tag_parts[1]}-${tag_parts[2]}
log_stream_name ${tag_parts[0]}
region ap-northeast-1
auto_create_stream true
</template>
</match>
CloudWatch Logs エージェントを使用する場合等、インスタンスIDでログストリームを設定する事が多いですが、
fluent-plugin-cloudwatch-logs で実装していてログが転送されていない場合は確認してみると良いかもしれません。