本文へ移動
松葉 / Matsuba ・ 開発過程資料

異常の検知/ Detection

サーバは動いているのに業務が止まっている、を見つける

ここから後半です。クラウド側の監視は「サービスが応答しない」「バッチが異常終了した」を拾いますが、実際に困るのはサービスは正常なのに業務が前に進んでいない状態です。それを判定するには、アプリのデータベースの中を数える必要があります。この章は、何をどう数えているかを扱います。

01

アプリ独自の 29 種Alert Catalog

全 29 種です。重大度は 2 段(重大 / 警告)で、種別ごとに固定しています。ただし 3 種だけ、影響の範囲によって重大度が変わります。29 種すべてに起票する実装があります(表示だけの枠は残っていません)。

All 29 Alert Kinds
系統種別重大度判定のしきい値
ウイルス
スキャン
ウイルス検出重大感染と判定されたファイル 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 行にまとめるときに文が食い違い、まとめられなくなるためです。

1 種だけ、退役したものがあります

当初は 30 種でしたが、1 種(Drive のゴミ箱送り失敗)を退役させて 29 種になりました。理由は、起票する経路が一度も存在しなかったこと、そしてその失敗の形はほかの 2 つの仕組み(同期ジョブの失敗記録・配信不能の監視)で二重に見えていることが分かったためです。鳴らない枠を残すと、「この種類は本番で 1 件も出ていない」と「この種類は動いていない」が区別できなくなります。

02

起票元の 4 系統Where Alerts Come From

29 種は、性質の違う 4 つの場所から起票されます。実行体は Node.js 側と Go 側にまたがりますが、書き込み先は1 つのテーブルです。

図 10 · アラートの起票元 — 4 系統から 1 つのテーブルへ
4 系統 = 29 種(7 + 6 + 7 + 9)業務処理の中で気づくscanner(Go)/ matsuba-apiウイルス検出ファイル内容の不一致整合性エラースキャン失敗定義の更新失敗総当たりアクセス同一 IP の大量アクセス7 種起きた瞬間に、その処理がそのまま書く5 分ごとに数えるmatsuba-batch / dlq-monitorスキャン滞留イベント配信の滞留配信不能メッセージの超過メールバウンス率の上昇通知配送の滞留削除当日通知の欠落6 種「起きていないこと」を数えて気づく日次の突合matsuba-sync-batch(Go)同期の連続失敗ルート検証の失敗管轄外ファイルの大量検知API クォータの上昇所要時間の上昇単一 Box の上限接近存否確認のエラー7 種日次の全件突合で食い違いに気づく日次・月次のバッチ指標の集計ほか 4 本ストレージ費用の 80% 超予算のアラート鍵の期限超過送出量の異常保持削除の積み残しWorkspace 停止ユーザWorkspace 身元の不一致検出テストの失敗バッチ処理の失敗9 種app_alerts — 29 種 / 7 グループ / 重大・警告説明文は種別ごとの決まった日本語の文。可変の値は別の欄に入れる状態は 未対応 / 対応中 / 解決済み / 無視 の 4 つ/admin/alerts一覧・詳細・状態の変更30 秒ごとに更新メール29 種のうち 23 種は共通の文面4 通は個別の文面で先に届く未対応の件数バッジ全管理画面の上部に常設0 件のときは出さない

系統 ① は「起きた瞬間に、その処理がそのまま書く」形です。ほかの 3 つは「あとから数えて気づく」形で、こちらは何も起きていないことを異常と判定するケースを含みます(通知が作られていない・同期が動いていない)。同じ 1 つのテーブルに集めているので、運用する人は 1 か所だけ見ていれば済みます。

03

6 つの検知器Six Detectors

dlq-monitor という 1 つのバッチが、5 分ごとに 6 つの検知器を順に回します。見る先はアプリのデータベースが 5 つ、クラウドの監視から数値を取るものが 1 つです。

Six Detectors, Every Five Minutes
#検知するもの見る先述語しきい値
①スキャン滞留アプリ DB検査中のまま進んでいないファイルの版の件数> 一定件数
②イベント配信の滞留アプリ DB再試行の上限に達したイベントの件数> 0
③配信不能メッセージの超過クラウドの監視配信できずに溜まったメッセージの全数の合計> 一定件数
④メールバウンス率の上昇アプリ DB直近 24 時間の(不達 + 苦情)÷ 送信の試行> 一定の割合
分母が一定以上
⑤通知配送の滞留アプリ DB送信待ちのまま 30 分を超えた宛先の件数≥ 1
⑥削除当日通知の欠落アプリ DB前日に削除があった Box のうち、当日の決まった時刻までに通知が作られていないもの≥ 1

6 つを互いに独立に回す

6 つは順番に、しかし互いに独立に回します。1 つが例外で落ちても残りは実行し、失敗はその場でログに出したうえで、全部を試したあとにまとめて投げ直します(バッチが異常終了 → 5 分後に再実行)。

1 つの失敗で全部が止まる作りにすると、この仕組み自身が「静かな欠落」を作ってしまいます。塞ぐつもりの穴を検知器が自分で開けることになるので、ここは最初から独立に組んでいます。

取れなかった数値を 0 と報告しない: ③ はクラウドの監視から数値を取ります。この取得に失敗したとき、「0 件でした」と報告しません。取得の失敗としてそのまま失敗させます。0 と報告すると「配信不能は起きていない」と読めてしまい、しかも画面にもログにも異常が出ません。これは、この仕組みがいちばん避けたい形です。

滞留の検知に、なぜ 2 つの検知器が要るのか

② と ③ は名前が似ていますが、別の故障を見ています。片方がもう片方の代わりにはなりません。

Two Different Failures
検知器見ているものそのとき何が起きているか
② イベント配信の滞留アプリ側の「送り出しに失敗して溜まったもの」アプリからイベントを発行できていない(権限不足・宛先の不在など)。再試行の上限に達して残る
③ 配信不能メッセージの超過クラウド側の「発行はできたが受け取り側が処理できないもの」発行は成功している。受け取る側が上限回数まで失敗して、配信できないメッセージの置き場に溜まっている

⑤ が別にあるのも同じ理由です。通知を実際に届ける段には、配信できないメッセージの置き場という概念がありません。試行の回数を使い切った依頼は痕跡なく消えます。そのとき宛先の状態は「送信待ち」のまま残るので、画面の「配信失敗」の一覧にも現れません。画面にもログにも監視にも出ない完全な死角だったため、「送信待ちのまま 30 分超」を数える検知器を足しました。

04

鳴らし直さない仕組みSuppression

5 分ごとに数える形にすると、素朴に作れば滞留が続くあいだ 5 分ごとに 1 行ずつ増えます(12 行 / 時間・288 行 / 日)。これでは一覧が使えません。

対処は「時間の窓で止める」ではなく、解決済み以外の同じ種類の行がある間は起票しない方式です。時間の窓(たとえば 24 時間)にすると、管理者が対応中で抱えている案件が翌日また新しい行として湧いてきます。

図 11 · 5 分ごとの観測と、起票するかどうかの判定(例:スキャン滞留・しきい値 N 件超)
5 分ごとの観測(例:スキャン滞留・しきい値 N 件超)00:0000:0500:1000:1500:20観測した件数122525400しきい値を満たすか満たさない満たす満たす満たす満たさない解決済み以外の同種—無い有る(報告 25)有る(報告 25)有る(報告 40)起票するかしないするしないする(増えたため)しない画面で見えるもの何も出ない1 行目が現れる変わらない2 行目が現れる変わらない(自動で解決する種類はここで解決)状態の選び方が、再通知の有無を決める「対応中」も「無視」も同じ内容の再通知を止める(抱えている案件を毎日鳴らし直さない)「解決」にすると再通知が再開する。条件が続いていれば数分後に新しい行が立つ(正直な再発通知)前回の報告件数が読めないときは 0 として扱い、鳴らす側に倒す

「件数が増えたときだけ鳴らし直す」のは、既存の 1 行に新しい欠落を埋めてしまわないためです。25 件で立てた行に 40 件目までを黙って含めると、「25 件の話」として対応したつもりが実際は 40 件だった、という食い違いが起きます。この扱いをするのは配送・滞留に関わる 3 種で、残りは件数が増えても鳴らし直しません。

調査中は「対応中」が正しい一手

5 分ごとに数える種類のアラートでは、「解決」を押すと同じ内容の再通知が再開します。まだ滞留が続いている状態で解決にすると、数分後に新しい行が立ちます。これは仕様どおりの動きですが、知らないと「何度も同じアラートが出る」と見えます。

そこで、この 5 種類の推奨アクションの文の末尾には共通の一文が付いています。「調査中は『対応中』にしてください」という案内で、こうすると同じ内容の再通知が止まったままになります。

05

条件が消えたら自動で閉じるAuto-Resolve

一部の種類は、条件が消えたことを検知器が観測した時点で、自動的に解決済みになります。人が押す必要がありません。

Kinds That Close Themselves
種別閉じる条件
イベント配信の滞留溜まっていたイベントが 0 件になった(再投入も破棄も、結果として 0 になれば閉じる)
通知配送の滞留送信待ちのまま 30 分超の宛先が 0 件になった
自動削除の当日通知の欠落欠けていた通知が作られた
Workspace 停止ユーザ利用者が復帰した、またはアプリ側でも無効化された
Workspace 身元の不一致記録との食い違いが解消された

自動で閉じる仕組みを入れた理由は、逆の状態が実際に起きたからです。本番で「イベント配信の滞留」のアラートが 1 件、未対応のまま残っていました。中身のイベントは既に処分済みで、検知の条件はもう消えていたのに、アラートだけが残っていた形です。

手で解決できない 2 種類

逆に、Workspace 系の 2 種類は手で「解決」にできません。条件が消えると自動で閉じる作りなので、手で閉じても翌日の同期でまた未対応に戻ります。押せるのに翌日戻るボタンは嘘なので、窓口が拒否し、画面はそのボタン自体を出しません(二重の防御)。「対応中」(判断を保留する)と「無視」は選べます。

06

届け方Delivery

3 つの経路で届きます。管理画面を開いていない時間帯にも届く必要があるので、メールが要ります。逆に、メールだけだと埋もれるので画面が要ります。

Three Delivery Paths
経路内容対象
画面の一覧種別・重大度・状態で絞り込める一覧。30 秒ごとに自動で更新される。新しい重大なアラートは自動で消えない通知で知らせる29 種すべて
メール共通の文面 2 通(重大 / 警告)で配送。種別ごとに受け取りを止められます23 種
個別の文面のメールウイルス検出・内容の不一致・Drive 同期の失敗 2 種・共有リンクの総当たりは、専用の文面(4 通)で先に届く。宛先の解決も別で、アップロードした人や Box の Owner にも届く5 種
件数バッジすべての管理画面の上部に、未対応の件数を常設。0 件のときは出しません。押すとアラートの一覧へ移動する未対応の合計

29 種のうち共通の文面で送らないのは 6 種です。うち 5 種は上の「個別の文面」が受け持ち、残る 1 種(アップロード整合性エラー)は意図的にメールを送っていません。この事象は提出者側の再アップロードで解消するもので、管理者が即座に動く必要がないためです(画面の一覧には出ます)。

(画面の画像は掲載していません)
種別の日本語名と重大度、決まった説明文、そして次にやることの案内が入ります。関連する管理画面へのリンクも添えます。
音を鳴らさない判断: 新しい重大なアラートを音で知らせる案は採っていません。管理画面は複数のタブで開かれるので鳴り方が読めず、そして席を外している間に鳴った音は何も情報を残しません。代わりに、自動で消えない画面上の通知・上部の件数バッジ・メールの 3 つで気づける形にしています。
07

本番での実例Production Record

本番で仕組みが実際に事象を捕まえた例を 1 つ取り上げます。

「イベント配信の滞留」1 件の中身

この 1 件は、この資料でいちばん説明したい形の故障です。ファイルの検査完了を伝えるイベントが、発行の権限が足りないために送れず、再試行の上限に達して溜まりました。

  • 画面にはエラーが出ていません。利用者から見て、ファイルは正常にアップロードされています。
  • クラウド側の監視にも異常が出ていません。サービスは正常に応答しています。
  • 結果として起きたのは「通知メールだけが出ない」ことです。これは、受け取る側が「来ていない」と申告するまで誰にも見えません。

5 分ごとの検知器がこれを拾い、アラートの自由項目に内訳を残しました。どの種類のイベントが何件、いちばん古いものはいつ発生したか、直近のエラーは何か、です。この 4 つが揃っていたので、原因の特定はすぐに済みました。

この 1 件が「自動で閉じる」を入れた理由でもあります: 溜まっていたイベントは処分され、検知の条件はすでに消えていました。それにもかかわらず、アラートだけが未対応で残っていました(当時この種類には自動で閉じる仕組みがなかった)。運用画面の一覧に、もう起きていない事象が居座る状態です。ここから「条件が消えたら自動で閉じる」を、この種類にも入れました。