🚀
FireLens(Fluent Bit v2.1) で Tomcat(SpringBoot) からのログを処理する
ECSを試しているついでにFireLensでのログ収集基盤構築までやってみたのでその記録です。
アプリケーション自体はSpringBootで作っており、デフォルトのTomcatをwebサーバーとしています。
やりたいこと
- エラーログを分ける
- /helthcheckへのアクセスログは無視する
- アクセスログはS3とCloudWatchの2つに流す
最終的にCloudWatchに出力するストリームは以下画像のようになりました。
1.FireLensから出力されるログを整形する
Firelensからは以下のような形式でログが返される。
条件判定に使いたいのは、logに含まれる内容である。
{
"container_id": "",
"container_name": "",
"ecs_cluster": "",
"ecs_task_arn": "",
"ecs_task_definition": "",
"log": "0.0.0.000 - - [10/Feb/2024:00:00:00 +0000] \"GET /helthcheck HTTP/1.1\" 200 2",
"source": "stdout"
}
Fluent BitのStream ProcessorのSQLで処理できるようにするにはとりあえずJSON形式にする必要がある。
今回は以下Githubにあるサンプルをそのまま使い、Parserにて事前処理する。
[PARSER]
Name apache #ただの名前
Format regex
Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
すると以下のようなJSONに整形される
{
"code": "200",
"container_id": "",
"container_name": "",
"ecs_cluster": "",
"ecs_task_arn": "",
"ecs_task_definition": "",
"host": "0.0.0.000",
"method": "GET",
"path": "/helthcheck",
"size": "",
"source": "stdout",
"user": "-"
}
2.Stream Processorで処理する
上記JSON形式に整理できればあとは、SQLで処理できる。
- FireLensから出力されるイベントorレコードは、
<コンテナ名>-firelens-<コンテナID>
というタグが付けられている。このタグがついているものだけ処理するように絞り込む。 - 1つ目は、/helthcheckだけ除外するクエリ
- 2つ目は、エラーコードのものだけ、error-logタグのついたStreamとして再生成するクエリ
stream_processor.conf
[STREAM_TASK]
Name access
Exec CREATE STREAM access WITH (tag='access-log') AS SELECT * FROM TAG:'*-firelens-*' WHERE path <> '/helthcheck';
[STREAM_TASK]
Name error
Exec CREATE STREAM error WITH (tag='error-log') AS SELECT * FROM TAG:'*-firelens-*' WHERE code >= 400 AND code < 600;
3.メインの.confを作成
1.と2.で作成したファイルを両方読み込んでいる。
処理の順番としては以下になる。
- FILTERでparser.confで設定したapatch parser(ただの名前)によってログを整形
- stream_processor.confにて、access-logとerror-logタグを持つストリームを作成
- 再度、access-logとerror-logストリームはINPUT->OUTPUTまで流される
- [OUTPUT]によって出力
fluent-bit-custom.conf
[SERVICE]
Parsers_File /fluent-bit/parser.conf
Streams_File /fluent-bit/stream_processor.conf
[FILTER]
Name parser
Match *
Key_Name log
Parser apache
Reserve_Data True
[OUTPUT]
Name cloudwatch
Match access-log
region ${AWS_REGION}
log_group_name ${LOG_GROUP_NAME}
log_stream_prefix from-fluentbit/
auto_create_group true
[OUTPUT]
Name cloudwatch
Match error-log
region ${AWS_REGION}
log_group_name ${LOG_GROUP_NAME}
log_stream_prefix from-fluentbit/
auto_create_group true
[OUTPUT]
Name s3
Match access-log
region ${AWS_REGION}
bucket ${LOG_BUCKET_NAME}
total_file_size 1M
upload_timeout 1m
FireLensの挙動について
FireLensを使うと、標準出力へのログはFluentd Docker ログドライバーを介して Unix ソケット経由で FireLens コンテナに送信される。
Fluentd Docker ログドライバーについて
- 実は、
container_id,container_name,source
についてはこのログドライバーによって付与されており、ログがlog
をキーにして格納されるのもこのドライバーが行なっている。 - このドライバーはTCP,unixドメインsocket通信の2つをサポートしている。
-
fluentdhost:24224
orunix:///path/to/fluentd.sock
-
参照記事
以下AWSの記事が最も参考になった。
Discussion