コネヒト開発者ブログ

コネヒト開発者ブログ

Papertrail + Amazon CloudWatchでアプリケーション監視の幅を広げる

こんにちは、サーバーサイドのお仕事してます金城(@o0h_)です。
今更ながら「映画大好きポンポさん」(の2巻)を読みました、めっちゃ良くないですか・・・

映画大好きポンポさん2 (MFC ジーンピクシブシリーズ)

映画大好きポンポさん2 (MFC ジーンピクシブシリーズ)

本日は、サービスの監視の話です。
コネヒトではエラートラッキングにSentryを用いていますが、CloudWatch Alarmによる定量的なエラー観測も併せて行っています。
「どう使い分けるの」「どうやって観測しているの」というお話をさせていただきます。

https://cdn.mamari.jp/authorized/amana_5bbb0ea4-8550-4449-ba79-002aac120002.jpg

TL;DR

  • 「いつも起こるエラー」は、必ずしもエラートラッキングツールに蓄積していく必要がなさそうという判断
  • 代わりにログをPapertrailに溜めつつ、CloudWatch連携をして定量的に異常状態の監視を行うようにしたい
  • そのために「アプリ側(ロギング)」「Papertrail」の設定が必要

「問題」の対応レベル・監視レベルをデザインしよう

サービスを運用していると、いろいろなレベルの「エラー」が日々発生します。
その中には、「致命的なバグ」も「連携サービスの障害」「回避しようがない運用上の問題」「ユーザーの特定の操作によって生じる事象」など、様々なレベルや質のものがあります。 これに対して、 実装者の意図通りに処理を中断させるために例外をthrowする実装を用いることも多いと思います。例えば、 PageNotFoundException といったものです。

コネヒトでは、随分と前からメインのエラートラッキングツールとしてSentryを利用しています。
Sentryの良さというのは、「何かのエラーや予期せぬ例外が発生した際の記録を送信しておく先」としてアプリケーション連携が行われ、そのまま課題管理ができるボードとしても機能する点です。バグなどが混ざればここに蓄積されていく、という状態が成立します。

それを踏まえ、コネヒトでは原則として「Sentryに貯めていく「問題」は、個別に要確認・要対応のもの」という方針をとっています。端的に言えば「1件でも観測されたら対応しよう」というものです。
そのため、その範疇ではない、「いちいち見なくて良いし、無視をして問題ない」と判断したものもあります。例えば /wp-admin.php へのアクセスはWWWへ何かを公開したら最後、必ずやってくるでしょう。こうした「悪意のあるアクセス・操作」については、Sentryで管理したい内容ではないぞ、という扱いです。*1*2

さて、この「よく起こるし避けられない」問題の中には、それでも「サービスの異常事態を示す」のに非常に有益な情報も含まれていると考えます。
例えば、APIサービス側で「バリデーションエラー: ユーザー名の文字数は4文字以上にしてください」という内容は、先の基準で言う「Sentryで管理すべきもの」では無いように思います。しかしながら、「昨日から突如50件/1h増えた!」となれば、何らかの「異常」が(APIサービスの外で)生じているのではと考えることもできます。 「deprecated段階を経て廃止を行った旧バージョンのエンドポイントへのリクエストが想定どおりに推移していない」なども、その類でしょうか。

いわゆる「準正常系のエラー」について、根絶を目指して1件1件対応する!ことはないにせよ、定量的な観測を行うことで、よりサービスの品質安定に活用できるのではないか・・・?という発想です。

Papertrail -> Amazon CloudWatch(カスタムメトリクス) 連携!

主に準正常系に類されるエラーについては定量的な観測を行おう、そのためにPapertrail + CloudWatchが使えるぞ!!というのが本記事でご紹介したい内容です 💁

まずは、この主役を務める2つのクラウドサービスを簡単に紹介します。

Papertrailって?

papertrailapp.com

f:id:o0h:20180928103749p:plain ※画像は公式サイト より

Papertrailは、ログのホスティングサービスです。
各言語用に提供されたSDKやロガー*3とつなぎ込んだり、Syslogを用いて非常にカジュアルに「いろいろなサーバーのログを1箇所に集約する」ことが可能です。
収集したログは、CLIやブラウザベースでtailしたり高機能な検索・ブックマーク機能を用いて活用することが可能です。外部連携・エクスポート機能も充実しているので、「書き出して終わり」になりがちなアプリケーションログもとても簡単に活用することができます。

今回は、外部連携先の1つであるCloudWatchの利用に注目していきます。

Amazon CloudWatchって?

f:id:o0h:20180928110604p:plain:w360

Amazon CloudWatch は、開発者、システムオペレーター、サイト信頼性エンジニア (SRE)、IT マネージャーのために構築したモニタリングおよび管理サービスです。CloudWatch では、データと実用的なインサイトを利用して、アプリケーションのモニタリング、システム全体のパフォーマンスの変化に関する理解と対応、リソース使用率の最適化、および運用状態の統合的な確認を行うことができます。

CloudWatchというと、主にAWSリソースの監視目的で活用している方も多いのではないでしょうか。RDSの稼働状況だったり、EC2の状況をとても直感的に把握することができます。

これにくわえて、AWS名前空間以外の「カスタムメトリクス」の監視にも利用が可能です。これは、AWS外部からAPI経由で定量データを書き込む!というものです。

Papertrail -> Amazon CloudWatchの仕組み

Papertrailには「アラート」という機能があります。
これは、「指定した検索条件でのヒット数が」「指定した時間内に、指定件数以上記録された時」に、特定の連携先にデータを送るというものです。

この「連携先」として、Amazon CloudWatchを指定することができます。

これによって、「アプリケーション側からは、簡単にログを書き残していくだけ」で「発生件数を、シンプルなUIで集計や推移の確認が実現する」というわけです。

設定例: step-by-step

この設定がどれだけシンプルに行われるのか?を、実際に見ていきたいと思います。

0. まずはアプリケーションログの設定

前提として、「アプリケーションからPapertrailにログを送ることができている」という状態を作ってください。Papertrailのアカウント作成とアプリケーションのロギングの設定です。
ロギングについては、公式のヘルプを開き、 Configurationの項目を見ると、非常に幅広いプラットフォームでの対応例が記載されています。また、papertrail 使い方などと検索したらたくさんの情報が見つかるかと思います。

1. Papertrailの検索条件の保存

ログの受信が確認できたら、次に行うのは「検索条件の作成(保存)」です。 例では単純なキーワード部分位置を用いていますが、より高度な検索条件はヘルプを御覧ください。 f:id:o0h:20181008171806p:plain

検索条件が設定できたら、この条件を保存します

f:id:o0h:20181008172217p:plain

2. Alertの設定

次に行うのは、「Papertrail -> CloudWatchにデータが飛ぶようにする」設定です

f:id:o0h:20181008173301p:plain

この画面ではFrequency/Triggerの設定を行うことができますが、全量データを送る場合には Frequency:1min / Trigger When: at least 1 new events match で良いと思います。こうすることで、「1分間隔で、新しく1件以上引っかかったら送信する」状態になります。

なお、 Metric Namespace に任意の値を設定することができますが、特にこだわりがなければ空欄のままで問題ありません(その場合、 Papertrail というnamespaceが設けられます)

f:id:o0h:20181008174724p:plain

ここで1度、保存した内容での疎通テストを行っておくと確実です。 アラートの新規作成+保存後、検索条件設定の詳細画面に飛ぶので、その中にあるAlertを選択してください。ただいま作成したAlertの編集画面に遷移することができます。

f:id:o0h:20181008175049p:plain

3. CloudWatchの確認

実際にCloudWatchにデータが送信されているかを確認しましょう。 まずはCloudWatchにログインしてください

f:id:o0h:20181008175450p:plain

「カスタム名前空間」に、「Papertrail」は出現しているでしょうか。

f:id:o0h:20181008175634p:plain

f:id:o0h:20181008175801p:plain

f:id:o0h:20181008180018p:plain

正常に作動していれば、CloudWatch上からデータを確認することができます f:id:o0h:20181008181046p:plain

X. より便利な使い方

今回は詳細な紹介はしませんが、CloudWatch Alarm の設定を行うことで、より便利な監視体制を築くことができます。
実際に弊社で利用している例としては、「Webアプリケーションにおいてログインセッションが消失(タイムアウト)することは異常ではないが、あまりにも頻発している場合には調査・対処をしたいので、○分間で○件以上の当該エラーが確認された場合にはSlackに通知を投げる」というものがあります。 これは、

  1. Cloud Watch Alarmで閾値を設けて
  2. その閾値を超えたらSNS topicへの通知を行い
  3. SQS topicにLambda Functionを購読させておくことで
  4. Lambda Function上で通知内容の組み立て・通知先の判別処理を行った上でSlackに投げる

という仕組みに基づいています。
SNS/Lambdaと登場人物が増えるため、普段触っていない場合には少しハードルが高く感じられるかもしれません。しかし、非常に活用度が高いのと、蓋を開けてしまえばそれぞれ単純な処理や設定だけで完成しますので、ぜひ試してみてください。

XX. 蛇足: Papertrail + Slack連携

「一定値を超えたらSlackに通知」というのは、実はPapertrail -> Slackへの直接連携だけでも実現できます。設定の手軽さだけなら圧倒的にこちらのほうが便利です。
では、なぜCloud Watch / Cloud Watch Alarmを介してSlack連携を行うのでしょうか?

実際に利用していた/している経験を踏まえて、2点だけ紹介したいと思います。

1. 通知条件のカスタマイズ性 / 回復時の通知ができないこと

Papertrail -> Slack連携は、「設定した閾値を超過したとき」に通知が行われます。
これだけ書くと当たり前のようですが、実際に監視システムを作っていると「1回だけの超過ならスルーして大丈夫、もし超過状態が3インターバル分ずっと続いたら異常が生じている可能性が高いとみなす」という需要が出てくるのは良くある事です。あまりにもアラームが頻繁になり続け「オオカミ少年」状態になってしまうと、監視の効果がかなり薄れるからです。
本当に必要なときにだけ鳴る、という確からしさを高める必要があります。その観点に立つと、「1発アウト」しかできないのは、良い感じな閾値を探るハードルがとても高くなってしまうな・・・と感じました。

関連して、「閾値の超過状態が解消された」時にも同様に通知が欲しい時があります。Cloud Watch Alarmだと、「OK -> NG」の状態変化だけでなく、「NG -> OK」でも同様に通知を行うことができるので、やはりこうした点は専用システムの方が気が利いているなと感じました。

2. 通知内容のカスタマイズ性

Papertrail -> Slack連携をした場合、以下のような内容が飛んできます。

f:id:o0h:20181008185111p:plain
実際に記録された内容がSlack上で閲覧できる点は便利です。*4

他方で、CloudWatch Alarm -> Lambdaという構成の場合、「受け取った内容をどう処理するか」は全て自前での実装となります。手間が掛かる分、サービスや運用に即した通知内容・方法を構築することができます。 この点は、Papertrail -> Slack連携の「圧倒的手軽さ」に対して「かゆい所まで手が届く」というpros-consの検討になるかな、と思いました*5

まとめ

どんなサービスであれ、その開発・運用は不確実性を前提に立って行われるべきだと考えています。
そうした中で、やはり最も神経を擦り減らされるのはバグや障害への対応ではないでしょうか。
あまりに似たようなツールやシステムを導入してしまうと現場のストレスになりかねません。しかし、目的に応じた、より適切な選択を行っていくことは確かにチームのパワーとなっていくはずです!

コネヒトでも、色々なプラクティスを掻き集めて安心・安全なサービス運用をしていきたいな、と毎日考えています!

参考リンク

*1:「無視するエラー」を定めて、例外クラス名などの条件によって管理するようにしています

*2:この例については、Amazon CloudWatchを用いて4xxエラーの多発は別途モニタリングしています

*3:PHPならMonologなどでも簡単に扱えます

*4:ただし、今回の前提としている「よく起きがちだけど、つぶさに調査しなくていいもの」という類のものについては、「すぐに詳細が見られる」という点は、ハッキリとした強みには数えられないかも知れません

*5:1度だけLambda Functionを設定してしまえば使い回しが効きそうなので、適当なタイミングで作ってしまうのが妥当かな〜とは思っています