---
title: メトリクスとアラート
url: https://doc.liz6.com/ja/distributed-systems/08-observability/02-metrics-and-alerts
locale: ja
area: distributed-systems
tags:
- distributed-systems
- observability
date: 2026-06-30
modified: 2026-07-16
description: RED(Rate/Errors/Duration)はサーバー側の外部視点、USE(Utilization/Saturation/Errors)はリソースの内部視点——両者は補完関係にあります。SLIは実際の測定値、SLOは約束された目標、SLAは違反時の結果です。アラート設計の第一原則：ページングは人が直ちに行動すべき事柄のみに、その他はダッシュボードへ——誤報は当直エンジニアがアラートを無視するよう訓練してしまい、見逃しよりも危険です。
---

# メトリクスとアラート

> RED(Rate/Errors/Duration)はサーバー側の外部視点、USE(Utilization/Saturation/Errors)はリソースの内部視点——両者は補完関係にあります。SLIは実際の測定値、SLOは約束された目標、SLAは違反時の結果です。アラート設計の第一原則：ページングは人が直ちに行動すべき事柄のみに、その他はダッシュボードへ——誤報は当直エンジニアがアラートを無視するよう訓練してしまい、見逃しよりも危険です。

## RED と USE の方法论

2つの補完的な視点：

### RED (Rate, Errors, Duration)

**サービス**向け——各 service endpoint:

- **Rate**: 秒間リクエスト数——トラフィックパターンを理解する
- **Errors**: エラー率——500番台、タイムアウト、接続エラー
- **Duration**: レイテンシ分布（P50/P90/P99/P99.9）——ユーザー体験

RED はすべてのオンラインサービス（HTTP/gRPC worker）に適しており、各エンドポイントに少なくとも 3 つのメトリクスが必要です。

### USE (Utilization, Saturation, Errors)

**リソース**向け——CPU、メモリ、ディスク、ネットワーク:

- **Utilization**: リソースの使用率（CPU%、メモリバイト数）
- **Saturation**: リソースの待機キュー（CPU run queue、メモリ OOM score、IO await）
- **Errors**: リソースのエラー（ディスク IO エラー、NIC エラー、ドロップパケット）

USE はすべての物理/仮想リソースに適しており——使用制限に達する前に早期検出を行います。

## Prometheus HA

Prometheus はステートレス——各インスタンスで scrape 実行。高可用性は、2つの同一インスタンスが独立して scrape を実行することで実現します:

<svg viewBox="0 0 720 320" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="Prometheus HA 架构:两实例独立 scrape 相同 targets,remote_write 汇入 Thanos 去重">
  <defs>
    <marker id="pha" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker>
  </defs>
  <rect width="720" height="320" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">Prometheus HA: 2つのインスタンスが独立してscrapeし、remote_writeで長期ストレージに集約して重複排除</text>

  <rect x="40" y="56" width="150" height="44" rx="8" fill="#4f46e5"/>
  <text x="115" y="83" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Prometheus A</text>

  <rect x="530" y="56" width="150" height="44" rx="8" fill="#4f46e5"/>
  <text x="605" y="83" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Prometheus B</text>

  <rect x="290" y="45" width="140" height="50" rx="8" fill="#e2e8f0" stroke="#cbd5e1"/>
  <text x="360" y="66" text-anchor="middle" font-size="12.5" font-weight="700" fill="#334155">targets</text>
  <text x="360" y="82" text-anchor="middle" font-size="9.5" fill="#64748b">A、B はそれぞれ独立して取得、ターゲットは同一</text>

  <line x1="190" y1="78" x2="288" y2="68" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="235" y="64" text-anchor="middle" font-size="10" fill="#475569">scrape</text>

  <line x1="530" y1="78" x2="432" y2="68" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="485" y="64" text-anchor="middle" font-size="10" fill="#475569">scrape</text>

  <rect x="250" y="190" width="220" height="56" rx="10" fill="#0d9488"/>
  <text x="360" y="213" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Thanos / Cortex / Mimir</text>
  <text x="360" y="232" text-anchor="middle" font-size="11" fill="#ccfbf1">集約・重複排除・長期ストレージ</text>

  <line x1="115" y1="100" x2="300" y2="190" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="180" y="127" text-anchor="middle" font-size="10" fill="#475569">remote_write</text>

  <line x1="605" y1="100" x2="420" y2="190" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="540" y="127" text-anchor="middle" font-size="10" fill="#475569">remote_write</text>

  <rect x="60" y="266" width="600" height="42" rx="8" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="76" y="284" font-size="12.5" fill="#115e59">同一のtargetsをそれぞれ独立して取得し、2倍のデータがremote_write経由でThanosに流入します。Grafanaでのクエリ時には</text>
  <text x="76" y="301" font-size="12.5" fill="#115e59">external_labelsを使って2つのレプリカを区別し、同一のtime seriesを自動的に重複排除します。</text>
</svg>

Grafana が Thanos をクエリ → A と B の同一 time series を自動的に重複排除（Prometheus の `external_labels` を利用して区別）。

## SLI → SLO → SLA

```
SLI (Service Level Indicator): 実際に測定されたメトリクス
  例: 過去28日間の GET /api 成功率 = 99.95%

SLO (Service Level Objective): 私たちが約束する目標
  例: GET /api 成功率 >= 99.9%
  
SLA (Service Level Agreement): 目標未达到时的后果
  例: SLO未达到 → 10% creditを赔偿

Error budget = 100% - SLO = 0.1%
  "燃烧"可能: 紧急发布hotfix时(可能短暂破坏SLO), error budget就是你的"配额"
```

## アラート設計原則

1. **ユーザーが可視化する SLO 違反時のみページング**: メトリクスが `P99 レイテンシ > 500ms` を示していても、ユーザーが利用可能であればページングすべきではありません。`4xx/5xx rate > SLO` の場合にのみページングを送信
2. **原因ではなく症状**: アラートは「ユーザーが 500 エラーを見ている」べきであり、「CPU が 70%」ではない
3. **ノイズの排除**: 各アラートには明確なアクション可能な runbook が必要です。そうでない場合 → チケットに格下げ
4. **感度と特異度のバランス**: `for: 5m` (少なくとも5分間継続して初めて発火) で一時的なスパイクをフィルタリング。`for` が長いほど → 検知は遅くなりますが、false positive は少なくなります

## 誤報のガバナンス

```
一般的な誤報の原因:
  - 閾値が固定 (P99=200ms) だが、昼間と夜間でトラフィックパターンが異なる → より大きなウィンドウでのパーセンタイルを使用
  - デプロイ中にアラートがトリガーされる → メンテナンスウィンドウを追加するか、ロールアウト中に抑制
  - 誤報が多すぎる → アラートが無視される → 実際の障害が見逃される → これをアラーム疲労と呼ぶ
```

ガバナンス: アラート発火を定期的にレビュー——どのアラートがトリガーされたが、対応するユーザー影響がなかったか？→ 閾値を引き上げるか、チケットに変更。

## 参考

- **Google SRE Book**: Chapter 6 — Monitoring Distributed Systems
- **USE Method**: brendangregg.com/usemethod.html
- **RED Method**: grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services

*Keywords: RED, USE, SLI, SLO, SLA, error budget, Prometheus HA, alert design, alarm fatigue*
