本記事は、2022年5月14日に行われた「SRE NEXT 2022」にて、当社Sreake事業部SREである青木亮磨が発表した内容「より意味のある監視を目指して、外形監視の有効活用」について、まとめた内容となります。
なお、当日の講演動画はYoutubeのSRE NEXTチャンネルより配信されておりますので、合わせてご覧ください。
監視とは
今回は監視についてお話ししていきます。
まず監視とは何かですが、書籍「入門 監視」の言葉を引用すると、監視とは「あるシステムやそのシステムのコンポーネントの振る舞いや出力を観察しチェックし続ける行為」です。では、なぜ監視が必要かというと、システムを安定して継続的に提供するためです。
監視には、大きく3つの要素が存在します。

1つ目は、システムの行動や状態に関するデータの収集・保持です。具体的には、アプリケーションやサーバ、ネットワークなどのログやメトリクスなどを収集し、後から参照できるように保持します。

2つ目は収集したデータの可視化・分析です。収集したデータを可視化して、システムの状態を把握できるようにしたり、必要に応じて分析を行い、システムに何か問題が起きていないか、何か問題が起きそうではないかを確認します。

3つ目は問題の検知・通知、いわゆるアラートです。先ほどの項で、システムに問題が起きていないか、起きそうではないか分析すると述べましたが、目視でシステム全体の状態を把握することは骨の折れる作業です。また、24時間ずっと張り付いているわけにもいかないので、システムに何か問題が起きていたり、起きそうな場合には、自動で検知して通知してくれる仕組みを用意することは監視において非常に重要な要素です。
一般的には、通知には「緊急で対応しなければいけない場合の通知」と、「緊急ではないが後ほど確認しておいた方がよい場合の通知」の2種類があります。
よくあるアラート設計
通知には2種類存在すると述べましたが、そういう区分けをせずに、思いつく怪しい状態を次々と、緊急対応しなければいけないアラートとして通知してしまうというのは、よくあるアラート設計なのではないかなと思います。

しかし、こういった設計をしてしまうと、大量にアラートが発生して、電話やメンションの嵐になってしまいます。大量にアラートが発生していても、それらのアラートが本当に緊急で対応しないといけない内容なのであれば、アラート設計的には問題ありません。ただ、緊急で対応しなくても良い内容のアラートなのであれば、それはとても危険な状態です。

緊急ではない、もしくは対応する必要がないアラートが発生すると、業務の中断や業務時間外の呼び出しが発生し、貴重な時間が奪われてしまいます。また、そうしたアラートが上がる状態が続くと、単純に疲れてしまいます。しまいにはアラートを軽視するようになり、本当に対応が必要な場合に初動が遅れたり、適当に対応して判断や対処を誤ったり、無視してしまうようになります。俗に言う「オオカミ少年アラート」問題の発生です。
ユーザー目線での監視
「オオカミ少年アラート」問題の対策としては、システム目線で何か問題が起きてそうな場合に通知するのではなく、ユーザー目線でサービスが正常に動いているかを確認し、サービスに影響が生じている、つまり緊急対応が必要な場合に通知するようにするというのが一つの手です。
ユーザー目線でのサービスの監視には、クリティカルユーザージャーニー (CUJ) が活用できます。

ユーザージャーニーとは、ユーザーが目的を果たすために行う一連のアクションを指します。ユーザージャーニーはたいてい複数ありますが、その中でもビジネスへのインパクトとして最も重要なものがクリティカルユーザージャーニー (CUJ) と呼ばれます。例えば、ECサイトであれば商品を購入されることがビジネスとして重要なので、CUJとしては「商品の検索 → 商品をカートに追加 → 購入」という一連のアクションが考えられます。このCUJが正常に実行できる状態であるかどうかを監視すれば、サービスに影響が生じているかどうかを判断することできます。
CUJの監視には外形監視が一番シンプルで導入しやすいです。

外形監視と一口に言っても、大きく分けて2つのやり方が存在します。1つ目はAPIベースのやり方です。こちらは、CUJを実行する際にアプリケーションから利用されるAPIを順々に確認し、正常にレスポンスが返ってくるかを確認します。この方法のメリットは、APIにリクエストを送るだけなので非常にシンプルで分かりやすいことです。ただし、デメリットとしては、実際にユーザーが利用するブラウザや端末からサービスを利用できているかという観点では確認ができないことです。
2つ目はブラウザベースのやり方です。こちらはヘッドレスブラウザなどを用いて、実際にブラウザ上でアプリケーションを操作して、CUJを実行できるかを確認する方法です。メリットは、APIベースよりもよりユーザー目線でサービスの状態を確認できる点です。しかし、UIの変更が多い場合には、テストシナリオの保守が大変というデメリットがあります。たいていの場合、この保守コストが無視できない大きさになってしまうと思うので、今回はAPIベースでCUJの監視を行ってみます。
Datadogを用いたCUJの外形監視
今回はDatadogを用いて、CUJの外形監視を行ってみます。

監視対象としては、Sock Shopというデモアプリを利用します。こちらは靴下のECサイトで会員登録・ログイン・商品検索・カート・注文といった機能が存在します。ECサイトなので、ここでは「商品の検索 → 商品情報の取得 → カートに追加 → 注文」というフローをCUJとして定義します。

具体的な監視の設定に入る前に、Datadogの外形監視機能であるSynthetic Monitoringについて紹介します。Synthetic Monitoringには3種類のテスト方法が存在します。
1つ目はAPI Testです。こちらは、あるAPIに対して、単一のリクエストを送り、そのレスポンスを検証するというものです。
2つ目はMultistep API Testです。こちらは、複数のAPI Testをチェーンして、シナリオでのテストが可能となります。前のリクエストで得たレスポンスは後続のリクエストで用いることが可能なので、例えば商品検索のAPIにリクエストを送り、ヒットした1件目の商品をカートに入れるといったテストが可能になります。
3つ目はBrowser Testです。こちらは実際にブラウザ上でアプリケーションを操作して、アプリケーションの動作を検証できます。
今回はAPIベースでCUJを監視するので、Multistep API Testを利用します。
実際に定義したシナリオはこちらです。

注文する際にログインが必要なので、まずはログインをして、その後検索ページから商品を検索し、ヒットした1件目の商品ページに遷移します。そして、商品をカートに追加し、カート画面に遷移し、最後に注文するというシナリオを API ベースでテストしていきます。
では、1つずつ見ていきます。
まずはログインです。

左側のスクリーンショットのDefine The Stepの項目を見ていきます。ここではリクエストの内容を設定します。Sock Shopはベーシック認証でログインする仕組みなので、Authorization Headerにユーザー名とパスワードをセットします。
なお、パスワードのような機密性の高い情報は、Global Variablesという機能をhide and obfuscate variable valueというオプションとともに利用することで、値は利用できるが値の中身は見ることができないという状態で保持することができます。
ヘッダーの設定はできたので、ログイン用のエンドポイント (/login) にリクエストを送るようにURLを指定します。
続いて、Define the Stepの下のAdd Assertionsの項目を見ていきます。ここでは、レスポンスの検証内容を設定します。まずは、レスポンスタイムが2000ms以下であることを確認します。2000msというのはデフォルトの値を利用しているだけなので、実際に使う場合には適宜値を調整してください。次に、ステータスコードが200であることを確認します。後は、認証に成功した場合、ヘッダーのset-cookieにlogged_inという値が設定されるはずなので、その値が含まれていることを確認します。レスポンスがこれらの設定した条件を満たさなかった場合、このステップは失敗ということになります。
最後に、Extract variables from the responseの項目を見ていきます。ここでは、レスポンスで取得した値を変数に入れて、後続のリクエストで利用できるようにするということができます。ここでは、後続のリクエストのヘッダーにcookieを設定できるように、今回取得したcookieを保持しておきます。
次に商品検索です。

先ほど、ログイン時に取得したcookieをヘッダーに設定します。以降のステップでも、同様にリクエストにcookieを設定しますが、繰り返しになるので今後は説明を省略します。
cookieを設定した後は検索パラメータを入力していきます。今回はbrownタグが設定されている商品のみを検索したいため、Query Paramsに tags=brownと入力し、商品検索用エンドポイント (/catalog) にリクエストを送ります。
レスポンスの検証内容は、レスポンスタイムが2000ms以下であることと、ステータスコードが200であることとします。
後続のステップでは検索でヒットした1件目の商品をカートに入れて購入するフローを検証するので、レスポンスの1件目の商品IDを変数に入れておきます。
続いて商品情報の取得です。

先ほどの検索でヒットした1件目の商品の詳細情報を取得するために、先ほど得た商品IDを用いて、商品情報を個別に取得するためのエンドポイントである (/catalog/<id>) にリクエストを送ります。
レスポンスの検証内容は先ほど同様、レスポンスタイムとステータスコードと、bodyのidが、検索した商品IDと一致していることとします。
続いてカートに追加です。

リクエストのbodyに追加したい商品IDを記載し、カート追加用のエンドポイント (/cart) にPOSTします。レスポンスの検証内容はレスポンスタイムが2000ms以下であることと、ステータスコードが201であることとします。

続いて、カートの中身を確認するために、カートの状態を参照するためのエンドポイント (/cart) にリクエストを送り、レスポンスタイムが2000ms以下、ステータスコードが200、カートの中身の商品IDが先ほど追加した商品IDと一致していることを確認します。

そして、注文用のエンドポイント (/orders) にPOSTし、レスポンスタイムが5000ms以下、ステータスコードが201であることを確認します。
ここで1点注意ですが、今回はデモアプリなので特に気にせず注文処理をテストしていますが、実運用環境では監視のリクエストにより不都合が生じないように、監視のリクエストの場合は、決済のようなクリティカルな処理はスキップし、正常時と同じようなレスポンスを返すといった振る舞いに事前にしておく必要があります。

監視の頻度は、30秒から1週間の間で設定可能です。高頻度で行うことが望ましいですが、その分費用がかさみますので、予算を鑑みて決めてください。ちなみにSynthetic MonitoringのAPI Testの費用は、2022年4月11日時点では毎月1万テストあたり5ドルです。

ダッシュボードでは、このようにテスト結果を見ることができます。こちらは全ステップ成功している場合の例です。

失敗した場合はこのように表示されます。失敗時のアラート設定をしておけば、Slackなどのチャットツールに通知したり、PagerDutyと連携して電話をかけられます。
各監視サービス、パブリッククラウドの外形監視機能
ここまで、Datadogのお話をしてきましたが、他の監視サービスやパブリッククラウドにも外形監視機能は備わっています。

例えばNew Relicだと、Syntheticsという機能の中にEndpoint availabilityというAPIベースの監視機能があります。AWSであればCloud WatchのSynthetics Canaries、Google CloudであればCloud Monitoringのpublic uptime checkがあります。
詳細については表を見ていただければと思いますが、各サービスについて簡単にまとめると、DatadogはUI上で簡単に設定ができるのでとても楽です。New RelicとAWSはスクリプトを記述する形式なので最初は少し大変かもしれませんが、柔軟な設定が可能です。ただし、AWSに関しては他と比べるとコストが高くなる印象があります。Google Cloudはシナリオでのテストはできないため利用できる場面は限られますが、無料で使えるので利用できる場面があればどんどん利用すると良いでしょう。
まとめ
最後にまとめです。

何でもかんでも緊急的なアラートとして通知すると、アラート疲れが起きてしまったり、アラートを軽視するようになって、アラートとしての効果を失う可能性があります。
なので、まずはサービスに影響が生じている場合に通知すると良いでしょう。サービスに影響が生じているかの判断にはCUJの外形監視というアプローチが導入しやすいです。各監視サービスやパブリッククラウドには外形監視機能が備わっているのですぐに導入が可能です。
ただし、CUJの外形監視をしておけばよいという訳ではありません。CUJの外形監視で捕捉できない障害を検知するには、他の監視でカバーする必要があります。近いうちに起こりうる障害を検知するには、サービス影響が生じているかではなく、システム目線での健康診断も必要です。もし検知した場合には、緊急的なアラートとは別の方法で通知したり、チケットを生成するなどして、緊急度の違うアラートが入り乱れないように注意しましょう。
サービス詳細や料金についてのご質問・ご相談などお気軽にお問い合わせください

サービスのメリットや紹介テキスト
金融・医療・動画配信・AI・ゲームなどの様々な領域での実績から、最適な課題設定と解決策を提示します。