外部 Synthetic Healthcheck — Worker outage 検知

SSoT 参照: 通知 channel / severity 振り分けは notification-strategy.md で定義。 本 runbook は GH Actions cron 実装 + Discord webhook 配線 + 本格化 (Cloudflare Health Checks) 移行手順のみ扱う。

dev fail → P1 (#p1-ops)、prod fail → P0 (#p0-alerts + @here) に振り分け済 (commit 956c8c6d)。workflow_dispatch の input force_fail=true で smoke 発火可。

監査 2026-04-29 #1 Operations Critical 対策。
「外部 synthetic 監視ゼロ — Worker outage 検知が user 報告依存」を解消する。

現状 (2026-04-29)

  • 暫定: .github/workflows/synthetic-healthcheck.yml で 5 分粒度の GH Actions cron 監視を稼働中。失敗時 Discord 通知。
  • 本格: Cloudflare Health Checks (Pro plan 必要 / より高頻度 / 別 region から probe) は未設定 (M-04 manual)。
  • 内部 cron warmer (api/src/cron/warmer.ts) は Worker 自身が動いている前提なので、Worker 全停止検知には使えない。

GH Actions 暫定実装の特性

項目
監視頻度 5 分間隔 (GH Actions cron 最短粒度)
監視 region GH Actions runner = 現状 ubuntu-22.04 (US/EU 中心)
失敗判定 HTTP != 200 OR body の ok != true連続 2 回 確認したら通知 (transient flap 対策で 5 秒 sleep + retry)
通知先 Discord webhook (matrix で parky-api-dev は warning 黄色 / parky-api-prod は critical 赤 + @here mention)
通知先未設定時 warning ログのみ (workflow は走り続ける)
Actions UI probe 失敗時は最終 step で exit 1 し job が赤くなる (履歴で過去失敗を辿れる)

本構成の限界

  • GH Actions cron は SLA 緩い — 5 分後に正確に走る保証はなく、重い時間帯に最大 +10 分遅延する事例あり。本気で 1 分粒度 SLA が必要なら有料 monitor 必須。
  • Region 偏重 — GH Actions runner は US/EU 中心。日本 user が体験する outage を完全に再現できない。
  • GH Actions 自体が落ちると盲目 — GitHub status page は別 channel で監視する想定。

セットアップ手順 (user manual)

1. Discord webhook (notification-strategy.md SSoT 準拠)

5 channel × 1 webhook 構成。本 workflow は severity に応じて 2 本を参照する:

severity channel GH Secret
critical (prod) #p0-alerts DISCORD_WEBHOOK_ALERTS
warning (dev) #p1-ops DISCORD_WEBHOOK_OPS

Webhook URL の発行 + 1Password 登録 + GH Secret 一括投入手順は notification-strategy.md §10 Phase 1 参照。 旧 DISCORD_HEALTHCHECK_WEBHOOK_URL (#system-alerts 単一 webhook) は廃止済。

2. 動作確認

  • 通常モード: gh workflow run synthetic-healthcheck.yml --ref main で手動 dispatch。 healthz が緑なら Discord には何も出ない (= 正常)。
  • smoke モード: gh workflow run synthetic-healthcheck.yml --ref main -f force_fail=true で probe を skip し Discord notify path を強制発火。alert は subject に [SMOKE] prefix + 説明 field 付きで投稿される。job 自体は green を維持。
  • 既存通知 (実 outage 検知時): subject [P1] healthcheck FAILED — parky-api-dev (dev) または [P0] ... — parky-api-prod (prod) の embed が該当 channel に届く。

本格移行 (Cloudflare Health Checks)

GH Actions cron を捨てる必要はないが、以下を追加すると 1 分粒度 + 多 region monitor になる。

前提

  • Cloudflare Pro plan 以上 (Health Checks は Free 不可)
  • monitor 1 つ = $0 (Pro plan 内)、追加 monitor は $5/mo each (5 個まで Pro 標準)

手順

  1. Cloudflare Dashboard → TrafficHealth ChecksCreate
  2. Name: parky-api-prod-healthz
  3. Target: api.parky.co.jp/healthz / Method: GET / Interval: 60s / Expected status: 200
  4. Notification: Slack / Discord webhook (Cloudflare → Notifications → New → Webhook)
  5. dev も同様に dev-api.parky.co.jp/healthz で別 monitor (interval 5min で十分)

移行後の役割分担

監視 カバー
Cloudflare Health Checks 1 分粒度の本体 outage 検知 (主役)
GH Actions cron 5 分粒度のバックアップ + Cloudflare 自体の障害時の fallback
Sentry alert (M-02) 5xx burst / error rate spike (機能別 tracking)

関連

  • 監査レポート: .work/parky/2026-04-29_001_parky_comprehensive_evaluation_v2.html
  • M-04 (manual checklist): .work/parky/2026-04-28_002_parky_manual_action_checklist.html
  • /healthz 実装: parky/api/src/app-core.ts (現状は { ok: true, time } のみ。将来 deep health 化で DB ping + R2 ping 追加予定)
↗ Source markdown (synthetic-healthcheck.md)