
パフォーマンス監視とボトルネック特定
速いサービスは正義ですが、闇雲にサーバを増やしても体感は改善しません。効くのは「どこで時間と資源が失われているか」を測り、再現性のある手順で潰すことです。監視は“鳴らす”ためでなく、意思決定を早めるための情報設計だと捉えると、投資は小さく成果は大きくなります。
SLOから逆算する監視設計
最初に決めるのはダッシュボードではなく、ユーザー体験を守るSLO(Service Level Objective)です。APIのp95遅延、エラー率、可用性、ジョブ完了時間など、事業のKPIに直結するSLIを1〜3個に絞り、予算(Error Budget)で運用判断を回します。
SLI/SLOの具体例
- チェックアウトAPIのp95遅延≤500ms、成功率≥99.9%(30日ローリング)
- 画像生成ジョブのp99完了≤90秒、タイムアウト率≤0.5%
- 管理画面のLCP≤2.5s(75パーセンタイル、RUM計測)
アラートは「閾値超過」より「予算消費速度(burn rate)」を使います。例えば2時間で予算の5%を消費したら重大、24時間で2%は警告、のように短期・長期で2本立てにします。これだけで夜間のノイズは激減します。
メトリクスの階層とラベル設計
メトリクスは階層で切ると分析が速くなります。サービス→エンドポイント→リージョン/ゾーン→テナント/顧客プランの順でラベルを付与し、ユーザー影響の粒度で集計できます。高カーディナリティ(例:ユーザーID)は避け、相関が必要なものはトレースIDで結びます。
計測の実装と落とし穴
可観測性はメトリクス・ログ・トレースの三位一体です。入れ方しだいで見える/見えないが決まります。
メトリクス:Counter/Gauge/Histogramの使い分け
- 遅延は必ずヒストグラムで。バケットは実態に合わせて例: [5, 10, 25, 50, 100, 250, 500, 1000ms]。p95/p99を後段で出せます。
- エラー率は「エラー数/総数」の2本をCounterで取り、比率はクエリで計算。ステータスコードは200/4xx/5xxに正規化。
- キュー長・コネクションプール使用率・スレッド数はGauge。飽和(saturation)を追うと上限が見えます。
ログ:構造化と相関
- JSONで出力。trace_id, span_id, user_tier, endpointを必ず含める。
- サンプリングを設計。通常1〜10%、エラー時は100%に昇格(動的サンプリング)。
- PIIやSQL全文はマスキングし、必要ならハッシュでグルーピングだけ可能に。
トレース:遅い区間を可視化
- W3C Trace Contextで全コンポーネントを関連付け。外部API/DB/メッセージングはspanに種別とリモート先を付与。
- head/tailサンプリングを併用し、遅延上位p99のトレースは必ず保持。
- db.statementは要約(operation, table, whereの形)で。全文は機密に注意。
RUMも忘れずに。LCP/FID/CLSに加え、ネットワーク・デバイス情報(3G/4G、端末クラス)でサーバ側遅延と切り分けます。計装はOpenTelemetryが無難です。実装時はCopilotでメトリクス埋め込みのひな型を用意し、アラート文面やRunbookの草案はChatGPTやClaudeで下書き → 最終レビューを人間が行うと早いです。
収集間隔とコスト設計
- スクレイプ間隔は10sが標準、コア系は5s、重いメトリクスは30〜60s。異常検知は“解像度の高い少数の指標”を優先。
- 高頻度×高カーディナリティは課金爆弾。業務に不要なラベルは落とし、集約ジョブで1分平均へダウンサンプル。
- Exemplar(トレースへのハイパーリンク)を使うと、メトリクス→遅いトレースへワンクリックで飛べます。
ボトルネック特定の標準フロー
- 症状を定義:SLO違反のどのSLIか(遅延/エラー/飽和)。p95かp99かを明確に。
- 影響範囲を絞る:リージョン/エンドポイント/テナント/リリース版でフィルタ。新リリースや特定顧客層なら再現性あり。
- 依存関係を可視化:サービスマップで上流/下流を確認。下流のエラー/遅延が相関するか。
- 時間の使われ方を分解:トレースでClient→Queue→App→DB→外部APIの各区間を比較。キュー待ちが長ければ容量問題、Appが長ければCPU/GC/ロック、DBならスキャン/ロック/プール枯渇。
- 計測で仮説検証:
- CPU 90%超+Run queue増=CPU飽和。pprof/フレームグラフでhot path特定。
- GC pause増=アロケーション過多。オブジェクト再利用/構造最適化。
- DB接続プール使用率≈100%+待ち時間増=プール小さすぎ or N+1。スロークエリとインデックス確認。
- 外部APIのp95遅延増+リトライ増=外部依存。サーキットブレーカーとバックオフを調整。
- ネットワーク:再送/タイムアウト増=輻輳 or DNS。コネクション再利用/TLSチューニング。
- 緩和策→恒久対策の順で実施:
- 即効薬:キャッシュTTL延長、重い機能をフラグで無効化、レート制限で守る。
- 恒久:索引追加、N+1修正、バッチのスケジューリング変更、シャーディング/キュー導入。
身近な企業活用例:小規模EC「LimeCart」の失敗と改善
従業員40名のD2C EC「LimeCart」。年末セールでチェックアウトのp95が2.8秒、5xxが3%に悪化。対処としてアプリサーバを2→6台に増強しましたが、売上は伸びずカゴ落ちが続出。振り返ると監視はCPU/メモリのダッシュボード中心で、ユーザー体験の指標がありませんでした。
そこでSLOを「チェックアウトp95≤600ms/成功率≥99.9%」に設定し、OpenTelemetryでAPI遅延ヒストグラム、DB/外部APIのspan属性、RUMを導入。アラートは予算消費方式へ刷新。初回の分析で、ピーク時に「在庫更新クエリ」のロック待ちが急増、DB接続プールが飽和していることが判明。クエリは在庫テーブルを範囲UPDATEしており、カバリングインデックスがなく全表スキャン+行ロックが発生していました。
緩和として在庫確認をキャッシュに切替え、決済直前だけ悲観ロックを取得。恒久対策で(1)在庫テーブルに(sku, location, status)複合インデックス追加、(2)更新粒度を1 SKU単位に変更、(3)在庫引当をキュー化し、タイムアウト時は自動解放(予約在庫TTL)を実装。合わせて接続プールを適正化し、アプリのGCを調整。
次のセールではp95=420ms、エラー率0.2%、インフラコストは20%削減。オンコールはburn rate二段アラートにより夜間の誤検知がゼロに。Runbookの下書きはChatGPT、事後分析のテンプレと学習項目整理はClaude、コードへのメトリクス埋め込み雛形はCopilotを活用し、運用書類の整備時間も半減しました。
パフォーマンスは気合いではなく、SLO起点の設計、適切な計装、そして標準化された切り分けフローの積み重ねです。サーバ監視運用事業では、この土台が24/7の監視、アラート運用、障害後の改善サイクルを安定させ、チームの“判断速度”を底上げします。日々の運用が意思決定に直結するよう、測り方と見せ方をまず整えることが近道です。