エラーはダッシュボード上の赤信号として現れるだけではありません。チェックアウトの失敗、リクエストの停止、あるいは最悪のタイミングでユーザーが離脱するといった形で現れます。エラーが存在することは簡単にわかりますが、なぜそれが起きているのかを知るところに真の課題があります。
現代の分散システムでは、エラーの根本原因の調査はこれまで以上に困難になっています。サービスは相互に依存し、デプロイメントが絶えず行われ、小さな障害がより大きな障害へと波及します。チームが慌てて事態を収拾しようとしている間にも、顧客はすでにその影響を受けており、企業は刻々と損失を被っています。長年にわたり業界では、2014年にGartnerが示唆した、システム停止の平均コストは1分あたり5,600ドル、という数字が使用されていました。しかし、最近のデータによると、これらのコストは着実に増加しており、現在、企業のダウンタイムは平均で1分あたり14,056ドルに達し、大規模な組織では1分あたり最大23,750ドルの損失が発生しています。これらの数字はあっという間に積み上がっていきます。生産性の低下、ユーザーの不満、ブランドのダメージについて考える以前に、8時間に及ぶ世界的なシステム停止は、企業の収益だけで数百万ドルの損失をもたらす可能性があります。これは、CrowdStrike社のシステム障害を思い起こさせます。
ただ、良い知らせがあります。適切なオブザーバビリティのプラクティスとツールを活用すれば、チームは症状を追いかけることから解決策を突き止めることへと転換できるのです。
このブログでは、体系的なエラー分析の手法がチームのダウンタイム削減や問題の迅速な解決にどのように役立つのかをご説明します。実用的なフレームワークの概要を説明し、New Relicなどのツールを使用してそれを実践し、MTTRを短縮してユーザーとビジネスの両方を保護する方法について説明します。
よくある失敗パターン
チームが問題点を把握している場合でも、解決を遅らせる予測可能な落とし穴に陥ることがよくあります。よくある失敗パターンには、次のようなものがあります。
- 根本原因ではなく表面的な症状を追う
ほとんどのインシデントは、エラー率の急上昇、サービスのタイムアウト、ユーザーに表示される500エラーなど、目に見える症状から始まります。ただし、チームは通常、これらのエラーのサインを、根本にある障害パターンを究明することなく、個別に切り分けて対処してしまいます。アラートは発報するものの、すぐに解決する方法がないため、チームは表面的な問題の解決に追われます。このような場当たり的な対応に終始することで、かえってアラートノイズが増え、実際の根本原因に集中できなくなります。 - データの過負荷とノイズ
多くのチームは依然として”すべてを収集する”監視に固執し、あらゆるメトリクス、ログ、トレースを取り込んでいます。この戦略は安全策のように聞こえますが、すぐに裏目に出る可能性があります。過剰なテレメトリーを生成する今日のシステムでは、チームがデータに溺れ、ノイズが発生し、コストが膨らみます。貴重なシグナルが埋もれてしまい、エンジニアは修正よりもノイズを取り除く作業に多くの時間を費やし、MTTRを短縮するどころか、かえって長期化させてしまいます。 - サイロ化されたダッシュボードと分断されたビュー
監視ツールはしばしば独立して存在し、APMとログは別の画面に、ダッシュボードはチームごとに構築されます。システムに障害が発生すると、エラーの原因究明は複数の画面にまたがるパズルのようになります。エンジニアは、問題解決に集中する代わりに、コンテキストの切り替えを余儀なくされ、データを手動で関連付けなければなりません。この分断された状態こそが、インシデント対応を遅らせる最大の要因の一つです。 - アラート疲れと感度の低下
監視システムが、優先度が低かったり誤検知のアラートを継続的に発すると、それらのシグナルは信頼性を失います。エンジニアはそれらを無視するようになり、重大なインシデントを完全に見逃してしまうリスクがあります。この"アラート疲れ"は非常に一般的な問題であるため、Google SRE Bookではこれについて明確に警告しています。その上で、症状に基づいたアラート設定と、それに伴う明確な優先順位付けの導入を推奨しています。 - 変更コンテキストの欠如
大半のシステム障害は、デプロイメント、設定の更新、インフラストラクチャの変更といった直近の変更イベントに関連しています。これらの変更イベントとシステムの挙動の間に明確な関連付けがなければ、チームは無駄な調査に時間を費やします。DORAのState of DevOpsレポートでは、エリートチームは変更の追跡とインシデント対応を密接に結びつけているため、より迅速に復旧できることが強調されています。このコンテキストの欠如は、エンジニアがしばしば"暗闇の中でデバッグする"状態を意味します。
こうしたパターンが続くのは、従来の監視ツールがシステムを横断して点と点をつなぐように設計されていなかったためです。これらの問題を打破するには、従来の監視を超えて、エラー、メトリクス、イベント、ログ、トレースの全てを単一のワークフローにまとめる必要があります。ここで、オブザーバビリティ(可観測性)が重要になります。
オブザーバビリティ≠監視:その違いを理解する
従来の監視は、ログとメトリクスを中心に構築されており、基本的に事後対応的でサイロ化されています。ログは、特定の時点で何が起こったかのスナップショットを提供しますが、多くの場合、構造化されておらず、単一のプロセスまたはサービスのみに関連付けられています。メトリクスは、一定期間にわたって数値を集計しますが、エラーにつながる詳細なコンテキストを隠してしまうことがよくあります。例えば、5xx応答の急増といったアラートが発報した場合、何かがおかしいことはすぐにわかりますが、その障害が自社のコード、ダウンストリームの依存サービス、あるいは設定変更のどれに起因するのかを特定するために、複数のダッシュボードを横断して探し回り、大量のログを取得し、タイムスタンプを手動で関連付ける必要があります。
一方、オブザーバビリティは、トレース、構造化ログ、メトリクス、イベント、コンテキストをクエリ可能な単一の基盤にまとめることで、その体験を一変させます。分散トレーシングは、個々のリクエストが関連するすべてのサービスにわたる経路をつなぎ合わせ、遅延や障害が発生した場所を正確に特定します。コンテキスト情報を持つ構造化されたログは、trace.idなどの識別子を介してリクエストのトレースデータを構成するスパンに自動的に紐付けられます。これにより、エンジニアは手動でコピー&ペーストや画面切り替えを行うことなく、ハイレベルなエラーアラートから、そのエラーの原因となった正確なログに直接ジャンプできます。また、デプロイイベントや設定変更を同じデータレイヤーに取り込むことで、直近の変更が問題の発生時期と一致しているかどうかを瞬時に把握できます。つまり、監視が"何かがおかしい"ことを教えるのに対し、オブザーバビリティは"なぜそれが起きているのか"という問いに答えることを可能にし、それによって、ノイズの多い対症療法から焦点を絞った根本原因の調査へと変えることができます。
エラーの追跡:ステップバイステップの根本原因分析(RCA)プレイブック
インシデントが発生すると、すぐに"解決"しようと考えがちです。そうではなく、あらゆるエラーを、システムの構造をより深く理解するためのパンくずリストと捉えてみましょう。
症状 → シグナル → システム → 根本原因
この手順を踏むことで調査範囲を絞り込み、実際の原因を明らかにします。
- 症状の把握
ユーザーまたはアラートが報告した内容(エラーの急増、遅延の発生、5xx応答など)から調査を始めます。正確なタイムスタンプ、影響を受けたエンドポイント、付随するアラートメッセージを記録します。このスナップショットは、その後に続くすべての調査の基盤となります。もしこれが数秒でもずれると、間違ったイベントを追跡することになります。
- シグナルへの変換
「この症状は何を伝えているのか?」と自問し、生の観察データを測定可能なシグナルに変換します。たとえば、単にエラー率、遅延のパーセンタイル、スループットを観測するだけでなく、次のように質問します。
- 1分間に失敗したリクエスト数は?
- 応答時間のどのパーセンタイルが急上昇したか?
- 受信したリクエストの数は変化したか?
これらのメトリクスを時系列でプロットし、異常が始まった瞬間を探します。このシグナルこそが、サービス間の相関関係を把握することを可能にします。
- 調査対象のシステムを切り分ける
この時点で、問題が発生したことはわかりますが、どこで発生したかはわかりません。テレメトリーを使用して、調査範囲を絞り込みます。
- 異常なメトリクスを最初に示したサービスまたはホストでフィルタリングする。
- メトリクスに変化が見られるダウンストリームの依存関係(データベース、キャッシュ、サードパーティAPI)を探す。
目標は、可能性のある対象を、ごく少数の候補システムにまで絞り込むことです。
- トレースとログでシステムをドリルダウン
サービスを特定できたら、それらのサービス内のどこに問題があるかを確認します。
- 代表的なリクエストをトレース:失敗したトランザクションを一つ選択し、その経路をエンドツーエンドで追跡します。遅延が発生したり、例外がスローされた最初のスパンが、通常、直接的な障害箇所を示しています。
- そのトレースに紐づいたログを検査:スタックトレース、エラーメッセージ、またはカスタム属性(例:db.queryTime)を探します。ログは、エラーが発生した正確なコード行や外部呼び出しを示してくれます。
- その時点の依存関係の健全性を確認:あるスパンが外部API呼び出しを示している場合、同時刻にその外部サービスのメトリクスが異常ではなかったかを確認します。
外部システムを呼び出した後にトレースが突然途切れている場合、障害の原因はサービス外部にある可能性があります。逆に、エラーがあなたのコード内で発生している場合は、ログとスタックトレースを見ることで障害の原因を特定できるでしょう。
- 外部イベントとの相関関係
外部システムは、障害の静かな原因となる場合があります。次のような、影響を与えた可能性のあるイベントに合わせてタイムラインを調整します。
- デプロイメントの期間:同じ日に新しいバージョンがリリースされましたか?たとえ別のサービスへのデプロイであっても、インターフェースの取り決めやデータ形式の変更がダウンストリームに波及する可能性があります。
- 設定の変更:タイムアウト値、接続プールサイズ、または機能フラグへの直近の微調整が、不安定さを招いた可能性があります。
- インフラストラクチャイベント:クラウドプロバイダーのメンテナンス、ネットワーク遅延の急増、またはDNS更新は、断続的なエラーとして表面化することがよくあります。
外部イベントがトレースで最初に見られる異常と一致する場合、根本原因の発生源を特定できた可能性が高いです。
根本原因の仮説を確定させるには、その現象を安全に再現するか、あるいは原因に応じて、ロールバックや設定値の調整といった一時的な修正を適用して検証します。もし症状が解消すれば、あなたの仮説は裏付けられます。解消しない場合は、新しいデータを使用して手順4に戻って繰り返します。この手順に従うことで、ノイズの多いインシデントを、明確で再現可能な調査プロセスに変えることができます。その結果、分析を集中させ効率化でき、MTTRの短縮と障害の再発防止を実現できます。
このフレームワークは特定のツールに依存しませんが、New Relicのようなオブザーバビリティプラットフォーム内に適用すると、はるかに強力になります。
New Relicにおける根本原因の分析
RCAプレイブックが実際のテレメトリーにどのように適用されるかを説明するために、New Relicにおける次のシナリオを考えてみましょう。あなたはAd Serviceに関するアラートを受け取りました。内容は、Ad Serviceのエラー率があらかじめ定義された閾値を超過した、というものです。このアラートは何か問題があることを示す症状であり、次のようなものになります。
アラートはAd Serviceに紐づいているため、障害が発生しているシステムはすでに明らかです。New Relic内で問題のあるサービスに移動します。この例では、Ad ServiceはAPMに登録されたサービスであり、まずはSummaryページから調べることにします。このページには、エラー率、レスポンスタイム、スループットなどのアプリケーションレベルのテレメトリーが表示されます。
このページのエラーチャートを見ると、約20%のエラー率が継続しており、定期的に上昇していることがわかります。応答時間も同じ間隔で上昇していますが、スループットは安定しているため、トラフィックの急増が原因ではないことが分かります。これにより、症状が確認されました。すなわち、サービスは通常の負荷の下でエラーを返しているということです。
ここから、Errorsチャートをクリックすると、そのサービスのErrors Inboxに移動します。次の画像に示すように、ここではそのサービスから発生したすべてのエラーグループが表示されます。
この特定のケースでは、2つの主要なエラークラスが見られます。
SQL connection failed with status {Too many connections}TimeoutException: context timed out
最初のエラーグループを見てみましょう。クリックするだけでOccurrence details viewを開くことができます。このページには、Error group metrics、occurrences(発生回数)、Stack trace、Distributed Trace(分散トレース)などの詳細が表示されます。
ほとんどの場合、スタックトレースは失敗したリクエストに直接つながっています。例えば、上の画像では、スタックトレースはAdServiceImpl.getAdsを指しており、そのエラーは失敗したリクエストのトレース情報(GET /product/{id})にリンクされています。これにより、調査対象がサービス内の特定のコードパスに絞り込まれます。さらに一歩進んで、このビューからDistributed Trace(分散トレース)を開くこともできます。
Distributed trace(分散トレース)は、6つの異なるサービスにわたるリクエストの経路を示しており、Ad Serviceのスパンは赤でフラグ付けされています。また、コールスタック(呼び出し履歴)内で例外が発生した場所も示しています。これらが先ほどのエラーメッセージと組み合わされることで、Ad ServiceがSQL接続を使い果たしており、その障害が広告を読み込もうとするすべての製品ページに波及していることが明らかになります。
ログが、このランタイム障害を裏付けています。
ログ、トレース、Podのメタデータは自動的に関連付けられるため、手動で検索する必要はありません。調査は、症状からシグナル、システム、そして最終的に根本原因へと順調に進みました。その根本原因とは、コネクションプールが飽和しているため、Ad Serviceが新しいSQLコネクションを開けなくなっていることです。
これで問題の根本原因がわかったので、ようやく修復に移ることができます。
ボーナス:AIによるエラーの説明と修復
手動のRCAワークフローに加えて、New RelicはNew Relic AIを通じて修復を支援することもできます。Ad Serviceのシナリオでは、Log detailsパネルの上部にあるExplain this errorボタンをクリックします。New Relic AIはスタックトレースとエラーの詳細を分析し、状況に応じた修復ガイダンスを提供します。このケースでは、SQLコネクションプールの枯渇を特定しデータベース接続制限の見直し、コネクションプール設定のチューニング、アプリケーション内での接続解放の確認という実用的な手順が提案されます(下図参照)。
まとめ
インシデントは必ず発生するものですが、長期にわたるシステム停止は避けられます。体系的なエラー分析の手法により、何時間もかかる推測に頼った作業を、再現性があり、根拠に基づくプロセスに変えることができます。ただし、この体系的な手法は、New Relicのようなオブザーバビリティツールによってサポートされて初めて機能します。より多くのデータを収集することではなく、適切なデータを適切なタイミングで可視化することが重要です。New Relicは、アラート、トレース、ログ、変更イベントのすべてを単一のワークフローに結び付けるため、チームは検出から解決までをより迅速に進めることができます。その結果、MTTRが短縮され、障害発生回数が減少し、顧客からの信頼が強化され、エンジニアリングとビジネスの両面で信頼性に対する自信が高まります。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。