monitoring-setup-guide について
monitoring-setup-guide は、サービスの本番監視を設計するチーム向けのスキルです。技術スタックとユーザージャーニーに沿って、メトリクス、構造化ログ、トレース、実行可能なアラート閾値、ダッシュボードを整理します。
主な機能
- 014つのゴールデンシグナル指標
- 02構造化ログのスキーマ
- 03分散トレースのチェックリスト
- 04閾値に基づくアラート仕様
- 05ビジネス指標とダッシュボード
- 06サービス情報に応じた入力整理
活用シーン
- 01新規サービスの監視計画
- 02既存サービスの指標とアラートの見直し
- 03主要なユーザージャーニーに沿った運用閾値の設定
- 04サービスの健全性を共有する基準の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mohitagw15856/ pm-claude-skills --skill monitoring-setup-guideインストール後、Claude Code で/monitoring-setup-guideを入力して読み込まれたか確認します。
詳細
モニタリング設定ガイドスキル
サービスの包括的なモニタリング設定ガイドを作成します。測定する項目、ログの構成方法、実行可能な閾値を用いたアラートの設定方法、実際の運用上の疑問に答えるダッシュボードの構築方法を明確に定義します。優れたモニタリングガイドがあれば、「本番環境で何が起きているかわからない」が根本原因の分類に含まれなくなり、オンコールエンジニアは何をもって正常とするかを確認するための信頼できる情報源を得られます。
必要な入力情報
まだ提供されていない場合は、以下を確認してください:
- サービス名と説明 — サービスの機能とシステム内での役割
- 技術スタック — 言語、フレームワーク、インフラストラクチャ(例:Kubernetes 上の Go/gRPC、ECS 上の Python/FastAPI)
- 現在のモニタリングツール — Datadog、Prometheus + Grafana、CloudWatch、New Relic、Honeycomb、または未導入
- 主要なユーザージャーニー — ユーザーまたは利用者がサービスで行う、最も重要な 2~4 個の操作(アラート対象の判断基準になります)
- 既存のアラート — 既存のアラート設定を貼り付けるか、現在モニタリングしている内容を説明してください
出力形式
モニタリング設定ガイド:[Service Name]
チーム: [Team name] | テックリード: [Name] スタック: [Language/Framework]([Infrastructure] 上) モニタリングプラットフォーム: [Datadog / Prometheus+Grafana / CloudWatch / etc.] 日付: [Date] | レビュー周期: 四半期ごと
1. モニタリングの方針
優れたモニタリングは、次の 3 つの質問に答えます:
- 現在、サービスは正常ですか?(アラート)
- 過去も正常でしたか。また、悪化傾向にありませんか?(ダッシュボード + SLO トラッキング)
- なぜ問題が発生したのですか?(ログ + トレース)
このガイドでは、[Service Name] についての答えを定義します。すべてのアラートは実行可能でなければなりません。オンコールエンジニアがアラートへの対応として具体的な行動を取れない場合、そのアラートは設定すべきではありません。
モニタリング対象の主要なユーザージャーニー:
- ジャーニー 1:[例:「ユーザーが支払いを送信する — POST /charges を実行し、確認を受け取る」]
- ジャーニー 2:[例:「ユーザーが取引履歴を表示する — GET /transactions」]
- ジャーニー 3:[例:「サブスクリプション更新ジョブが実行される — バックグラウンドワーカーが請求イベントを処理する」]
2. 4 つのゴールデンシグナル
[Service Name] に 4 つのゴールデンシグナルを適用します:
レイテンシ
レイテンシは、リクエストの完了にかかる時間を測定します。成功したリクエストと失敗したリクエストは分けて追跡してください。集計レイテンシだけを測定すると、エラー応答が速い場合に、失敗しているリクエストの遅さが見えなくなります。
| メトリクス | 説明 | 取得元 | ディメンション |
|---|---|---|---|
[service].request.duration_ms | リクエストのエンドツーエンドレイテンシ | アプリケーションのインストルメンテーション | endpoint、method、status_code |
[service].db.query_duration_ms | データベースクエリのレイテンシ | ORM / クエリのインストルメンテーション | query_name、table |
[service].external.request_duration_ms | 依存先へのアウトバウンド呼び出しのレイテンシ | HTTP クライアントのインストルメンテーション | target_service、endpoint |
[service].queue.processing_duration_ms | 1 件のメッセージの処理時間(該当する場合) | コンシューマーのインストルメンテーション | queue_name、message_type |
レイテンシの SLO 目標:
| エンドポイント / 操作 | p50 目標 | p95 目標 | p99 目標 |
|---|---|---|---|
GET /api/v1/[resource] | < [50] ms | < [200] ms | < [500] ms |
POST /api/v1/[resource] | < [100] ms | < [400] ms | < [1000] ms |
GET /health | < [10] ms | < [20] ms | < [50] ms |
| [バックグラウンドジョブ名] | < [5] 秒 | < [15] 秒 | < [60] 秒 |
トラフィック
トラフィックは、システムに対する需要を測定します。予期しない急増やトラフィックの低下(上流の障害を示す場合があります)の検出や、キャパシティプランニングに使用します。
| メトリクス | 説明 | ソース |
|---|---|---|
[service].request.count | 1 秒あたりのリクエスト数 | アプリケーション/ロードバランサー |
[service].request.count_by_endpoint | エンドポイント別の RPS | アプリケーション |
[service].queue.messages_consumed_per_second | コンシューマーのスループット | キューコンシューマー |
[service].queue.depth | キューで待機中のメッセージ数 | キューメトリクス |
トラフィックのベースライン(本番環境を 2 週間以上観測した後に更新してください):
| 期間 | 予想 RPS | 低トラフィックの下限 | 急増の上限 |
|---|---|---|---|
| ピーク時(平日の営業時間) | [N] RPS | [N × 0.5] RPS | [N × 5] RPS |
| オフピーク時(夜間/週末) | [N × 0.2] RPS | [N × 0.05] RPS | [N] RPS |
エラー
エラーは、失敗したリクエストの割合を測定します。クライアントエラー(4xx — 呼び出し元の操作に誤りがある)とサーバーエラー(5xx — サービスに障害がある)を区別してください。
| メトリクス | 説明 | アラート対象? |
|---|---|---|
[service].request.error_rate | 5xx エラー数/総リクエスト数 | はい — アラートルールを参照 |
[service].request.client_error_rate | 4xx エラー数/総リクエスト数 | しきい値アラート — 急増は API の不適切な使用を示す場合があります |
[service].dependency.error_rate | 下流の依存先への呼び出しエラー | はい — 上流の健全性を示すシグナル |
[service].queue.dlq_depth | デッドレターキュー内のメッセージ数 | はい — 処理の失敗を示します |
飽和度
飽和度は、サービスがどの程度「満杯」か、つまり制約のあるリソースが最大容量にどれほど近いかを測定します。
| リソース | メトリクス | アラートしきい値 | ソース |
|---|---|---|---|
| CPU | [service].cpu.utilisation_pct | 5 分間継続して >80% | コンテナ/VM メトリクス |
| メモリ | [service].memory.utilisation_pct | 5 分間継続して >85% | コンテナ/VM メトリクス |
| DB 接続 | [service].db.connection_pool.utilisation_pct | >75% | アプリケーション/DB メトリクス |
| スレッドプール/ゴルーチン | [service].runtime.goroutine_count / thread_count | >N(ベースラインを確立) | ランタイムメトリクス |
| ディスク(該当する場合) | [service].disk.utilisation_pct | >75% | インフラストラクチャ |
| キューの深さ(該当する場合) | [service].queue.depth | >[バックログのしきい値] | キューメトリクス |
3. ビジネスメトリクス
ゴールデンシグナルに加え、サービスがビジネス価値を提供しているかを測定するメトリクスを追跡してください。これらは SLO レポートやプロダクトダッシュボードで重要です。
| メトリクス | 説明 | ソース | アラート? |
|---|---|---|---|
[service].[primary_action].success_rate | [例:「決済成功率」] | アプリケーション | はい — 1 時間平均と比べて >5% 低下した場合 |
[service].[primary_action].count | [例:「1 分あたりに処理した決済数」] | アプリケーション | はい — 急激な低下(トラフィック異常) |
[service].[resource].created_per_hour | [例:「新規作成アカウント数」] | アプリケーション/DB | いいえ — 参考情報 |
[service].cache.hit_rate | キャッシュから応答したリクエストの割合 | キャッシュのインストルメンテーション | はい — [60]% を下回った場合 |
[service].job.[name].success_rate | [バックグラウンドジョブの成功率] | ジョブフレームワーク | はい — [99]% を下回った場合 |
4. ログ戦略
構造化ログのスキーマ
すべてのログは構造化 JSON でなければなりません。本番環境では、構造化されていないテキストログを出力しないでください。すべてのログ行に必須フィールドを含める必要があります。
必須フィールド(すべてのログ行):
{
"timestamp": "2024-01-15T10:23:45.123Z",
"level": "info",
"service": "[service-name]",
"version": "[git-sha-short]",
"trace_id": "[uuid-from-request-context]",
"span_id": "[span-uuid]",
"request_id": "[uuid-per-request]",
"message": "[human readable description]"
}
リクエストログ(すべての HTTP リクエストで出力):
{
"timestamp": "...",
"level": "info",
"service": "[service-name]",
"event": "http_request",
"method": "POST",
"path": "/api/v1/[resource]",
"status_code": 201,
"duration_ms": 45,
"user_id": "[uuid — DO NOT log PII directly]",
"request_id": "[uuid]",
"trace_id": "[uuid]"
}
エラーログ(コンテキストを含め、すべてのエラーで出力):
{
"timestamp": "...",
"level": "error",
"service": "[service-name]",
"event": "error",
"error_code": "[application-error-code]",
"error_message": "[description — no sensitive data]",
"stack_trace": "[stack trace]",
"request_id": "[uuid]",
"trace_id": "[uuid]",
"context": {
"[key]": "[relevant context without PII]"
}
}
ログレベル — それぞれの使いどき
| レベル | 使用する状況 | 例 |
|---|---|---|
error | 対応が必要な問題が発生した場合。最終的にはオンコール担当者への通知が必要です | データベースクエリの失敗、外部 API からの 5xx 応答、必須設定の欠落 |
warn | 予期しないことが起きたものの、サービスは引き続き動作している場合 | 失敗後にリトライが成功、ヒットが期待される場面でのキャッシュミス、レート制限への接近 |
info | 重要なビジネスイベントやリクエストのライフサイクル | リクエストの受信、決済の処理、ユーザー認証、ジョブの開始・完了 |
debug | 詳細な診断情報。本番環境ではデフォルトで無効です | クエリパラメーター、中間計算結果、キャッシュキーの検索 |
ログに記録してはいけないもの
絶対に記録しないでください:
- パスワード、トークン、API キー、シークレット(ハッシュ化したものも含む)
- クレジットカード番号や PAN データの全桁
- 社会保障番号や政府発行の ID
- 氏名、生年月日、連絡先情報を同じログ行にまとめたもの(PII の集約)
- リクエスト/レスポンスの本文全体(代わりにフィールド単位で抽出してください)
- ヘルスチェックのリクエスト(ノイズが多すぎるため、アクセスログから
GET /healthを除外してください)
5. 分散トレーシングの設定
他のサービスを呼び出すすべてのサービスで、分散トレーシングが必須です。サービス境界をまたいだ根本原因の分析が可能になります。
計装チェックリスト
[ ] Tracing library installed:
- Go: go.opentelemetry.io/otel
- Python: opentelemetry-sdk, opentelemetry-instrumentation
- Node: @opentelemetry/sdk-node
- Java: opentelemetry-java-instrumentation
[ ] Tracer initialized at service startup with service name and version
[ ] Trace context propagated via W3C Trace Context headers:
traceparent: 00-[trace-id]-[span-id]-01
tracestate: [optional vendor-specific]
[ ] Automatic instrumentation enabled for:
[ ] Inbound HTTP/gRPC requests (creates root span)
[ ] Outbound HTTP/gRPC calls (creates child spans)
[ ] Database queries (creates child spans with sanitized query)
[ ] Cache operations (Redis, Memcached)
[ ] Message queue produce/consume
[ ] Custom spans added for:
[ ] Key business operations ([e.g. payment processing, user lookup])
[ ] Background jobs (each job execution = root span)
[ ] Third-party API calls with custom attributes
[ ] Span attributes to capture on all spans:
- user.id (if authenticated — no PII)
- deployment.environment (production/staging)
- service.version (git SHA)
- [service-specific key attributes]
[ ] Trace exporter configured to: [Datadog / Jaeger / Tempo / OTLP endpoint]
[ ] Sampling rate configured:
- Production: [1–10]% of requests (adjust based on volume and cost)
- Always sample: errors, slow requests (>p99 threshold), and 100% of [critical endpoint]
トレース計装の例
# Python — OpenTelemetry example
from opentelemetry import trace
tracer = trace.get_tracer("[service-name]")
def process_payment(payment_data):
with tracer.start_as_current_span("process_payment") as span:
span.set_attribute("payment.amount_cents", payment_data["amount"])
span.set_attribute("payment.currency", payment_data["currency"])
# Never: span.set_attribute("payment.card_number", ...)
try:
result = _do_process(payment_data)
span.set_status(trace.StatusCode.OK)
return result
except PaymentError as e:
span.set_status(trace.StatusCode.ERROR, str(e))
span.record_exception(e)
raise
6. アラートルールの仕様
すべてのアラートには、名前、条件、しきい値、重大度、明確なオンコール対応を設定する必要があります。明確な対応がないアラートは作成しないでください。
アラートの定義
| アラート名 | 条件 | しきい値 | 重大度 | オンコール対応 |
|---|---|---|---|---|
[Service]HighErrorRate | 5 分間のローリングウィンドウにおける 5xx エラー率 | 2 ウィンドウ連続で >1% | P1 | 直近のデプロイを確認し、エラーログを調査してください。ランブックを参照してください[リンク] |
[Service]CriticalErrorRate | 2 分間のローリングウィンドウにおける 5xx エラー率 | >5% | P1 — 即時対応 | 上記と同様です。直ちにページ通知し、待たないでください |
[Service]HighP99Latency | 主要エンドポイントの p99 レイテンシ | 3 分間、SLO 目標の >2 倍 | P2 | DB レイテンシ、キャッシュヒット率、上流の依存関係を確認してください |
[Service]LatencySLOBreach | p99 レイテンシ | 5 分間連続で >SLO 目標 | P1 | SLO の消費率が高いため、オンコール担当者にページ通知し、20 分以内に解決しない場合はエスカレーションしてください |
[Service]HighCPU | CPU 使用率 | 5 分間継続して >80% | P2 | トラフィックの急増を確認し、必要に応じてスケールアップしてください。暴走プロセスがないか確認してください |
[Service]HighMemory | メモリ使用率 | 5 分間継続して >85% | P2 | メモリリーク(特にデプロイ後)を確認してください。OOM が迫っている場合はポッドを再起動してください |
[Service]DBConnectionPoolHigh | DB 接続プールの使用率 | >75% | P2 | 長時間実行中のクエリを確認し、サービスのスケーリングまたはプールサイズの拡大を検討してください |
[Service]DLQDepthHigh | デッドレターキューの深さ | >10 メッセージ | P2 | DLQ のメッセージを調べてエラーのパターンを特定し、安全であればバグを修正して再処理してください |
[Service]TrafficDropAnomaly | 昨日の同時刻と比較した RPS | 5 分間継続して >50% 減少 | P1 | 上流が停止している可能性があります。呼び出し元の状態とロードバランサーを確認してください |
[Service]PrimaryActionSuccessRateDrop | [ビジネスメトリクスの成功率] | 10 分間で <[95]% | P1 | [サービス固有の対応(例:「決済プロバイダーのステータスを確認」)] |
[Service]DownstreamDependencyErrors | [依存先]への呼び出しのエラー率 | 5 分間で >5% | P2 | [依存先]のステータスページを確認し、利用可能であればフォールバックを有効にしてください |
アラート設定の例
# Prometheus / Grafana alerting rules (adapt for your platform)
groups:
- name: [service-name]-alerts
rules:
- alert: [Service]HighErrorRate
expr: |
(
sum(rate([service]_http_requests_total{status=~"5.."}[5m]))
/
sum(rate([service]_http_requests_total[5m]))
) > 0.01
for: 2m
labels:
severity: critical
team: [team-name]
annotations:
summary: "High error rate on [Service Name]"
description: "Error rate is {{ $value | humanizePercentage }} (threshold: 1%)"
runbook_url: "[runbook link]"
- alert: [Service]HighP99Latency
expr: |
histogram_quantile(0.99,
sum(rate([service]_http_request_duration_seconds_bucket[5m])) by (le, endpoint)
) > [0.5]
for: 3m
labels:
severity: warning
team: [team-name]
annotations:
summary: "p99 latency elevated on [Service Name]"
description: "p99 latency on {{ $labels.endpoint }} is {{ $value | humanizeDuration }}"
runbook_url: "[runbook link]"
# Datadog monitor configuration (Python SDK or Terraform)
import datadog
datadog.initialize(api_key="[key]", app_key="[key]")
datadog.api.Monitor.create(
type="metric alert",
query=f"sum(last_5m):sum:{{service}}.http.errors{{service:[service-name]}} / sum:{{service}}.http.requests{{service:[service-name]}} > 0.01",
name="[Service] High Error Rate",
message="Error rate exceeded 1%. @pagerduty-[service-oncall]\n\nRunbook: [link]",
tags=["service:[service-name]", "team:[team-name]"],
options={
"thresholds": {"critical": 0.01, "warning": 0.005},
"notify_no_data": False,
"evaluation_delay": 60,
}
)
7. ダッシュボードレイアウトの仕様
サービスのプライマリダッシュボードを一目見ただけで、「サービスは現在正常か?」が分かるようにしてください。次のレイアウトを使用してください。
┌─────────────────────────────────────────────────────────────────────┐
│ [SERVICE NAME] — Service Health Dashboard [Time range ▼] │
├───────────────┬───────────────┬───────────────┬─────────────────────┤
│ Error rate │ p99 Latency │ RPS (current)│ SLO budget remaining│
│ [BIG NUMBER] │ [BIG NUMBER] │ [BIG NUMBER] │ [BIG NUMBER / days] │
│ vs SLO: 0.1% │ vs SLO: 500ms│ vs avg: [N] │ [Error budget gauge]│
├───────────────┴───────────────┴───────────────┴─────────────────────┤
│ Error rate over time (24h) │
│ [Time series: 5xx rate line, SLO threshold line] │
├─────────────────────────────────┬───────────────────────────────────┤
│ Latency percentiles over time │ Request throughput over time │
│ [Lines: p50, p95, p99, p999] │ [Bars: RPS by endpoint] │
│ [SLO threshold horizontal line]│ │
├─────────────────────────────────┴───────────────────────────────────┤
│ Latency heatmap (all requests — shows distribution shape) │
├─────────────────────────────────┬───────────────────────────────────┤
│ CPU utilisation over time │ Memory utilisation over time │
│ [All instances/pods — lines] │ [All instances/pods — lines] │
│ [Alert threshold: 80%] │ [Alert threshold: 85%] │
├─────────────────────────────────┴───────────────────────────────────┤
│ DB: connection pool utilisation│ DB: query latency (p99 per query)│
├─────────────────────────────────┴───────────────────────────────────┤
│ [Business metric 1 over time] │ [Business metric 2 over time] │
│ e.g. Payment success rate │ e.g. Orders created/min │
└─────────────────────────────────┴───────────────────────────────────┘
2 つ目のダッシュボード — 依存関係の状態:
┌─────────────────────────────────────────────────────────────────────┐
│ [SERVICE NAME] — Dependency Health │
├─────────────────────────────────────────────────────────────────────┤
│ For each dependency: error rate | latency | current status │
│ [Database] [N]% errors | [N]ms p99 | ● Healthy / ⚠ Degraded │
│ [Redis] [N]% errors | [N]ms p99 | ● Healthy │
│ [External API][N]% errors | [N]ms p99 | ● Healthy │
├─────────────────────────────────────────────────────────────────────┤
│ Outbound call latency over time (one line per dependency) │
├─────────────────────────────────────────────────────────────────────┤
│ Circuit breaker / fallback state (if implemented) │
└─────────────────────────────────────────────────────────────────────┘
8. 可観測性の負債分析
現状で不足している項目と、その追加の優先度を率直に評価します。
| ギャップ | 影響 | 優先度 | 工数 | 担当者 | 目標日 |
|---|---|---|---|---|---|
| [例:分散トレーシングがない — サービス間のレイテンシーを確認できない] | 高 — 依存関係の問題を把握できない | P1 | [2日] | [名前] | [日付] |
| [例:ビジネスメトリクスのアラートがない — インフラのアラートのみ] | 高 — ビジネス上の障害が検知されない | P1 | [1日] | [名前] | [日付] |
| [例:ログが構造化されていないテキスト — 検索できない] | 中 — インシデント調査に時間がかかる | P2 | [3日] | [名前] | [日付] |
| [例:デッドレターキューの監視がない] | 中 — 失敗したメッセージが見過ごされる | P2 | [4時間] | [名前] | [日付] |
| [例:アラートのしきい値が本番環境のベースラインに合わせて調整されていない] | 中 — アラート疲れやアラートの見逃しにつながる | P2 | [1日] | [名前] | [日付] |
| [例:レイテンシーのヒートマップがない — 平均値では外れ値が見えない] | 低 — テールレイテンシーの問題を見つけにくい | P3 | [2時間] | [名前] | [日付] |
可観測性の負債合計:[N] 項目 | 推定工数:[N 日]
品質チェック
- すべてのアラートに、担当者と具体的な対応手順が定められている — 最初に何を調査すべきかを指定せずに「調査してください」とだけ示すアラートがない
- アラートのしきい値は、テンプレートのデフォルト値ではなく、本番環境のベースラインに照らして調整されている
- 構造化ログが実装されている — 本番環境に構造化されていないテキストログがない
- PII がログから明示的に除外されている — 担当エンジニアがこれを確認済み
- 分散トレーシングで、すべてのサービス境界を越えてトレース ID が伝播している(テストリクエストで確認する)
- 主要なダッシュボードで「サービスは正常か?」を 10 秒以内に判断できる — 適切なパネルを探し回る必要がない
- インフラメトリクスだけでなく、ビジネスメトリクスも追跡している — 4 つのゴールデンシグナルだけにとどまらない
- 可観測性の負債項目に担当者と日付が設定されている — 単に「あれば望ましい」という状態ではない
アンチパターン
- 具体的なオンコール対応手順のないアラートを作成しない — 「調査してください」とだけ示すアラートは、エンジニアに無視する習慣をつけさせる
- 本番環境のベースラインに照らして調整せずに、テンプレートのしきい値を設定しない — 未調整のしきい値は、アラート疲れやインシデントの見逃しを引き起こす
- PII、トークン、シークレットをログに記録しない — ログに記録してはならない項目の明示的な一覧がなければ、ロギング基準は不完全
- 4 つのゴールデンシグナルだけを測定し、少なくとも 1 つのビジネスメトリクスのアラートを追加しないままにしない — ビジネス上重要な経路がひそかに失敗していても、インフラの状態は正常になり得る
- すべてのサービス境界を越えてトレース ID が伝播することを確認せずに、分散トレーシングを導入しない — 部分的なトレーシングは、誤解を招く不完全なトレースを生成するため、トレーシングがない状態よりも悪い