いつもアプリケーションの開発ばかりで、まじめに監視系を考えたことがなかったので、
fluentdを中心にした監視系を作ってみた。
ツッコミ大歓迎です。アチラコチラの資料を参考にしつつ作ったので、オカシイところがあれば是非ともコメント下さいませ。
前提
- 複数台のアプリケーションサーバ
- 一台のログ収集サーバ
- ログにはエラーログとアクセスログの大きく2種類を用意する
- エラーログは更に複数のレベルでファイル単位にわかれている
- fatal
- error
- warn
- アプリケーションサーバとログ収集サーバは同一ネットワーク上にある
やりたいこと
メールで来ても絶対に気がつかない自信がある。
異常の側から教えてくれる仕組みを目指す。
- fatalログが出た場合は、電話による通知を行う
- 全てのエラーログはchatツールに出力する
- ログのバックアップ
- ログの分析・可視化
この記事では1, 2, 3についてまとめる。
構築
fluentdのインストール
公式のドキュメントが一番わかり易い。
Installation | Fluentd
ログの送信側
既にログをJSONでファイルに吐き出していたのでtailする。
サンプルログ。仮にこういうログだったとする。
{"name":"applicationX","hostname":"localhost","req":{"method":"GET","url":"/","ua":"Mozilla/5.0 ... "},"res":{"statusCode":200},"error":"", "time":"2015-02-26T08:23:28.998Z"}
/etc/td-agent/td-agent.conf
<source>
type tail
path <PATH/TO/LOG>
pos_file <PATH/TO/POSFILE>
tag app.access
format json
include_time_key true
include_tag_key true
time_key sacrifice # avoid overwrite <time> field
</source>
<source>
type tail
path <PATH/TO/LOG>
pos_file <PATH/TO/POSFILE>
tag app.fatal
format json
include_time_key true
include_tag_key true
time_key sacrifice # avoid overwrite <time> field
</source>
# 以下、error, warn, debugそれぞれ<source> ... </source>
<match *.**>
type forward
heartbeat_type tcp
<server>
host <YOUR LOG SERVER>
</server>
</match>
これで
2015-02-26 17:23:28 +0900 app.access: {"name":"applicationX","hostname":"localhost","req":{"method":"GET","url":"/","ua":"Mozilla/5.0 ... "},"res":{"statusCode":200},"time":"2015-02-26T08:23:28.998Z"}
# 構造:time tag record
という内容のログが送信される
time_key
ログにtimeという要素があるので、これでアクセス時刻別に処理しようと思っていたが、
fluentdを通した時点でなくなっていた。なので、time_keyで存在しない要素を指定して要素の削除を回避している。
heartbeat_type
デフォルトではUDPの24224を使って死活管理をしている。
udbポートを開けたくなかったので、ハートビートもtcpで行うように変更。
tagについて
fluentdはピリオドで区切ると扱うのが楽なのでピリオド区切り。
ログの受信側
$ sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-forest # td-agent.confを構造化して書くため
$ sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-twilio # 電話
$ sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-hipchat # chat通知
$ sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-s3 # S3にバックアップ
/etc/td-agent/td-agent.conf
<source>
type forward
port 24224
</source>
<match app.access>
type copy
<store>
type stdout # debug用 /var/log/td-agent/td-agent.logに流れる
</store>
<store>
type s3
aws_key_id "#{ENV['AWS_ACCESS_KEY_ID']}"
aws_sec_key "#{ENV['AWS_SECRET_KEY']}"
s3_bucket <AWS S3 BUCKET NAME>
s3_region ap-northeast-1
path app/access/
buffer_path /var/log/td-agent/buffer/s3_app_access
time_slice_format %Y-%m-%d/%H
time_slice_wait 10m
</store>
</match>
<match app.*>
type forest
subtype copy
<template>
<store>
type s3
aws_key_id "#{ENV['AWS_ACCESS_KEY_ID']}"
aws_sec_key "#{ENV['AWS_SECRET_KEY']}"
s3_bucket <AWS S3 BUCKET NAME>
s3_region ap-northeast-1
path ${tag_parts[0]}/${tag_parts[1]}/ # app/fatal/, app/error/, ...
buffer_path /var/log/td-agent/buffer/s3_${tag_parts[0]}_${tag_parts[1]}
time_slice_format %Y-%m-%d/%H
time_slice_wait 10m
</store>
<store>
type hipchat
api_token "#{ENV['HIPCHAT_API_TOKEN']}"
default_room <YOUR CHAT ROOM>
default_from fluentd
default_color yellow
default_notify 1
default_format text # メンションを含めたい場合はtextである必要がある。HipChatのAPI仕様
default_timeout 3
key_name error
</store>
</template>
<case app.fatal>
<store>
type twilio
account_sid "#{ENV['TWILIO_ACCOUNT_SID']}"
auth_token "#{ENV['TWILIO_AUTH_TOKEN']}"
from_number +810000000000 # twilioで取得した番号
default_number +811111111111, +812222222222 # 電話を受け取りたい番号
</store>
</case>
</match>
アクセスログとエラーログでmatchを分けたがまとめられるような気もする・・・。
S3の記述が重複しておりもやもや。
=> 続・fluentdでつくる監視系 - Qiitaで対応
AWSのアクセストークン
S3のフルパーミッションが付与されているトークン。
EC2インスタンスかつIAM Roleが付与されている場合は省略可
hipchatのkey_name
ここで指定した要素をJSONから取り出して通知する。
なお、渡せるのは文字列のみ。構造を持った要素(例えば、res)を渡すと無視される。
エラーの詳細を全部流したいので、対策を考え中。
続・fluentdでつくる監視系 - Qiitaで解決
twilio
messageという要素があると、読み上げてくれる。
今はmessageという要素が無いため電話をとった瞬間に切れる。
続・fluentdでつくる監視系 - Qiitaで解決
その他
- 同一ネットワーク上にあるのでforwardで転送したが、間にインターネットを挟む場合はsecure_forwardがいいと思う。
- アプリケーションログ以外、サーバのシステム監視はまた今度
- fluentd側でlog_levelを設定したらもっとスッキリかけるかもしれない
まとめ
最低限、fatalは電話、エラー系のログはchatにポスト、ログはバックアップ、ができた。
参考
fluentdの簡単な使い方、設定方法一覧 - Hive Color
fluentd で json に time を残したい - Qiita
日本語読み上げ対応。FluentdからTwilioの電話APIを操作する「fluent-plugin-twilio」を使って電話を掛けてみた - Y-Ken Studio
fluent-plugin-s3
fluent-plugin-hipchat
fluent-plugin-forest