LESSON 40分

ストーリー

佐藤CTO
SLI/SLO/SLAの設計は完了した。だが、計測できなければ絵に描いた餅だ
佐藤CTO
PrometheusでメトリクスをCollectし、Grafanaで可視化する — それがSREの計測基盤の標準構成だ
佐藤CTO
ダッシュボードは一度作ったら終わりではなく、チームの意思決定を支援する生きたツールにする必要がある

Prometheusメトリクスの設計

メトリクスタイプ

タイプ用途SLIへの使い方
Counter累積値(単調増加)リクエスト数、エラー数http_requests_total
Histogram分布(バケット)レイテンシのパーセンタイルhttp_request_duration_seconds
Gauge瞬間値(増減する)現在の接続数、キュー長node_memory_available_bytes
Summary分布(クライアント側計算)レイテンシ(集約不可)go_gc_duration_seconds

SLI用メトリクスの実装

import { Registry, Counter, Histogram, collectDefaultMetrics } from 'prom-client';

const register = new Registry();
collectDefaultMetrics({ register });

// SLI: 可用性メトリクス
const httpRequestsTotal = new Counter({
  name: 'http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'handler', 'status'] as const,
  registers: [register],
});

// SLI: レイテンシメトリクス
const httpRequestDuration = new Histogram({
  name: 'http_request_duration_seconds',
  help: 'HTTP request duration in seconds',
  labelNames: ['method', 'handler'] as const,
  // SLO閾値を含むバケット設計
  buckets: [0.01, 0.05, 0.1, 0.2, 0.3, 0.5, 1, 2, 5, 10],
  registers: [register],
});

// ミドルウェアでの計測
function metricsMiddleware(req: Request, res: Response, next: NextFunction): void {
  const start = process.hrtime.bigint();

  res.on('finish', () => {
    const durationNs = Number(process.hrtime.bigint() - start);
    const durationSec = durationNs / 1e9;

    const handler = req.route?.path ?? req.path;
    const method = req.method;
    const status = res.statusCode.toString();

    httpRequestsTotal.inc({ method, handler, status });
    httpRequestDuration.observe({ method, handler }, durationSec);
  });

  next();
}

PromQL基礎

# 1. レート計算(Counter用)
# 直近5分間のリクエスト/秒
rate(http_requests_total[5m])

# 2. 合計(ラベルでグループ化)
sum by (handler) (rate(http_requests_total[5m]))

# 3. 可用性SLI
sum(rate(http_requests_total{status!~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

# 4. パーセンタイル計算(Histogram用)
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)

# 5. エラーバジェット消費率(30日ウィンドウ)
1 - (
  sum(increase(http_requests_total{status!~"5.."}[30d]))
  /
  sum(increase(http_requests_total[30d]))
) / 0.001  # SLO 99.9%の場合

# 6. エラーバジェット残量(分単位)
(
  (
    sum(increase(http_requests_total{status!~"5.."}[30d]))
    /
    sum(increase(http_requests_total[30d]))
  )
  - 0.999
) * 30 * 24 * 60

Grafanaダッシュボード設計

SLOダッシュボードの構成

graph TD
    subgraph Dashboard["SLO Dashboard - ShopNow API"]
        subgraph KPIs["主要KPI"]
            Avail["可用性<br/>99.97%<br/>● Green"]
            Budget["エラーバジェット<br/>残67%"]
            Burn["バーンレート<br/>0.5x"]
        end
        subgraph Trends["トレンド"]
            SLITrend["可用性 SLI トレンド<br/>(30日ローリング)<br/>実績 vs SLO目標(99.9%)"]
            BudgetConsume["エラーバジェット消費(累積)<br/>消費: 33% / 残り: 67%"]
        end
        subgraph Details["詳細"]
            LatencyPanel["レイテンシ p50/p99<br/>p50: 45ms<br/>p99: 280ms<br/>SLO: &lt; 300ms"]
            ErrorPanel["エラー率 by エンドポイント<br/>/search: 0.02%<br/>/payment: 0.1%"]
        end
    end

    classDef kpi fill:#198754,stroke:#146c43,color:#fff
    classDef trend fill:#0d6efd,stroke:#0a58ca,color:#fff
    classDef detail fill:#6c757d,stroke:#495057,color:#fff

    class Avail,Budget,Burn kpi
    class SLITrend,BudgetConsume trend
    class LatencyPanel,ErrorPanel detail

Grafanaダッシュボード定義(JSON抜粋)

{
  "dashboard": {
    "title": "SLO Dashboard - ShopNow API",
    "tags": ["slo", "sre"],
    "panels": [
      {
        "title": "現在の可用性(30日ローリング)",
        "type": "stat",
        "targets": [
          {
            "expr": "sum(increase(http_requests_total{status!~\"5..\"}[30d])) / sum(increase(http_requests_total[30d])) * 100",
            "legendFormat": "可用性"
          }
        ],
        "fieldConfig": {
          "defaults": {
            "thresholds": {
              "steps": [
                { "color": "red", "value": 99.0 },
                { "color": "orange", "value": 99.5 },
                { "color": "yellow", "value": 99.9 },
                { "color": "green", "value": 99.95 }
              ]
            },
            "unit": "percent"
          }
        }
      },
      {
        "title": "エラーバジェット消費率",
        "type": "gauge",
        "targets": [
          {
            "expr": "(1 - sum(increase(http_requests_total{status!~\"5..\"}[30d])) / sum(increase(http_requests_total[30d]))) / 0.001 * 100"
          }
        ],
        "fieldConfig": {
          "defaults": {
            "min": 0,
            "max": 100,
            "thresholds": {
              "steps": [
                { "color": "green", "value": 0 },
                { "color": "yellow", "value": 50 },
                { "color": "orange", "value": 80 },
                { "color": "red", "value": 100 }
              ]
            }
          }
        }
      }
    ]
  }
}

ダッシュボード設計のベストプラクティス

USE/REDメソッド

メソッド対象メトリクス
USEリソース(CPU, Memory, Disk)Utilization, Saturation, Errors
REDサービス(API, マイクロサービス)Rate, Errors, Duration
# RED メソッド実装例

# Rate: リクエストレート
sum(rate(http_requests_total[5m])) by (handler)

# Errors: エラーレート
sum(rate(http_requests_total{status=~"5.."}[5m])) by (handler)
/
sum(rate(http_requests_total[5m])) by (handler)

# Duration: レイテンシ(p50, p90, p99)
histogram_quantile(0.50,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, handler)
)
histogram_quantile(0.90,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, handler)
)
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, handler)
)

ダッシュボードの階層設計

Level 1: エグゼクティブダッシュボード
  │  SLO達成状況、エラーバジェット残量
  │  対象: CTO、VPE、ステークホルダー

Level 2: サービスダッシュボード
  │  4ゴールデンシグナル、SLIトレンド
  │  対象: チームリード、SRE

Level 3: デバッグダッシュボード
     エンドポイント別メトリクス、依存サービス状態
     対象: オンコールエンジニア
ダッシュボード設計のアンチパターン
アンチパターン問題改善
情報過多1画面に50+パネル階層化して5〜10パネルに
意味不明なグラフコンテキストなしのメトリクスタイトル、閾値、SLO線を追加
静的な閾値季節変動を考慮しない動的ベースラインを使用
アラートと連携なしダッシュボードだけでは不十分Alertmanagerと連携
更新されない古いダッシュボードが放置定期的なレビューと棚卸し

まとめ

ポイント内容
メトリクスタイプCounter(累積)、Histogram(分布)、Gauge(瞬間値)
PromQLrate、sum by、histogram_quantile でSLIを計算
ダッシュボード構成可用性、バジェット消費、レイテンシ、エラー率を1画面に
REDメソッドRate/Errors/Duration でサービス品質を可視化
階層設計エグゼクティブ→サービス→デバッグの3層構成

チェックリスト

  • Prometheusのメトリクスタイプを理解し、SLI用メトリクスを実装できる
  • PromQLでSLI/SLOの計算クエリを記述できる
  • SLOダッシュボードの構成要素を把握した
  • USE/REDメソッドを使い分けられる
  • ダッシュボードの階層設計の考え方を理解した

次のステップへ

次は「演習:SLI/SLOを設計しよう」です。マイクロサービスプラットフォームに対して、実践的なSLI/SLO設計を行いましょう。


推定読了時間: 40分