InfraGuard

問題解決(インシデントケース)

障害やエラーを、登録 → 調査中 → 原因特定 → 解決 → 終了 の流れで追跡し、直接原因・根本原因・復旧措置・再発防止策を記録するインシデントケースのワークフローです。

概要 — 何をする画面か

問題解決 は、サービス役割領域のインシデントケースのワークフローです。障害・エラー・性能低下を1つのケースとして登録し、ステータスのパイプライン 登録 → 調査中 → 原因特定 → 解決 → 終了 に沿って進めながら、各ステップで調査内容・原因・対処を記録します。事後検証(ポストモーテム)と再発防止策の台帳も兼ねます。

データはすべて infr_incident テーブル1つに保存され、この画面が扱うのは area='service' の行だけです。セキュリティ問題解決 画面は同じテーブルを area='security' で共有します — スキーマは同一で、ボードだけが分かれています。

各ケースには、正式な事後報告書に倣った4つの原因・対処フィールドがあります。

フィールド 意味 例
direct_cause 障害を直接引き起こした表面的な要因 mysql の接続数上限を超過(Too many connections)
root_cause その表面的な原因を生んだ背景的な理由 5分周期の cron スクリプトが接続を返さない → リーク → 上限が枯渇
resolution 障害中にサービスを復旧させた対処 接続の整理、プロセスの再起動、即時復旧のための上限引き上げ
action_taken 再発を防ぐための恒久対策 MAX_USER_CONNECTIONS で専用アカウントを隔離、スクリプトを修正、監視警報を追加

この画面は、以前の「SLA & Uptime」メニューから改名されたものです(名前空間 sla → resolution)。稼働率目標の KPI(uptime_target)はそのまま維持されています。


どんなときに使うか


画面構成

KPI ストリップ

上部の KPI は area='service' のケース全体から算出されます。

KPI 算出方法
合計(total) サービスケースの件数
対応中(active) open + investigating + cause_identified の合計
解決済み(resolved) resolved + closed の合計
MTTR(mttr_min) (解決時刻 − 発生時刻)の平均(分)。occurred_at と resolved_at の両方があるケースのみが対象
累計ダウンタイム(downtime_min) 各ケースの downtime_min フィールドの単純合計(分)
稼働率目標(uptime_target) 運用ポリシーの sla_uptime_target(既定 99.9%)

正確な MTTR を得るには、ケースに発生時刻(occurred_at)を入力し、解決への遷移で resolved_at を自動的に記録させてください。発生時刻のないケースは MTTR の平均から除外されます。

ケースボード

ケースはカード/行として一覧表示され、次の優先順位でサーバー側(コントローラーで raw SQL を使わないよう PHP で)ソートされます。

  1. ステータス順位: open → investigating → cause_identified → resolved → closed
  2. 深刻度順位: crit → warn → info
  3. 新しい id が先

このため、対応中で・深刻で・新しいケースが上位に浮かび上がります。

各カードには、ソースバッジ(手動/Pulse/警報/外部機関/隔離/検知からの昇格)、深刻度、ステータス、プロジェクト名、発生時刻、ダウンタイム、イベント数が表示されます。

詳細モーダル

ケースを開くと、左側にレポート(概要・直接原因・根本原因・復旧措置・再発防止策)、右側にタイムライン(ステータス変更・ノート)が表示され、上部にパイプラインの遷移ボタンが並びます。


使い方

1) ケースを登録する

[Register case] → モーダルフォーム。作成時には source='manual'、area='service'、status='open' で保存され、detected_at はサーバー側で記録され(now())、タイムラインに created イベントが追加されます。

フィールドと入力制限:

フィールド 必須 制限
title ✔ 最大 200 文字
severity info/warn/crit — 空欄の場合は warn が既定(運用ポリシーの incident_default_severity)
project_id infr_project に存在する必要があります
service_id infr_service に存在する必要があります
url 最大 255 文字
occurred_at 日付
summary 最大 4000 文字
direct_cause / root_cause / resolution / action_taken それぞれ最大 4000 文字
downtime_min 整数、≥ 0
impact 最大 191 文字

2) ステータス遷移(パイプライン)

詳細モーダルで次のステップのボタンをクリックすると、ステップ遷移ダイアログが開きます。各ステップには「このステップで何をするか」が説明され、そのステップに関係するレポート項目を入力できます。送信した項目だけが更新されるため、ステータスを変えずに原因を追記したり、レポートだけを充実させたりできます。

ステップ コード このステップですること
登録 open ケースを受付状態(調査前)に戻します
調査中 investigating 症状を確認し、影響範囲を切り分け、概要を記述します
原因特定 cause_identified 直接原因と、その背景にある根本原因を特定して記録します
解決 resolved 適用した復旧方法と再発防止策を記録します
終了 closed 対処と再発防止策が実施済みであることを確認し、ケースを終了します

遷移のルール:

日付は、有効な UI ロケール(window.__locale)に結び付けた toLocaleString で描画されるため、EN モードでも月や時刻が正しく表示されます。

3) 協業ノート

詳細モーダルでノートを追加すると、タイムラインに kind='note' イベントが追加されます(ノートは infr_incident_event に統合されており、専用のノートテーブルはありません)。本文は最大 4000 文字です。

4) 削除

ケースを削除すると、そのインシデントと紐づく infr_incident_event の行がまとめて削除されます。元に戻すことはできません。

5) 自動取り込み(Pulse / 例外レポーター)

外部の Laravel アプリがインシデント取り込み API(POST /api/v1/incidents)へ例外を送信すると、IncidentIngestService がそれを処理し、このボードへ自動的に登録します。

キーと連携コードは 管理 ▸ APIキー で管理します。


データソース

テーブル 役割
infr_incident ケース本体。この画面は area='service' のみを照会します。マイグレーション 000719(+ 000723 取り込みフィールド・000731 area・000732 source 拡張)
infr_incident_event タイムライン(追記のみ)。kind = created/note/action/status_change/cause/resolution/alert_added。created_at のみを使用(マイグレーション 000720)
infr_project プロジェクトのドロップダウン・カードのプロジェクト名
infr_service サービスのドロップダウン
infr_audit_log 作成・更新・遷移・削除の監査証跡

主な infr_incident のカラム: source, area, title, severity, status, project_id, service_id, url, occurred_at, detected_at, resolved_at, closed_at, summary, direct_cause, root_cause, resolution, action_taken, downtime_min, impact, fingerprint, occurrence_count, last_occurred_at, api_key_id, created_by, updated_by。

既定値は運用ポリシーの OpsPolicy::slaDefaults() から読み込まれます。

sla_uptime_target         = 99.9   # SLA 目標稼働率(%)
incident_default_severity = warn   # 登録時の既定の深刻度(info|warn|crit)

ルート:

GET  /service/resolution              index(ボード)
GET  /service/resolution/live         live  (JSON ポーリング更新)
POST /service/resolution/save         ケースの登録/更新
POST /service/resolution/transition   ステータス遷移(+ ステップ別レポート/closed_at)
POST /service/resolution/note         協業ノートの追加
POST /service/resolution/delete       ケースの削除

アクセス権限

操作 必要レベル
ボードの閲覧(index/live) 認証済みユーザー(infr.auth、レベル ≥ 1)
登録・更新・遷移・ノート・削除 レベル ≥ 2

すべての書き込み(登録・更新・遷移・削除)は infr_audit_log に incident.create / incident.update / incident.transition / incident.delete として記録され、実行者と前後のステータスが残ります。レベルの体系については RBAC レベル を参照してください。


トラブルシューティングと FAQ

Q. MTTR が空欄/値なしで表示されます。 MTTR の平均に含まれるには、ケースに発生時刻(occurred_at)と解決時刻(resolved_at)の両方が必要です。発生時刻を入力したか、解決への遷移で resolved_at が記録されたかを確認してください。

Q. 累計ダウンタイムが 0 と表示されます。 ダウンタイムの KPI は各ケースの downtime_min フィールドの単純合計です。ケースにダウンタイム(分)を入力する必要があり、発生時刻と解決時刻から自動的に算出されるわけではありません。

Q. Pulse のケースが表示されません。 取り込まれたケースは source='pulse' で area は未設定のため、既定の service となりここに表示されます。それでも見当たらない場合は、(1) API キーが有効か、(2) 同じフィンガープリントがすでに未解決のケースへ重複排除されていないか(occurrence_count が加算されただけ)を確認してください。セキュリティのインシデントは、このボードではなく セキュリティ問題解決(area='security')に表示されます。

Q. 終了時刻を過去に設定できますか。 できます。closed 遷移ダイアログの終了時刻(flatpickr)フィールドに希望の時刻を入力すると、その値が保存されます。空欄のままにすると、サーバーの現在時刻(now())が使われます。

Q. ステータスを変えずに原因だけ追記したいです。 遷移ダイアログは、送信した項目だけを更新します。同じステータスへ遷移しながらレポート項目を入力すれば、ステータス変更イベントを発生させずにレポートを更新できます(あるいはケースを直接編集してください)。

Q. 削除したケースは復元できますか。 できません。削除するとケースとそのタイムラインイベントがすべて消え、元に戻せません。削除操作そのものは監査ログに記録されます。


関連項目

문제 해결 — 인시던트 보드
문제 해결 — 인시던트 보드