背景
アカツキが提供しているサービスはリリース前に必ずテストを行っています。テストでバグが見つかったときにこれを切り分けるため、発生時のログを探すことがあります。「クライアントアプリで明らかに表示がおかしい」とか、そういったバグなら問題ないのですが、クライアントアプリからでは見えないサーバー側のバグが起きていて、それが見逃されてしまう…なんてこともあるかもしれません。
ふと、「機械的にこれを検出できるといいなー、あとログを探るためだけに毎回SSHするのもめんどくさいなー」 と思い、手を動かしてみることにしました。
今回の要件
- テスト環境でサーバーエラーが起きたのを機械的に検出して、すぐ知らせてほしい
- アクセスしやすいところに必要なログだけがあると嬉しい
- できれば簡単な方法でやりたい
ツールの選定
アプリケーションの例外を検知して開発者に知らせてくれるものに、ExceptionNotifierや Airbrake(有料)、Errbitなどがありますが、インストールするためにいずれもコードの修正が必要になります。
コードの修正をしなくて良い方法を模索していて、そこで目をつけたのがCloudWatch LogsというAWSのサービスでした。CloudWatch Logsではログに対してアラートを設定することが出来ます。 また、ログの保存に耐久性の高いストレージを使用することが出来ます。エラーの検知に関してはfluentd使用してログをtailすれば実現できそうです。
CloudWatch Logsとfluentdを利用する方法だとコードを変更する必要がなく、かつモジュール同士が疎結合になるので設計上とても実用的です。また、HipChatやSlackなどのチャットサービスを経由した通知もfluentdのプラグインを利用すれば比較的簡単に作ることできそうなので、アカツキ的に使いやすいということもありました。
CloudWatch Logs とは
CloudWatch LogsはAWSのログファイルのリアルタイムモニタリングサービスです。
- ログファイルの格納
- ログファイルの監視
- ログファイルの閲覧
- アラートの設定
- 保持期間の設定
などが出来ます。
2014年12月からTokyoリージョンでも利用できるようになりました。
やってみた
概要
サーバーエラーはRuby on Railsのログに全て記載されるので、ここを監視するのが比較的簡単にエラーを知る方法かなと思います。サーバーエラーが発生した時はそのログをCloudWatch Logsに投げるようにして、CloudWatch側でアラートを設定します。
IAM Userの作成
ポリシーを以下のようにして、CloudWatch Logs用のIAMユーザーを作成しました
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*",
"s3:GetObject"
],
"Resource": [
"arn:aws:logs:us-east-1:*:*",
"arn:aws:s3:::*"
]
}
]
}
(参考: https://github.com/ryotarai/fluent-plugin-cloudwatch-logs/blob/master/README.md)
作成したら、AccessTokenとSecretを控えておきます。
fluentdの設定
1. fluent-plugin-cloudwatch-logs プラグインをインストールします。
$ /usr/lib64/fluent/ruby/bin/gem install fluent-plugin-cloudwatch-logs --no-ri --no-rdoc
2. td-agent.confに設定を記述する
<source> type tail path /path/to/logfile.log pos_file /var/log/td-agent/logfile.log.pos tag app.error format /^E, (?<log>.*)$/ </source> <match app.error> type cloudwatch_logs log_group_name your_log_group_name log_stream_name your_log_stream_name auto_create_stream true </match>
3. 環境変数の設定
td-agentユーザーにはログインシェルがなかったため、/etc/init.d/td-agentに以下のように記述しました。
export AWS_REGION="your_region" export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY" export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"
4. td-agentの起動
$ service td-agent start
5. td-agent.logの確認
デフォルトだと/var/log/td-agentにあるtd-agent.logにエラーが表示されていないことを確認します。
アラートの設定
fluentdが起動してAWS ConsoleからCloudWatch Logsに移動すると、Log GroupとLog Streamが自動で生成されていました。Log Groupsからアラートを設定したいLog Groupを選択してCreate Metric Filterからアラートを設定します。
Filter Patternに検出パターンを入力して、アラートを設定したら完成です!
まとめ
簡単なアプリの監視をアプリ側の変更なしで、かつ少ない手順で作成することが出来ました。
機械的にエラーを検出することができ、通知もログの取得も簡単になりました。
このように一時的なログの置き場として利用したり、ログ自体を監視したい時にCloudWatch Logsは便利なサービスです。機会があれば利用してみてはどうでしょうか。