fluentd
S3
hipchat
twilio

fluentdでつくる監視系

More than 3 years have passed since last update.

いつもアプリケーションの開発ばかりで、まじめに監視系を考えたことがなかったので、

fluentdを中心にした監視系を作ってみた。

ツッコミ大歓迎です。アチラコチラの資料を参考にしつつ作ったので、オカシイところがあれば是非ともコメント下さいませ。


前提


  1. 複数台のアプリケーションサーバ

  2. 一台のログ収集サーバ

  3. ログにはエラーログとアクセスログの大きく2種類を用意する

  4. エラーログは更に複数のレベルでファイル単位にわかれている


    1. fatal

    2. error

    3. warn



  5. アプリケーションサーバとログ収集サーバは同一ネットワーク上にある


やりたいこと

メールで来ても絶対に気がつかない自信がある。

異常の側から教えてくれる仕組みを目指す。


  1. fatalログが出た場合は、電話による通知を行う

  2. 全てのエラーログはchatツールに出力する

  3. ログのバックアップ

  4. ログの分析・可視化

この記事では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