Open4

ECS で Firelens / FluentbitでログファイルをS3/CloudWatchに転送する

takostakos

[PARSER] で大事なこと

  • ミリ秒付きの日時をパースする場合は Time_Format %Y-%m-%dT%H:%M:%S.%L%z
    • %L にたどり着くのに時間かかった
  • 日時が 2023-09-11 10:00:03 みたいなTimezone情報を含まない日時でかつJSTの場合は Time_Offset +0900 をつけること
    • CloudWatchLogsは2時間より未来のログを保存してくれないけど、デフォだとUTCな感じなのでCloudWatchLogsに転送されるけど保存されないっていう謎挙動でドハマリした
  • 転送されるログのペイロードから日時情報が欠落するが TimeKeep On をつけることで維持されるようになる
takostakos

転送がうまくいかないときはとりあえず debug ログを出力してみる

[SERVICE]
    Log_Level debug
takostakos

ログレベルで転送しないようにする場合は [FILTER]grep を利用する

https://docs.fluentbit.io/manual/pipeline/filters/grep

[FILTER]
    Name grep
    Match *
    Exclude level DEBUG

Exclude の値(↑の例だと DEBUG ) はケースセンシティブ
level[PARSER] で指定してるフィールド名なので状況にあわせて要調整

takostakos

laravel.log 用の [PARSER] は一旦以下のような感じになった。

[PARSER]
    Name laravel_log_firstline
    Format regex
    Regex /^\[(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (?<env>\w+).(?<level>\w+): (?<message>.*)$/
    Time_Key time
    Time_Format %Y-%m-%d %H:%M:%S
    Time_Offset +0900
    Time_Keep On
  • Parserはたぶんコンテナイメージに埋め込む必要がある気がする
  • laravel.log はスタックトレースが吐かれるのでマルチラインパーサーとして機能させる必要がある
  • 「1行目の書式」をこんな感じで定義できるので、なんかいい感じにする
  • Laravel側の設定によるけど Time_Offset は吐かれるログのタイムゾーンに合わせて定義しないと、S3転送はともかくCloudWatchLogs転送で困るので注意
  • Time_Keep は趣味もあるけどCloudWatchLogs転送時の見やすさを優先して含めたほうが良い気がする

対応する [INPUT] とかは以下みたいな感じ。

[INPUT]
    Name tail
    Tag laravel.log
    Path /path/to/laravel.log
    Multiline On
    Parser_Firstline laravel_log_firstline

[FILTER]
    Name grep
    Match laravel.log
    Exclude level DEBUG

[OUTPUT]
    Name cloudwatch_logs
    Match laravel.log
    region ap-northeast-1
    log_group_name /Your/CloudWatchLogs/GroupName
    log_stream_prefix your-custom-prefix-
    auto_create_group On

[OUTPUT]
    Name s3
    Match laravel.log
    region ap-northeast-1
    bucket YOUR_S3_BUCKET_NAME
    total_file_size 1M
    upload_timeout 1m
    use_put_object On
  • Tag はドット使えるからファイル名指定するのがわかりやすい気がしてる
  • [INPUT]MultilineOn にして Parser_Firstline にさっき作ったパーサーを指定してあげる
  • デバッグログは転送したくなかったから [FILTER]Exclude 指定する
  • OUTPUT 2つとも指定しておくことで、 CloudWatchLogs と S3 の両方に転送される