FirelensでCloudWatch Logsにログ出力する際、特定JSONキーだけを出力する

2021.11.29

こんにちは、岩城です。

小ネタです。

Firelens(Fluent Bit)を使ってCloudWatch Logにログ出力すると、アクセスログやアプリケーションのログだけ構わないのに、コンテナIDやECSタスクの情報などの情報も一緒にJSON形式出力されて見辛いと感じるケースがあります。

そんな時は、Fluent Bitの設定で特定のJSONキーの値のみを出力させるようにしましょう。

どういうことか

Fluent Bitの設定を以下のようにしたとします。

[OUTPUT]
    Name cloudwatch_logs
    Match *
    region ap-northeast-1
    log_group_name /ecs/logs/hello-world-from-ecs-service
    log_stream_prefix from-fluentbit-
    auto_create_group true

東京リージョンのCloudWatch Logsにある/ecs/logs/hello-world-from-ecs-clusterというロググループにfrom-fluentbit-から始まるログストリームでログ出力します。

設定ファイルの設定について、もう少し詳しく知りたい方は以下エントリをご確認ください。とても分かりやすくまとまっています。

本題にもどります。

Firelensにより出力されるログ形式はデフォルトでJSON形式であり、本エントリ冒頭にあるとおり、コンテナやECSに関する情報が含まれます。

{
    "container_id": "03c8dd594afa490bab06c3d791fec382-2254804424",
    "container_name": "hello-world-from-ecs-nginx",
    "source": "stdout",
    "log": "xxx.xxx.xxx.xxx - - [29/Nov/2021:07:20:58 +0000] \"GET / HTTP/1.1\" 200 64 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"",
    "ecs_cluster": "hello-world-from-ecs-cluster",
    "ecs_task_arn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task/hello-world-from-ecs-cluster/03c8dd594afa490bab06c3d791fec382",
    "ecs_task_definition": "hello-world-from-ecs-task-definition:24"
}

これに関してはログだけを見た時、どのECSサービス、ECSタスク、コンテナから出力されたログか分からないので、情報として含まれることには意味があります。

ただし、CloudWatch Logsに出力させる場合、ロググループ名にECSサービス名を含めたり、ログストリーム名にECSタスクIDやコンテナ名が含めたりできるので、実際のログには不要だとするケースがあったりします。

そんな時、Fluent Bitの設定で特定JSONキーを指定して、アクセスログやアプリケーションログだけをCloudWatch Logsに出力させることができます。

特定JSONキーの値だけを出力させる

特定JSONキーの値だけを出力させるには、Fluent Bitの設定ファイルに1行付け足すだけです。

今回はlogキーだけを出力させたいのでlog_key logとします。

[OUTPUT]
    Name cloudwatch_logs
    Match *
    region ap-northeast-1
    log_group_name /ecs/logs/hello-world-from-ecs-cluster
    log_stream_prefix from-fluentbit-
    log_key log
    auto_create_group true

この状態でログ出力すると、logキーの中身だけが出力されるようになります。

logキーの値のみを指定してS3にログ出力する時は注意が必要

Firelensでは、Kinesis Data Firehoseを介してS3にログ出力することも可能です。

こちらもlogキーのみを指定してS3にログ出力できますが注意が必要です。

[OUTPUT]
    Name kinesis_firehose
    Match *
    region ap-northeast-1
    log_key log
    delivery_stream ecs-delivery-stream

CloudWatch Logsの場合はロググループ名やログストリーム名にECSサービス名やコンテナ名、タスクIDを含められましたが、S3の場合は以下のようなフォルダ構成でログ出力されます。

ログの中身はこんな感じ。

xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:54 +0000] \"GET /favicon.ico HTTP/1.1\" 404 555 \"http://54.178.60.86/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"
xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:53 +0000] \"GET / HTTP/1.1\" 200 64 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"
xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:54 +0000] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"

以上より、ログだけあっても、どのECSサービス、コンテナ、タスクから出力されたログか分からなくなるため注意が必要です。

個人的にFirelensでS3にログ出力させる場合は、特定のJSONキーを指定せずに各種情報を含めた方が良いと感じました。

おわりに

本エントリがどなたかのお役に立てれば幸いです。