監視とは「システムが今どういう状態かを継続的に把握する仕組み」。問題をユーザーより先に自分が気づくための仕組み。
| 種類 | 内容 | 例 |
|---|---|---|
| メトリクス | 数値で表せる状態の記録 | CPU使用率・レスポンスタイム |
| ログ | テキストのイベント記録 | エラーログ・アクセスログ |
| トレース | リクエストの処理経路の記録 | DB→API→UIの流れ |
この3つをまとめて**オブザーバビリティ(可観測性)**と呼ぶ。
💡 ポイント: 「監視はOpsだけの仕事」はアンチパターン。アプリを一番知っているエンジニアが監視設計を担うべき。
時間とともに変化する数値の記録。時系列で並べることで「いつから悪化したか」が見える。
| 種類 | 例 |
|---|---|
| インフラ系 | CPU・メモリ・ディスク使用率 |
| アプリ系 | レスポンスタイム・エラー率 |
| ビジネス系 | 注文数・アクティブユーザー数 |
Utilization : 使用率(CPUが何%使われているか)
Saturation : 飽和度(キューに詰まっていないか)
Errors : エラー数
Rate : リクエスト数(毎秒何件来ているか)
Errors : エラー率(何%失敗しているか)
Duration : 処理時間(どのくらいかかるか)
Rate → Vercel Analytics のリクエスト数
Errors → Vercel のError率 / Supabase の Failed Queries
Duration → Vercel のレスポンスタイム / Supabase の Query Time
💡 ポイント: ユーザー向けの問題(ログインできない等)はREDで追う。インフラの根本原因調査にはUSEを使う。RED → USE の順で掘り下げる。
「何かが起きた瞬間のテキスト記録」。メトリクスで異常を検知した後、詳細の原因調査に使う。
| レベル | 用途 |
|---|---|
| DEBUG | 最も詳細。開発中のみ使用 |
| INFO | 正常な動作の記録 |
| WARN | 注意が必要だが問題ではない |
| ERROR | 処理が失敗した |
| FATAL | システムが継続不能な致命的エラー |
本番環境では INFO 以上だけ出力するのが一般的。
// middleware/logger.ts(Hono)
app.use('*', async (c, next) => {
const start = Date.now()
await next()
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: c.res.status >= 400 ? 'ERROR' : 'INFO',
method: c.req.method,
path: c.req.path,
status: c.res.status,
duration_ms: Date.now() - start,
userId: c.get('userId') ?? null
}))
})
💡 ポイント: JSON形式にすることで検索・集計・フィルタリングが格段にしやすくなる。Vercelは
console.logを自動キャプチャしてLogsタブで確認できる。
異常を検知したときに人に通知する仕組み。多すぎるとアラート疲れを引き起こす。
✅ 今すぐ人間が対応する必要がある
✅ ユーザーに影響が出ている(or 出る)
❌ 参考情報として知りたいだけ
❌ 自動復旧するかもしれない
| 種類 | 例 | 評価 |
|---|---|---|
| 原因ベース | CPU使用率 > 80% | ❌ ユーザー影響と直結しない |
| 原因ベース | DBコネクション数 > 100 | ❌ 同上 |
| 症状ベース | エラー率 > 1% が5分以上 | ✅ ユーザー影響に直結 |
| 症状ベース | レスポンスタイム P99 > 3秒 | ✅ 同上 |
💡 ポイント: 「継続時間の条件をつける」ことで一時的なスパイクによる誤発火を防げる。
サーバー側が正常でも、ブラウザ上で問題が起きていることがある。サーバーのログだけでは気づけない。
| 指標 | 内容 | 良い値 |
|---|---|---|
| LCP | 最大コンテンツの描画時間 | 2.5秒以内 |
| INP | 操作への応答速度 | 200ms以内 |
| CLS | レイアウトのズレ具合 | 0.1以下 |
| 種類 | 仕組み | 得意なこと |
|---|---|---|
| RUM(リアルユーザー監視) | 実際のユーザーのブラウザで計測 | 地域・デバイス差の把握 |
| 合成監視 | ロボットが定期アクセスして計測 | ユーザーがいない時間帯の監視 |
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics /> {/* ユーザー行動の計測 */}
<SpeedInsights /> {/* Core Web Vitals の計測 */}
</body>
</html>
)
}
💡 ポイント: RUMはユーザーがいないと計測できない。深夜・障害直後など「ユーザーがいない状況」の監視は合成監視が唯一の手段。
「レスポンスが遅い」とわかった次に、「どこで時間がかかっているか」を特定するのがAPMの役割。
リクエスト受信 [0ms]
↓
認証チェック [0ms → 20ms] 20ms
↓
DBクエリ実行 [20ms → 280ms] 260ms ← 🐌 ここが遅い
↓
レスポンス返却 [280ms → 300ms] 20ms
P50 (中央値) : 120ms ← 半分のユーザーはこれ以下
P95 : 800ms
P99 : 3200ms ← 1%のユーザーは3秒以上待っている
平均値 : 150ms ← P99の問題が平均値には隠れる
app.use('*', async (c, next) => {
const traceId = crypto.randomUUID()
const start = Date.now()
await next()
console.log(JSON.stringify({
traceId,
path: c.req.path,
status: c.res.status,
total_ms: Date.now() - start,
}))
})
// DBクエリ時間も個別に計測
const queryStart = Date.now()
const { data } = await supabase.from('orders').select('*')
console.log(JSON.stringify({
traceId,
step: 'supabase_query',
duration_ms: Date.now() - queryStart
}))
💡 ポイント: 平均値だけ見るのは危険。P99が高い = 一部ユーザーが極端に遅い体験をしている。よくある原因はN+1クエリ・インデックス不足・外部APIタイムアウト。
① 検知 → アラート発火 / ユーザー報告
② トリアージ → 重大度の判定
③ 対応 → 原因特定 → 暫定対処(復旧優先)
④ 解消 → 根本原因の修正
⑤ 振り返り → ポストモーテム
| レベル | 状況 | 対応速度 |
|---|---|---|
| SEV1 | サービス全停止 | 即時(夜中も) |
| SEV2 | 主要機能が使えない | 30分以内 |
| SEV3 | 一部機能に影響 | 営業時間内 |
| SEV4 | 軽微・ユーザー影響なし | 計画的に対応 |
✅ blame-free(犯人探しをしない)
✅ タイムラインを時系列で記録する
✅ 再発防止策を「仕組み」として決める
❌ 「〇〇さんのミスが原因」で終わらせない
❌ 再発防止策が「気をつける」になっている
## インシデント概要
- 発生日時 / 解消日時 / 影響範囲 / 重大度
## タイムライン
- HH:MM アラート発火
- HH:MM 原因特定
- HH:MM 復旧完了
## 根本原因
(人ではなく仕組みの問題として記述)
## 再発防止策
- [ ] 具体的なアクション(チェックリスト形式)
💡 ポイント: 「人を責めるな、システムを責めろ」。どんな優秀なエンジニアでもミスはする。ミスが起きても障害にならない仕組みを作ることが目的。
「ツールより先に、何を監視するかを決めろ」
監視したい対象を決めてからツールを選ぶ。ツールを先に選ぶと、そのツールで計測できるものしか監視しなくなる。
| 用途 | ツール例 |
|---|---|
| メトリクス収集 | Prometheus, Datadog, Grafana |
| ログ管理 | Datadog Logs, Loki, Axiom |
| APM / トレース | Datadog APM, Sentry, New Relic |
| フロントエンド | Vercel Analytics, Sentry |
| アラート通知 | PagerDuty, OpsGenie, Slack連携 |
| 合成監視 | Checkly, Datadog Synthetics |
| 領域 | ツール | 備考 |
|---|---|---|
| フロントエンド | Vercel Analytics + Speed Insights | Core Web Vitalsが自動計測 |
| エラー監視 | Sentry | JS例外・APIエラーを捕捉 |
| ログ | Vercel Log Drains → Axiom | 長期保存・高度な分析 |
| DB監視 | Supabase Dashboard | クエリ時間・接続数 |
| アラート通知 | Slack連携 | Sentry / Vercel → Slack |
① まず入れる(コストほぼゼロ)
Vercel Analytics + Speed Insights
Supabase Dashboard の確認習慣
② 次に入れる
Sentry(無料枠でスタート可能)
③ 規模が大きくなったら
Datadog / Axiom / PagerDuty
💡 ポイント: フルスタック型(Datadog等)は管理が楽だがコスト高。組み合わせ型はOSSで安く抑えられるが管理が複雑。規模に合わせて選ぶ。
| ミス | 改善策 |
|---|---|
| CPU使用率にアラートを張る | エラー率・レスポンスタイムなど症状ベースに変える |
| 平均値だけでパフォーマンスを判断する | P95・P99のパーセンタイルも必ず確認する |
| ログを非構造化テキストで出力する | JSON形式の構造化ログにする |
| ポストモーテムで犯人を特定して終わる | 仕組みで再発を防ぐアクションを決める |
| ツールを先に選んで監視対象を決める | 監視したいことを先に決めてからツールを選ぶ |
| RUMだけで監視を完結させる | 合成監視も組み合わせて24時間カバーする |
| 監視をOpsに丸投げする | アプリを作ったエンジニアが監視設計に関わる |
- サーバーが正常でもブラウザ側で障害が起きることがあり、フロントエンド監視は必須だと気づいた
- Vercel Analytics + Speed Insights + Sentry の組み合わせがまず試すべき最小構成として明確になった
- P99の重要性:平均値が正常でも一部ユーザーが極端に遅い体験をしている可能性がある
- ポストモーテムの「blame-free」文化は技術だけでなくチーム設計の話でもある
- REDフレームワークはHonoのミドルウェアで比較的簡単に実装できそう