監視の目的は「システムが正しく動いているか」を知ること。よくある誤解は「サーバが落ちていないか確認すること」だが、それは監視の一部に過ぎない。本書が強調するのは 「ユーザーへの影響」から逆算して監視設計をする という考え方だ。
監視対象は大きく5層に分かれる:
[ ビジネス ] ← 売上・ユーザー数・コンバージョン率
[ フロントエンド ] ← ページロード・エラー率
[ アプリケーション ]← レスポンスタイム・例外・ログ
[ サーバ ] ← CPU・メモリ・ディスク
[ ネットワーク ] ← レイテンシ・パケットロス
DjangoアプリをAWS ECS上で動かしている場合、CloudWatchには自動でコンテナのCPU/メモリが届く。しかし「500エラーが増えている」「レスポンスが遅い」はアプリ層の監視を別途設計しないと見えない。
💡 ポイント: 「サーバが生きている ≠ サービスが正常」。死活監視だけでは、スローリークやDB接続枯渇は検知できない。
| 用語 | 説明 |
|---|---|
| 死活監視 | サーバやプロセスが起動しているかを確認する最も基本的な監視 |
| 5層モデル | ビジネス・フロントエンド・アプリ・サーバ・ネットワークの監視対象の分類 |
本書が挙げる代表的なアンチパターンは4つ:
① ツール依存 → ツールを入れること自体が目的になる
② 役割としての監視 → 「監視チームがやること」になり、開発者が無関心になる
③ チェックボックス監視 → アラートを設定したら終わり、中身を見ない
④ 障害対応だけの監視 → 壊れてから見るだけ。予兆を活かせない
特に②が重要で、監視はスキルであって役割ではないというのが本書の核心のひとつ。自分が作ったサービスは自分で監視設計すべき、という考え方だ。監視チームはツールや基盤を提供するのはOKだが、アラートの定義・閾値の設定はアプリ・インフラの担当者自身が行うべきだ。
「CloudWatchアラームを設定した」で安心するのがアンチパターンの典型。CPU 80%超えのアラームを設定しても、それが何を意味するか・どう対応するかが決まっていなければ、アラートは単なるノイズになる。
💡 ポイント: アラートが多すぎて無視されるようになったら、それはすでに監視が機能していないサイン(=アラート疲れ)。
| 用語 | 説明 |
|---|---|
| アラート疲れ | アラートが多すぎて担当者が無視するようになってしまう状態 |
| チェックボックス監視 | 形式的に設定だけして、実態を見ない監視のアンチパターン |
本書が推奨するデザインパターンの核心は 「外から内へ」 の設計順序:
① ユーザーが体験する症状から始める
↓
② その症状を引き起こすアプリ層の指標を定義する
↓
③ その原因を掘り下げるためにサーバ・インフラ層を見る
重要な概念として 「症状 vs 原因」 がある:
| 種別 | 例 | 対応 |
|---|---|---|
| 症状(アラートすべき) | レスポンスタイムが3秒超 | すぐ通知 |
| 原因(調査用) | CPU使用率80% | ダッシュボードで確認 |
| 原因(調査用) | DBコネクション数が上限近い | ダッシュボードで確認 |
CPUが高いこと自体はアラートの理由にならない。「ユーザーに影響が出ているか」が判断基準。CloudWatchでまず設定すべきは 5xxエラー率 や ALBのレイテンシ。CPU/メモリは原因調査用のダッシュボードに置く。
💡 ポイント: 「CPUが80%超えたらアラート」は典型的な原因ベース監視。症状ベースに切り替えるだけで、アラート疲れが大幅に減る。
| 用語 | 説明 |
|---|---|
| 症状ベース監視 | ユーザーへの影響が出ている状態をアラートの基準にする設計 |
| 原因ベース監視 | CPU・メモリ等のインフラ指標をアラートの基準にする(アンチパターン寄り) |
アラートの分類:
┌─────────────────────────────────────┐
│ 緊急(今すぐ起こす) │
│ → ユーザーへの影響が出ている │
│ → 例: 5xxエラー率が5%超 │
├─────────────────────────────────────┤
│ 要対応(営業時間内でOK) │
│ → 放置すると問題になる │
│ → 例: ディスク使用率が70%超 │
│ → 例: SSL証明書の有効期限が30日後 │
├─────────────────────────────────────┤
│ 情報(通知不要・ログだけでOK) │
│ → 記録しておくだけでよい │
│ → 例: デプロイ完了通知 │
└─────────────────────────────────────┘
SSL証明書の有効期限が30日後に切れる場合は「要対応(営業時間内でOK)」。放置すると証明書切れ→サービス停止という深刻な問題になるため、チケット化・担当者通知が必要。7日前なら「緊急」に格上げする等、期限に応じて分類を動的に変える設計もよく使われる。
# Django側でカスタムメトリクスを送信する例
import boto3
cloudwatch = boto3.client('cloudwatch', region_name='ap-northeast-1')
def record_error_rate(error_count, total_count):
cloudwatch.put_metric_data(
Namespace='MyDjangoApp',
MetricData=[{
'MetricName': 'ErrorRate',
'Value': error_count / total_count * 100,
'Unit': 'Percent'
}]
)
このメトリクスに対してCloudWatchアラームで「5%超 → SNS通知 → PagerDuty」のような連携が典型構成。
💡 ポイント: アラートが多すぎて無視されるのが最悪の状態。「アラートを減らす勇気」も監視設計のスキルのひとつ。
| 用語 | 説明 |
|---|---|
| オンコール | 障害発生時に対応する当番制度 |
| インシデント管理 | 障害の検知・対応・振り返りまでの一連のプロセス |
| PagerDuty | アラートをオンコール担当者に通知するツール |
技術指標だけでは「サービスが健全かどうか」を経営層・PdMに伝えられない。技術指標とビジネス指標を橋渡しする設計が必要:
技術指標 ビジネスKPI
─────────────────────────────────────────
5xxエラー率の上昇 → 購入完了率の低下
レスポンスタイム悪化 → 直帰率の上昇
ログイン失敗率の急増 → アクティブユーザー数の減少
DB応答遅延 → 売上・決済完了数の低下
ECサイトで最もビジネスへの影響が大きいカスタムメトリクスは注文完了数(OrderCompleted)。OrderCompleted が突然ゼロになれば、即座に売上ゼロを意味する。
# 注文完了数をカスタムメトリクスとして送信
def order_complete(request):
# ...注文処理...
cloudwatch.put_metric_data(
Namespace='MyDjangoApp/Business',
MetricData=[{
'MetricName': 'OrderCompleted',
'Value': 1,
'Unit': 'Count'
}]
)
CloudWatch Dashboardに OrderCompleted と 5xxエラー率 を並べて表示することで、技術障害がビジネスに与えた影響を即座に可視化できる。
💡 ポイント: ビジネスKPIはシステムごとに異なるので「これを監視すればOK」というテンプレートはない。自分のサービスの「お金を生む動線」を特定することが出発点。
| 用語 | 説明 |
|---|---|
| カスタムメトリクス | CloudWatchに独自定義の指標を送信する仕組み |
| KPI | Key Performance Indicator。ビジネス目標の達成度を測る指標 |
フロントエンド監視はサーバ側では見えない「ユーザーの実体験」を計測する:
パフォーマンス系:
LCP (Largest Contentful Paint) 最大描画タイミング
FID (First Input Delay) 入力遅延
CLS (Cumulative Layout Shift) レイアウトずれ
→ まとめてCore Web Vitalsと呼ぶ
エラー系:
JSエラー率・APIエラー率・404発生数
ユーザー行動系:
直帰率・セッション時間・離脱ポイント
| 目的 | ツール |
|---|---|
| Core Web Vitals | Google Search Console / Lighthouse |
| JSエラー収集 | Sentry |
| ユーザー行動 | Google Analytics / Datadog RUM |
| 合成監視(死活) | CloudWatch Synthetics |
合成監視(Synthetic Monitoring): スクリプトで定期的に動作確認する監視手法。CloudWatch Syntheticsはブラウザを自動操縦して「ログイン→商品閲覧→購入」の一連フローが動くかを定期チェックできる。対になる概念として**リアルユーザー監視(RUM: Real User Monitoring)**があり、実際のユーザーのブラウザから計測データを収集する。
💡 ポイント: 「サーバのレスポンスは200ms」でも「ブラウザでのLCPは4秒」はよくある乖離。ネットワーク・CDN・JS実行時間が上乗せされるから。
| 用語 | 説明 |
|---|---|
| Core Web Vitals | Googleが定めるWebパフォーマンスの主要指標(LCP・FID・CLS) |
| 合成監視 | ボットがシナリオを実行して問題を事前検知する監視手法 |
| RUM | Real User Monitoring。実ユーザーのブラウザからデータ収集する監視手法 |
| 種別 | 役割 | 例 |
|---|---|---|
| ログ | 何が起きたかの記録(テキスト) | ERROR 500 /api/orders/ |
| メトリクス | 数値の時系列データ | リクエスト数、エラー率 |
| トレース | リクエストの処理経路の追跡 | View→DB→Cacheの所要時間 |
「どのDBクエリが遅いか」の調査にはトレースが最も適している。AWSではX-Rayがトレースに対応しており、DjangoにはAWS X-Ray SDKを組み込むことで、スロークエリの特定まで一気通貫で調査できる。
# settings.py - watchtowerでDjangoログをCloudWatch Logsへ転送
LOGGING = {
'version': 1,
'handlers': {
'cloudwatch': {
'class': 'watchtower.CloudWatchLogHandler',
'log_group': '/django/myapp',
'stream_name': 'application',
}
},
'loggers': {
'django': {
'handlers': ['cloudwatch'],
'level': 'WARNING', # WARNING以上をCloudWatchへ送信
}
}
}
watchtower ライブラリを使うとDjangoのログを直接CloudWatch Logsに送れる。CloudWatch Logs Insightsでクエリ検索も可能になる。
💡 ポイント: ログは「障害が起きたときに原因を調べるもの」。メトリクスは「異常を検知するもの」。役割が違うので両方必要。
| 用語 | 説明 |
|---|---|
| トレース | リクエストの処理経路と各ステップの所要時間を記録する仕組み |
| AWS X-Ray | AWSのトレーシングサービス。DjangoアプリのスロークエリをDjangoレベルで追跡可能 |
| watchtower | DjangoのログをCloudWatch Logsに転送するPythonライブラリ |
| CloudWatch Logs Insights | CloudWatch Logsに対してSQLライクなクエリで検索できる機能 |
サーバメトリクスは原因調査用として使うのが正しい位置づけ:
| メトリクス | 目的 |
|---|---|
| CPU使用率 | 継続的な高負荷の検知 |
| メモリ使用率 | メモリリークの早期発見 |
| ディスク使用率 | ログ肥大化・容量枯渇 |
| ロードアベレージ | 処理待ちの蓄積 |
| DB接続数 | 接続枯渇の予兆 |
| SSL証明書期限 | 失効による障害防止 |
メモリリークは時間とともにメモリ使用率が単調増加するパターンとして現れる。放置するとECSタスクがOOM(Out of Memory)でkillされ、タスク再起動が繰り返される状態になる。
// CloudWatch Agent設定(抜粋)
{
"metrics": {
"metrics_collected": {
"disk": {
"measurement": ["used_percent"],
"resources": ["/"]
},
"mem": {
"measurement": ["mem_used_percent"]
}
}
}
}
ECSはタスクが落ちると新しいタスクが立ち上がるため「サーバが落ちた」に気づきにくい。タスク再起動回数もメトリクスとして監視すべき。
💡 ポイント: ECSのCPU/メモリはCloudWatchに自動送信されるが、ディスクやDB接続数はCloudWatch Agentの追加設定が必要。
| 用語 | 説明 |
|---|---|
| OOM | Out of Memory。メモリ不足でプロセスがOSにkillされること |
| ロードアベレージ | CPUの処理待ち行列の長さ。1・5・15分の平均で表示される |
| CloudWatch Agent | EC2やECSにインストールしてOSレベルのメトリクスを収集するエージェント |
| 軸 | 監視対象 |
|---|---|
| 疎通・可用性 | エンドポイントへのHTTPチェック・DNS解決 |
| パフォーマンス | レイテンシ・パケットロス率・帯域使用率 |
| セキュリティ寄り | SSL証明書期限・異常トラフィック(DDoS兆候) |
「特定の地域からだけレイテンシが高い」問題は、アプリサーバやDBは全ユーザーに共通なので、**CDN・エッジロケーションの設定ミスや、その地域とサーバ間の物理的な距離(ネットワーク経路)**が原因であることが多い。「地域で差が出る=アプリではなくネットワーク経路・CDN層を疑う」が定石。
| 監視項目 | AWSサービス |
|---|---|
| エンドポイント死活 | CloudWatch Synthetics |
| ALBレイテンシ | ALBアクセスログ → CloudWatch Metrics |
| DDoS検知 | AWS Shield + CloudWatch |
| SSL証明書期限 | ACM(自動更新)+ CloudWatch アラーム |
# Djangoミドルウェアでレイテンシを計測してCloudWatchに送る例
import time, boto3
def middleware_latency(get_response):
def middleware(request):
start = time.time()
response = get_response(request)
duration = (time.time() - start) * 1000 # ms換算
boto3.client('cloudwatch').put_metric_data(
Namespace='MyDjangoApp',
MetricData=[{
'MetricName': 'RequestLatency',
'Value': duration,
'Unit': 'Milliseconds'
}]
)
return response
return middleware
💡 ポイント: ACM(AWS Certificate Manager)でSSL証明書を管理すると自動更新されるため、証明書切れ障害をほぼゼロにできる。自前管理との差は大きい。
| 用語 | 説明 |
|---|---|
| レイテンシ | リクエストが往復するのにかかる時間(遅延) |
| ACM | AWS Certificate Manager。SSL/TLS証明書の発行・自動更新を管理するAWSサービス |
| DDoS | 大量のリクエストを送りつけてサービスを停止させる攻撃 |
セキュリティ対策(WAF・認証)は侵入を防ぐが、100%防げる前提には立てない。異常を早期検知して被害を最小化するのがセキュリティ監視の役割:
認証系:
ログイン失敗の急増(ブルートフォース)
普段と異なる時間・IPからのログイン
トラフィック系:
リクエスト数の異常な急増(DDoS兆候)
特定エンドポイントへの集中アクセス
操作系:
本番DBへの直接アクセス
IAMポリシーの変更・権限昇格
大量データの一括取得
# ログイン失敗をCloudWatchカスタムメトリクスに送る
from django.contrib.auth.signals import user_login_failed
from django.dispatch import receiver
@receiver(user_login_failed)
def on_login_failed(sender, credentials, request, **kwargs):
cloudwatch.put_metric_data(
Namespace='MyDjangoApp/Security',
MetricData=[{
'MetricName': 'LoginFailed',
'Value': 1,
'Unit': 'Count'
}]
)
| 検知したい異常 | AWSサービス |
|---|---|
| IAM権限変更 | CloudTrail → CloudWatch Alarm |
| 不審なIPからのアクセス | WAF → CloudWatch Metrics |
| ブルートフォース攻撃 | Django + CloudWatch カスタムメトリクス |
| 異常なAPI呼び出し | GuardDuty |
CloudTrailとGuardDutyの違い:
💡 ポイント: セキュリティ監視のアラートは「誤検知が多い」問題がある。閾値設計が甘いと毎日アラートが鳴り、アラート疲れでスルーされるようになる。
| 用語 | 説明 |
|---|---|
| CloudTrail | AWSのAPI呼び出し・IAM操作を全記録するサービス |
| GuardDuty | CloudTrailのログを機械学習で分析し、異常な振る舞いを自動検知するサービス |
| ブルートフォース | パスワードを総当たりで試す攻撃手法 |
| WAF | Web Application Firewall。不審なリクエストをブロックする仕組み |
現状評価の問い:
① 監視されていない単一障害点はないか?
② アラートの何割が実際に対応されているか
③ 障害時に原因特定まで何分かかるか?
④ ビジネスKPIと技術指標は紐づいているか
⑤ 監視設計をした人以外も理解できるか?
改善サイクル:
現状把握 → 優先順位付け → 実装 → 振り返り
↑________________________________↓
Django + ECS環境での実践チェックリスト:
| チェック項目 | 未対応でのリスク |
|---|---|
| 5xxエラー率のアラーム設定 | 障害に気づけない ← 最優先 |
| CloudWatch Logsへのログ転送 | 原因調査ができない |
| カスタムメトリクス(注文数等) | ビジネス影響が見えない |
| タスク再起動回数の監視 | ECS障害を見逃す |
| SSL証明書期限の監視 | 突然のサービス停止 |
監視の優先順位:まず「異常を検知する(5xxアラーム)」、次に「原因を調査する(Logsへの転送)」。ログ転送は原因調査のためなので、そもそも異常を検知できなければログを見る機会すら来ない。
💡 ポイント: 完璧な監視を目指すより「今一番痛い問題を1つ解決する」を繰り返す方が現実的。監視も技術的負債と同じで、少しずつ返済する発想が大事。
| ミス | 原因 | 改善策 |
|---|---|---|
| CPU 80%でアラートを設定する | 原因ベース監視になっている | 5xxエラー率・レイテンシ等の症状ベースに変更 |
| アラートが鳴っても誰も見ない | アラート疲れ・対応フローが未定義 | アラートの分類整理+対応手順書の作成 |
| 監視チームがアラートを全管理 | 役割としての監視アンチパターン | 閾値定義はアプリ担当者が行う |
| ログだけ転送して検知がない | 検知より調査を先に設定した | まず5xxアラームを設定してから調査基盤を整える |
| サーバ監視しかしていない | 死活監視=監視と誤解している | 5層モデルで抜け漏れを確認する |
| SSL証明書切れに気づかない | 「情報」として無視していた | 「要対応」として期限管理・アラーム設定する |
user_login_failed シグナルや watchtower ライブラリなど、DjangoとCloudWatchを繋ぐ実装イメージが持てた