異常の検知/ Detection
サーバは動いているのに業務が止まっている、を見つける
ここから後半です。クラウド側の監視は「サービスが応答しない」「バッチが異常終了した」を拾いますが、実際に困るのはサービスは正常なのに業務が前に進んでいない状態です。それを判定するには、アプリのデータベースの中を数える必要があります。この章は、何をどう数えているかを扱います。
アプリ独自の 29 種Alert Catalog
全 29 種です。重大度は 2 段(重大 / 警告)で、種別ごとに固定しています。ただし 3 種だけ、影響の範囲によって重大度が変わります。29 種すべてに起票する実装があります(表示だけの枠は残っていません)。
| 系統 | 種別 | 重大度 | 判定のしきい値 |
|---|---|---|---|
| ウイルス スキャン | ウイルス検出 | 重大 | 感染と判定されたファイル 1 件 |
| ファイル内容の不一致 | 警告 | 宣言された拡張子と中身が一致しない 1 件(予防的に隔離。実ウイルスとは別扱い) | |
| アップロード整合性エラー | 警告 | 申告されたハッシュ値と実測が一致しない 1 件(版は破棄され、再アップロードが正) | |
| スキャン滞留 | 警告 | 検査中のまま 5 分以上の滞留が 一定件数超 | |
| スキャン失敗(上限到達) | 警告 | 再試行 3 回で失敗に確定した 1 件 | |
| EICAR 検出テストの失敗 | 重大 | 月次の検出テストで、無害な標準テストファイルを検出できなかった | |
| ウイルス定義の更新失敗 | 警告 | 定義の更新が連続 3 回失敗 | |
| イベント・ 通知配送 | 配信不能メッセージの超過 | 重大 | 配信できずに溜まったメッセージの合計が 一定件数超 |
| イベント配信の滞留 | 警告 | 再試行の上限に達したイベントが 1 件以上 | |
| 通知配送の滞留 | 警告 | 送信待ちのまま 30 分超の宛先が 1 件以上 | |
| メールバウンス率の上昇 | 警告 | 直近 24 時間の不達率が 一定の割合超(分母が一定以上のときだけ判定) | |
| Drive 同期 | 同期の連続失敗(2 日) | 警告 | 同じ Box で 2 日連続の失敗 |
| ルート検証の失敗(30 日) | 警告 | Box のルートフォルダの検証が 30 日以上失敗 | |
| 管轄外ファイルの大量検知 | 警告 | 1 つの Box に、アプリの管理外のファイルが 一定件数超 | |
| API クォータの上昇 | 警告 | Drive API の使用率が 80% 超 | |
| 定期補修の所要時間の上昇 | 警告 | 定期の処理が、割り当てた時間の 一定の割合超を使った | |
| 単一 Box の上限接近 | 警告 | 1 つの Box の同期対象が 一定件数超(検知のみ・処理は続行) | |
| 共有リンク | 総当たりアクセスの検知 | 重大 | 1 つのリンクへ 1 分 20 件以上の認証失敗 |
| 同一 IP からの大量アクセス | 警告 | 同一 IP から 5 分 100 件のアクセス | |
| 保持期間・ アーカイブ | アーカイブ存否確認のエラー | 警告 | 週次の確認でエラーが 一定件数超(残りを打ち切る) |
| 保持期間削除の積み残し | 警告 | 1 回の削除の上限を超え、翌日へ持ち越した | |
| 自動削除の当日通知の欠落 | 警告 | 前日に削除があった Box に、当日の決まった時刻までに通知が 1 件も作られていない | |
| 管理・運用 | ストレージ費用の 80% 超 | 警告 | バケット合計が月予算の 80% 超 |
| Cloud Billing の予算 | 警告 / 重大 | 予算に近づいたとき(警告)/予算を超えたとき(重大)の通知を転記 | |
| 鍵のローテーション期限超過 | 警告 | 最後の入れ替えから 一定期間超 | |
| バケット送出量の異常増加 | 警告 | 対象 4 バケットの当日の送出量が、直前の一定期間の中央値の 一定倍数超かつ下限(既定 1 GiB)以上 | |
| バッチ処理の失敗 | 重大 | 対象のバッチが 1 回でも失敗(未対応の 1 行に畳み込み、一定の間隔で催促) | |
| アカウント | Workspace 停止ユーザ | 警告 / 重大 | 社内ディレクトリで停止されているのに、アプリ側が有効なままの利用者 1 人につき 1 行。Owner の Box を持つ場合は重大 |
| Workspace 身元の不一致 | 警告 / 重大 | 同じアドレスが別人へ再割り当てされた形跡 1 人につき 1 行。Owner の Box を持つ場合は重大 |
種別の名前・日本語の表示名・重大度と状態の日本語は、すべて共有の定数 1 か所が持っています。種別が増えると、関連する対応表(表示名・アイコン・系統・推奨アクション)の型が合わなくなり、コンパイルの時点で落ちます。更新の漏れが本番まで届きません。
1 種だけ、退役したものがあります
当初は 30 種でしたが、1 種(Drive のゴミ箱送り失敗)を退役させて 29 種になりました。理由は、起票する経路が一度も存在しなかったこと、そしてその失敗の形はほかの 2 つの仕組み(同期ジョブの失敗記録・配信不能の監視)で二重に見えていることが分かったためです。鳴らない枠を残すと、「この種類は本番で 1 件も出ていない」と「この種類は動いていない」が区別できなくなります。
起票元の 4 系統Where Alerts Come From
29 種は、性質の違う 4 つの場所から起票されます。実行体は Node.js 側と Go 側にまたがりますが、書き込み先は1 つのテーブルです。
系統 ① は「起きた瞬間に、その処理がそのまま書く」形です。ほかの 3 つは「あとから数えて気づく」形で、こちらは何も起きていないことを異常と判定するケースを含みます(通知が作られていない・同期が動いていない)。同じ 1 つのテーブルに集めているので、運用する人は 1 か所だけ見ていれば済みます。
6 つの検知器Six Detectors
dlq-monitor という 1 つのバッチが、5 分ごとに 6 つの検知器を順に回します。見る先はアプリのデータベースが 5 つ、クラウドの監視から数値を取るものが 1 つです。
| # | 検知するもの | 見る先 | 述語 | しきい値 |
|---|---|---|---|---|
| ① | スキャン滞留 | アプリ DB | 検査中のまま進んでいないファイルの版の件数 | > 一定件数 |
| ② | イベント配信の滞留 | アプリ DB | 再試行の上限に達したイベントの件数 | > 0 |
| ③ | 配信不能メッセージの超過 | クラウドの監視 | 配信できずに溜まったメッセージの全数の合計 | > 一定件数 |
| ④ | メールバウンス率の上昇 | アプリ DB | 直近 24 時間の(不達 + 苦情)÷ 送信の試行 | > 一定の割合 分母が一定以上 |
| ⑤ | 通知配送の滞留 | アプリ DB | 送信待ちのまま 30 分を超えた宛先の件数 | ≥ 1 |
| ⑥ | 削除当日通知の欠落 | アプリ DB | 前日に削除があった Box のうち、当日の決まった時刻までに通知が作られていないもの | ≥ 1 |
6 つを互いに独立に回す
6 つは順番に、しかし互いに独立に回します。1 つが例外で落ちても残りは実行し、失敗はその場でログに出したうえで、全部を試したあとにまとめて投げ直します(バッチが異常終了 → 5 分後に再実行)。
1 つの失敗で全部が止まる作りにすると、この仕組み自身が「静かな欠落」を作ってしまいます。塞ぐつもりの穴を検知器が自分で開けることになるので、ここは最初から独立に組んでいます。
滞留の検知に、なぜ 2 つの検知器が要るのか
② と ③ は名前が似ていますが、別の故障を見ています。片方がもう片方の代わりにはなりません。
| 検知器 | 見ているもの | そのとき何が起きているか |
|---|---|---|
| ② イベント配信の滞留 | アプリ側の「送り出しに失敗して溜まったもの」 | アプリからイベントを発行できていない(権限不足・宛先の不在など)。再試行の上限に達して残る |
| ③ 配信不能メッセージの超過 | クラウド側の「発行はできたが受け取り側が処理できないもの」 | 発行は成功している。受け取る側が上限回数まで失敗して、配信できないメッセージの置き場に溜まっている |
⑤ が別にあるのも同じ理由です。通知を実際に届ける段には、配信できないメッセージの置き場という概念がありません。試行の回数を使い切った依頼は痕跡なく消えます。そのとき宛先の状態は「送信待ち」のまま残るので、画面の「配信失敗」の一覧にも現れません。画面にもログにも監視にも出ない完全な死角だったため、「送信待ちのまま 30 分超」を数える検知器を足しました。
鳴らし直さない仕組みSuppression
5 分ごとに数える形にすると、素朴に作れば滞留が続くあいだ 5 分ごとに 1 行ずつ増えます(12 行 / 時間・288 行 / 日)。これでは一覧が使えません。
対処は「時間の窓で止める」ではなく、解決済み以外の同じ種類の行がある間は起票しない方式です。時間の窓(たとえば 24 時間)にすると、管理者が対応中で抱えている案件が翌日また新しい行として湧いてきます。
「件数が増えたときだけ鳴らし直す」のは、既存の 1 行に新しい欠落を埋めてしまわないためです。25 件で立てた行に 40 件目までを黙って含めると、「25 件の話」として対応したつもりが実際は 40 件だった、という食い違いが起きます。この扱いをするのは配送・滞留に関わる 3 種で、残りは件数が増えても鳴らし直しません。
調査中は「対応中」が正しい一手
5 分ごとに数える種類のアラートでは、「解決」を押すと同じ内容の再通知が再開します。まだ滞留が続いている状態で解決にすると、数分後に新しい行が立ちます。これは仕様どおりの動きですが、知らないと「何度も同じアラートが出る」と見えます。
そこで、この 5 種類の推奨アクションの文の末尾には共通の一文が付いています。「調査中は『対応中』にしてください」という案内で、こうすると同じ内容の再通知が止まったままになります。
条件が消えたら自動で閉じるAuto-Resolve
一部の種類は、条件が消えたことを検知器が観測した時点で、自動的に解決済みになります。人が押す必要がありません。
| 種別 | 閉じる条件 |
|---|---|
| イベント配信の滞留 | 溜まっていたイベントが 0 件になった(再投入も破棄も、結果として 0 になれば閉じる) |
| 通知配送の滞留 | 送信待ちのまま 30 分超の宛先が 0 件になった |
| 自動削除の当日通知の欠落 | 欠けていた通知が作られた |
| Workspace 停止ユーザ | 利用者が復帰した、またはアプリ側でも無効化された |
| Workspace 身元の不一致 | 記録との食い違いが解消された |
自動で閉じる仕組みを入れた理由は、逆の状態が実際に起きたからです。本番で「イベント配信の滞留」のアラートが 1 件、未対応のまま残っていました。中身のイベントは既に処分済みで、検知の条件はもう消えていたのに、アラートだけが残っていた形です。
手で解決できない 2 種類
逆に、Workspace 系の 2 種類は手で「解決」にできません。条件が消えると自動で閉じる作りなので、手で閉じても翌日の同期でまた未対応に戻ります。押せるのに翌日戻るボタンは嘘なので、窓口が拒否し、画面はそのボタン自体を出しません(二重の防御)。「対応中」(判断を保留する)と「無視」は選べます。
届け方Delivery
3 つの経路で届きます。管理画面を開いていない時間帯にも届く必要があるので、メールが要ります。逆に、メールだけだと埋もれるので画面が要ります。
| 経路 | 内容 | 対象 |
|---|---|---|
| 画面の一覧 | 種別・重大度・状態で絞り込める一覧。30 秒ごとに自動で更新される。新しい重大なアラートは自動で消えない通知で知らせる | 29 種すべて |
| メール | 共通の文面 2 通(重大 / 警告)で配送。種別ごとに受け取りを止められます | 23 種 |
| 個別の文面のメール | ウイルス検出・内容の不一致・Drive 同期の失敗 2 種・共有リンクの総当たりは、専用の文面(4 通)で先に届く。宛先の解決も別で、アップロードした人や Box の Owner にも届く | 5 種 |
| 件数バッジ | すべての管理画面の上部に、未対応の件数を常設。0 件のときは出しません。押すとアラートの一覧へ移動する | 未対応の合計 |
29 種のうち共通の文面で送らないのは 6 種です。うち 5 種は上の「個別の文面」が受け持ち、残る 1 種(アップロード整合性エラー)は意図的にメールを送っていません。この事象は提出者側の再アップロードで解消するもので、管理者が即座に動く必要がないためです(画面の一覧には出ます)。
本番での実例Production Record
本番で仕組みが実際に事象を捕まえた例を 1 つ取り上げます。
「イベント配信の滞留」1 件の中身
この 1 件は、この資料でいちばん説明したい形の故障です。ファイルの検査完了を伝えるイベントが、発行の権限が足りないために送れず、再試行の上限に達して溜まりました。
- 画面にはエラーが出ていません。利用者から見て、ファイルは正常にアップロードされています。
- クラウド側の監視にも異常が出ていません。サービスは正常に応答しています。
- 結果として起きたのは「通知メールだけが出ない」ことです。これは、受け取る側が「来ていない」と申告するまで誰にも見えません。
5 分ごとの検知器がこれを拾い、アラートの自由項目に内訳を残しました。どの種類のイベントが何件、いちばん古いものはいつ発生したか、直近のエラーは何か、です。この 4 つが揃っていたので、原因の特定はすぐに済みました。