特定のユーザー・特定の環境でだけ再現する
「一部でだけ起きる」を、報告を待たずに自力で絞り込めるようになる。影響範囲を軸ごとに二分して再現条件を確定させる手順と、軸の候補を漏れなく列挙するチェックリストが身につく。
- 一部でだけ起きるということは、影響を受ける集合と受けない集合の境界が必ず存在する。その境界を定義している軸を見つけるのが調査の本体で、原因の推測より先に来る。
- 軸の候補は7つ——ユーザー属性・データ内容・クライアント環境・地理と経路・時刻・インフラの個体・段階的公開の割り当て。ログを軸ごとに集計すれば偏りが見える。
- 軸が1つに絞れたら、その軸上で二分探索する。バージョン境界なら二分探索で特定のコミットまで、データ境界なら値の範囲まで詰められる。
「一部のユーザーからだけエラー報告が来る」「特定の環境でだけ画面が崩れる」。この種の問題が難しいのは、自分の手元では起きないからです。再現できないものはデバッグできないので、調査は「原因を探す」の前に「再現条件を確定させる」から始まります。
そして、この症状には確実に成り立つ性質があります。一部でだけ起きるなら、影響を受ける集合と受けない集合を分ける境界が必ず存在する。境界を引いている軸を見つければ、そこから先は通常のデバッグに落ちます。原因を推測するより先に、この境界の特定に集中するのが最短経路です。
軸の候補を先に列挙する
推測で当てにいくと、たまたま思いついた軸から順に試すことになり、順序が運任せになります。先に候補を並べてから、データで消し込みます。
| 軸 | 具体例 | ログで見る集計キー |
|---|---|---|
| ユーザー属性 | 権限ロール、プラン、作成時期、所属組織 | ユーザーID、ロール、テナントID |
| データ内容 | 特定の文字(絵文字・結合文字)、データ量、NULL、境界値 | 対象レコードのID、サイズ、文字種 |
| クライアント環境 | ブラウザとその版、OS、言語設定、拡張機能 | User-Agent、Accept-Language |
| 地理と経路 | 国、ISP、CDNのエッジ、社内網か否か | 送信元IP、CDNのPOP識別子 |
| 時刻 | 特定の時間帯、月末、日付変更、夏時間の切り替え | タイムスタンプ、ユーザーのタイムゾーン |
| インフラの個体 | 特定のサーバー、AZ、DBレプリカ、コンテナ | インスタンスID、ホスト名、AZ |
| 段階的公開 | フィーチャーフラグ、カナリア、A/Bの割り当て | フラグの評価結果、リリース群 |
やることは単純です。エラーが出たリクエストと出なかったリクエストを、この各キーで集計して偏りを探す。偏りが出た軸が境界です。
「エラーの80%がChromeから」は何の情報でもありません。全トラフィックの80%がChromeなら、それはただの構成比です。見るべきは軸の各値ごとのエラー率です。Chrome 0.1%・Safari 12% なら、件数ではChromeが多くてもSafariが犯人だと分かります。この間違いは非常に多く、そのまま無関係な方向へ何時間も使うことになります。
インフラの個体は最初に潰す
7つのうち、インフラの個体だけは他と性質が違うので先に確認する価値があります。理由は2つあります。第一に、これが原因ならアプリのコードは無罪で、調査範囲が一気に変わります。第二に、確認が最も簡単です。
エラーをインスタンスID・AZ・レプリカごとに集計する
1台に集中している → その個体が壊れている
ディスク障害、設定の取り残し、古いバージョンが残留、
時刻ずれ、証明書の期限切れ、リソース枯渇
全体に均等 → 個体は無罪。他の軸へ進む
「10台中1台だけが古い設定のまま」は驚くほど頻繁に起きます。エラーがインスタンスIDで偏っていないかは、数分で確認できて、当たれば即解決です。
同様に、DBのレプリカごとに偏るならレプリケーション遅延や1台のインデックス欠落を疑います。読み取りが複数レプリカに分散していると、「同じ操作を繰り返すと成功したり失敗したりする」という紛らわしい症状になります。
軸が絞れたら二分探索する
軸が1つに定まったら、その軸上で範囲を半分ずつ詰めます。
バージョンの軸なら、動く版と動かない版の間をコミット単位で二分探索します。git bisect はこれを自動化する仕組みで、log2 のオーダーで犯人のコミットに到達します。再現手順が確立していることが前提なので、ここでも再現条件の確定が先に来ます。
データの軸なら、対象のレコード集合を半分に割って、どちらで再現するかを繰り返します。「特定の1件だけで落ちる」まで詰められれば、そのデータを見れば原因が分かります。
設定の軸なら、動く環境と動かない環境の設定差分を取り、半分ずつ寄せます。手順はローカルでは動くのに本番だけ落ちると同じ考え方です。
データ内容の軸は見落とされやすい
横にスクロール
7軸のうち、データ内容は最も見落とされ、かつ最も「特定のユーザーだけ」という形で現れます。ユーザーごとにデータが違うので、結果としてユーザー軸の偏りに見えるからです。
- 文字の扱い。 絵文字(サロゲートペア)、結合文字、右から左に書く言語、ゼロ幅文字、正規化の違い(
がを1文字で表すか濁点を分けて2文字で表すか)。名前や住所に含まれると、その人だけで落ちます。 - データ量。 1件しか持たない人と10万件持つ人では、同じ画面がまったく違うクエリになります。タイムアウトやメモリ不足がその人だけで起きます。
- 境界値と欠損。 未設定の項目が
NULLなのか空文字なのか、初期からいるユーザーだけ移行前の形式のままか。 - 時刻とタイムゾーン。 ユーザーのタイムゾーンが日付変更をまたぐ位置にあると、その人だけ日付の集計がずれます。夏時間のある地域では年2回だけ壊れる処理があります。
「そのユーザーのデータを見れば分かる」は正しいのですが、本番の個人データへのアクセスは記録が残る権限操作です。まず再現に必要な最小限の情報だけ(データ量、文字種の有無、対象IDのような識別子)をログやメトリクスから取れないかを検討してください。多くの場合、中身そのものを見なくても「その人のレコードは12万件」「名前に結合文字が含まれる」まで分かれば十分に再現できます。
再現できたら、まず失敗するテストにする
再現条件が確定したら、修正に入る前にその条件を再現する自動テストを書くのが定石です。理由は3つあります。
- 再現手順が形式化される。 「あのユーザーで、あの画面で」という口伝が、実行可能な形になります。
- 修正の完了判定が明確になる。 テストが通れば直った、という基準が手に入ります。
- 再発が検知される。 この種のバグは、条件が特殊なぶん通常のテストをすり抜けて再発します。
観測を先に整える
この症状の調査効率は、ログにどの軸が入っているかでほぼ決まります。あとから増やせないので、平時に仕込んでおきます。
- リクエストログにインスタンスID・AZ・リリースバージョンを必ず含める。個体の切り分けが即座にできます。
- フィーチャーフラグの評価結果をログに残す。段階的公開の軸はこれが無いと追えません。
- エラーにリクエストIDとユーザーの識別子を紐づけ、報告から該当ログへ一発で辿れるようにする。
- 集計は率で出せる形にする。分母(そのセグメントの全リクエスト数)が取れないと、偏りの判定ができません。
まとめ
- 一部でだけ起きるなら、影響を受ける集合と受けない集合を分ける境界が必ず存在する。原因の推測より、境界を引く軸の特定を先に行う。
- 軸の候補は7つ——ユーザー属性・データ内容・クライアント環境・地理と経路・時刻・インフラの個体・段階的公開。ログを軸ごとに集計して偏りを探す。
- 偏りは件数ではなく率で見る。構成比を犯人と誤認するのが最頻の失敗。
- インフラの個体は最初に潰す。確認が数分で済み、当たればアプリは無罪になる。
- 軸が絞れたらその軸上で二分探索する。バージョンなら
git bisect、データなら集合を半分ずつ。 - 再現できたら修正の前に失敗するテストにする。再現手順の形式化・完了判定・再発検知が同時に手に入る。
- 調査効率は平時の観測設計で決まる。インスタンスID・リリース版・フラグ評価結果・分母を取れる形での集計を仕込んでおく。
トラブルシュート実戦の記事ガイド
特定のユーザー・特定の環境でだけ再現するを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
トラブルシュート
比較で見る軸
難易度: advanced / カテゴリ: トラブルシュート実戦 / タグ数: 5
導入後に効く点
軸の候補は7つ——ユーザー属性・データ内容・クライアント環境・地理と経路・時刻・インフラの個体・段階的公開の割り当て。ログを軸ごとに集計すれば偏りが見える。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- トラブルシュート実戦
- タグ数
- 5
判断チェックリスト
- 自社の用途が「トラブルシュート / デバッグ」に近いか確認する。
- 強みである「一部でだけ起きるということは、影響を受ける集合と受けない集合の境界が必ず存在する。その境界を定義している軸を見つけるのが調査の本体で、原因の推測より先に来る。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。