AWS FirelensでCloudWatch Logsにログを送信する

FirelensでFluentBitを用いてCloudWatch Logsにログを送る場合にはFluentBitのプラグインが利用可能です。

利用方法は簡単でOUTPUTセクションでNameにcloudwatchを指定して必要なパラメータを設定すればいいです。

[OUTPUT]
    Name cloudwatch
    Match   *
    region us-east-1
    log_group_name fluent-bit-cloudwatch-$(uuid)-$(tag)
    log_stream_name from-fluent-bit-$(pam['item2']['subitem'])-$(ecs_task_id)-$(ecs_cluster)
    auto_create_group true
https://github.com/aws/amazon-cloudwatch-logs-for-fluent-bit

ただ、aws-for-fluent-bit 2.29.0を利用した際に下記エラーに遭遇しました。

plugin 'cloudwatch' failed to initialize

調査したところcloudwatchというプラグインは旧プラグインで新しいプラグインはcloudwatch_logsという名称で提供されているようです。

cloudwatch_logsに変えるだけでOKとならない部分があります。
log_group_nameやlog_stream_nameで変数展開する機能が新プラグインでは下位互換性がない状態です。

READMEに旧プラグインについて記載があります。

Do you plan to deprecate this older plugin?
At this time, we do not. This plugin will continue to be supported. It contains features that have not been ported to the higher performance version. Specifically, the feature for templating of log group name and streams with ECS Metadata or values in the logs. While simple templating support now exists in the high performance plugin, it does not have all of the features of the plugin in this repo. Some users will continue to need the features in this repo.

https://github.com/aws/amazon-cloudwatch-logs-for-fluent-bit

ロググループ名、ログストリーム名についてECSのメタデータやログ内のデータを使ってテンプレート化する機能が含まれていないとのこと。
このテンプレート化という部分にはリンクが貼られていて遷移先にかかれているのが

Templating Log Group and Stream Names
A template in the form of $(variable) can be set in log_group_name or log_stream_name. variable can be a map key name in the log message. To access sub-values in the map use the form $(variable['subkey']). Also, it can be replaced with special values to insert the tag, ECS metadata or a random string in the name.

https://github.com/aws/amazon-cloudwatch-logs-for-fluent-bit

まさに前述したサンプルで記述のあった内容です。

今回、ログストリーム名をログ内の値を使った名前を設定したかったので直撃しました。
cloudwatch_logsプラグインでどうにかやる方法が確認できたので記載していきます。

log_stream_prefixというパラメータがあって指定した文字列をログストリーム名のprefixにつけてくれます。

このパラメータを指定するとログストリーム名はprefix+tagで作成されることがわかりました。
つまり、必要な値があればtagの時点でつけてしまえばいいのだと考えました。

FILTERセクションでrewrite_tagをするときに正規表現で必要な値をキャプチャしてnew_tagにつけることによって実現できました。

簡単な例

[FILTER]
  Name rewrite_tag
  Match *-firelens-*
  Rule $log (.*) new_tag.$1 false