ログ出力について考えたので、まとめてみました。
Twelve-Factor App
ざっくり言うと、
「ログは標準出力に出すと良いよ。」
しかし、ログをファイルに書き出したりする場合、環境によってはログの肥大化が問題になる。
ログの肥大化が問題になる場合、ログをローテートするのが良いが、標準出力のものをファイルに書き出す場合、うまいことやらないとロストしたり、そもそもローテート出来なかったりするのでどうしようか?というのがお題。
標準出力に時間を出すワンライナーで考える
/bin/sh -c 'while true;do date;sleep 1; done'
↑のワンライナーの標準出力を、ロスト無くロートテートすることを考えてみる。
ログの肥大化を考えない場合、下記で終了となる。
/bin/sh -c 'while true;do date;sleep 1; done' >> /tmp/hoge.log 2>&1
しかし、本番環境ではログ量が多かったりするので、やりたいことを下記に列挙する。
やりたいこと
- ログファイルの肥大化を防ぐため、ログローテートが出来ること
- ログ出力した情報にロストが無いこと(全部出力されること)
- cloudのオートスケーリング機能を使うと縮小時にログが失われるため、ログをどこかに集めたい
- デイリーでログローテートしたい(日付が変わったらローテートする)
- ログ処理にあまりサーバリソースを割きたくない(低コストでやりたい)
cloudの部分だけ僕の都合ですが、ログを集めたいという要件はcloudじゃなくてもあるはず。
環境
- オープンクラウド使う
- linuxOS上で動くシステム
- Webサーバ
ログをファイルに出力する場合のローテートについて
下記を見ると全体的に書いてあって、今回の話とかぶる部分も多いが、わかりやすい記事なので共有。
上記リンクの引用
ちゃんとローテートをしたい場合は以下のいずれかにすることが考えられます。
・ファイルに書き込む度にファイルをopenして書き込み後にcloseする
・ファイル名が変更されたタイミングを教えてもらい、元のファイル名でopenし直す
・ファイル名が変更されたタイミングを自力で検知して、元のファイル名でopenし直す
つまり、お題のワンライナーだと再起動する以外、ローテート不可能となる。
しかし、実際には「お題のワンライナー」Webサーバが動く。
Webサーバの場合、ログローテートのために再起動は辛いので、選択肢としては下記となる。
- Webサーバでログをローテートする(12factorから外れる)
- Webサーバに元のファイル名でopenし直す処理を入れる(これも微妙に12factorから外れる)
- ログを管理するプログラムを作って標準出力をそのプログラムに渡す
このうち、2だと日またぎでローテートした場合、標準出力しか見ていないので、少しだけ次の日のログが出てしまう場合がある。
3の場合は日付でマッチングしてローテートなど、小細工すれば分けられるが、サーバの処理コストが掛かる。
ファイルに出力する場合は、12factorから外れるが、1が良いかと思う。
ログをファイルに出力しない
- Webサーバの標準出力をfluentdなどのログ収集エージェントに渡す(ファイルに書かない)
- 標準出力をログ収集エージェントが用意したunix domain socketに書き込む
やりたいこと で書いたものを全部満たす場合、1か2の方法になる。
ディスク不良なども考慮すると、メモリで完結する1の方法がベスト。
まとめ
ログの出力は、標準出力とログ収集エージェントを組み合わせるのが良さそう。