0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

マイクロサービス基盤における SLI/SLO の実践設計ガイド(モバイル/Web/API)

Posted at

マイクロサービス基盤における SLI/SLO の実践設計ガイド(モバイル/Web/API)

概要

本記事は、モバイルアプリ・Web アプリケーション・顧客向け API 基盤を対象に、マイクロサービス環境での SLI/SLO を「実務で運用できる粒度」で設計・実装する方法を解説します。Google SRE、New Relic、Datadog の知見を参考にしつつ、プロダクト視点(顧客体験)とプラットフォーム視点(安定性/拡張性)を両立する指針・テンプレート・クエリ例を網羅します。

  • 対象読者: SRE/プラットフォームエンジニア、EM/テックリード、プロダクトオーナー
  • 目的: 合意可能な SLO と運用ルールを素早く定義し、継続的に改善できる体制を作る

本記事で示す指標名、属性名、メトリクス名、クエリ例、SLO の目標値(99.9% など)は参考値です。実際の環境では、使用している APM ツール(New Relic、Datadog 等)のドキュメントや、OpenTelemetry の Semantic Conventions を参照し、お使いの環境に合わせて読み替えてください。

前提・スコープ(仮置き)

  • システム構成(仮定)
    • マイクロサービス: 認証、ユーザー、課金、検索、注文、在庫、通知、レコメンド 等
    • API ゲートウェイ + CDN(エッジキャッシュ/レート制御)
    • データ基盤: RDB(マルチ AZ)、メッセージキュー、キャッシュ(Redis)、検索(OpenSearch)
    • 観測基盤: OpenTelemetry + Prometheus/Loki + Datadog/New Relic(いずれか/併用)
    • モバイル: iOS/Android(Release/Debug 分離計測、クラッシュ収集)
    • Web: SPA + SSR/ISR、一部 Edge Functions 利用
  • ビジネス KPI(例)
    • 課金成功率、サインイン成功率、検索成功率、注文完了率、セッション継続率
  • SLO の単位
    • プロダクト SLO(顧客体験)/ サービス SLO(技術コンポーネント)/ 依存 SLO(外部)

用語整理(簡潔)

  • SLI: 体験や品質を示す観測可能な指標(例: 200/OK 比率、p95 レイテンシ)
  • SLO: SLI に対する目標値(例: 7 日で 99.9%)
  • SLA: 契約(罰則/補償含む)。本記事は主に SLO を対象。
  • エラーバジェット: 1−SLO。機能開発と信頼性改善の意思決定基準。

設計原則(Google SRE に準拠しつつ現場適用)

  1. 顧客行動ベースで設計する(ユーザージャーニー→重要フロー→SLI→SLO)
  2. 少数のトップレベル SLO + 下位サービス SLO のツリー構造
  3. テール(p95/p99)を重視、分解能は「エンドポイント×リージョン×顧客セグメント」
  4. 多窓・多焼却率のアラート(短期/中期)で過検知/過負荷を回避
  5. エッジ/クライアントの体感 SLI を必ず含める(CDN/WebVitals/クラッシュ率)
  6. ダッシュボードは「意思決定に必要な最小セット」だけを常時可視化

対象システム別の SLI 設計

パーセンタイル(p50, p95, p99)について

パーセンタイルは、データを小さい順に並べたとき、特定の割合のデータがその値以下であることを示します。

  • p50(中央値): 50% のリクエストがこの値以下。平均よりも外れ値の影響を受けにくい。
  • p95: 95% のリクエストがこの値以下。大半のユーザーの体験を表す。
  • p99: 99% のリクエストがこの値以下。最も遅いユーザーでもこの範囲内であることを示す。

SLO 設計では、平均値ではなく p95 や p99 を重視します。理由は、少数の遅いリクエストが顧客体験を大きく損なうためです。たとえば、平均レスポンスタイムが 100ms でも、p99 が 5 秒であれば、1% のユーザーは非常に悪い体験を受けていることになります。

共通(全体)

  • 可用性: リクエスト成功率(2xx + 業務的成功)
  • レイテンシ: p50/p95/p99(受付→応答まで)。要セグメント(リージョン/端末/ISP)
  • エラー率: 4xx(顧客過失は除外方針を明示)、5xx、タイムアウト
  • スループット/負荷: RPS、同時実行数、キュー遅延、キャッシュヒット率
  • 依存健全性: DB/キャッシュ/外部 API の可用性・遅延
  • データ鮮度/整合性: 最終更新からの遅延、非同期整合の到達遅延

モバイルアプリ

  • 体感可用性: 主要画面の表示成功率(API 成功+UI レンダ成功)
  • 体感レイテンシ: 初回表示時間/重要操作の完了時間(p95)
  • クラッシュ率: セッションあたりクラッシュ率、ANR 率
  • オフライン耐性: 再送成功率、ローカルキャッシュヒット率
  • バージョン別品質: リリースチャネル別(Prod/Canary) SLI

Web アプリケーション

  • Core Web Vitals: LCP、FID/INP、CLS(p75 地域別)
  • ページ可用性: 主要ルートの 2xx 率+SSR/Edge 失敗率
  • フロントエラー: JS エラー率、API 呼び出しチェーンの成功率
  • レンダリング遅延: TTFB、TTI、Hydration 完了時間

顧客向け API 基盤

  • エンドポイント可用性: 成功率(業務成功で補正)
  • テール遅延: p95/p99 レイテンシ(エンドポイント/認証方式別)
  • 認証成功率: OAuth/JWT 検証成功率、レート制限ヒット率
  • Idempotency/整合性: 重複防止成功率、最終整合到達時間
  • 依存外部 API: サードパーティ別 SLI(契約 SLO と突合)

SLO サンプル(初期値の仮置き)

  • プロダクト SLO(体験)
    • サインイン成功率: 99.9%(7 日、全リージョン)
    • 初回表示 p95: ≤ 2.5s(Web)、≤ 3.0s(モバイル)
    • 注文完了成功率: 99.5%(7 日、業務成功で定義)
  • サービス SLO(技術)
    • API エンドポイント成功率: 99.95%(30 日、認証済み)
    • API レイテンシ p99: ≤ 800ms(Core)、≤ 1200ms(Non-Core)
    • DB 可用性: 99.99%(リージョン冗長、フェイルオーバ含む)
  • 依存 SLO
    • 決済外部 API 可用性: 99.9%(契約準拠)。違反時はフォールバック動作で緩和

注: 初期値は過去 30〜90 日のベースラインを計測し、顧客影響と実現可能性で調整。

エラーバジェット運用(意思決定ルール)

  • 期間: ローリング 30 日
  • 予算消費アクション
    • 25% 消費: 重要不具合の優先度引き上げ、実験を限定
    • 50% 消費: 新機能リリース凍結(高リスクのみ)、回帰抑止
    • 75% 消費: リリース全面凍結、信頼性改善スプリント
    • 100% 消費: 事後検証/学習共有、SLO 再評価

アラート設計(多窓・多焼却率)

  • 目標: 過負荷な常時アラートを避け、顧客に意味のある逸脱のみ検知
  • 代表的なルール
    • 短期高焼却: 5 分で 14% 以上の予算消費(SEV-1 可能性)
    • 中期中焼却: 1 時間で 5% 以上
    • 長期低焼却: 6 時間で 2% 以上(慢性的劣化)
  • セグメント別: リージョン/顧客セグメント/エンドポイント/アプリバージョン
  • 抑制: 予定メンテ中はサプレッション、依存障害時はコンポジット条件で一括抑制

計測と実装(New Relic / Datadog / Prometheus / OTel)

注意: 以下に示す指標名、属性名、メトリクス名は環境によって異なる場合があります。実際の実装時は、New Relic APM のメトリクス定義や OpenTelemetry の Semantic Conventions を参照し、お使いの環境に合わせて読み替えてください。

OpenTelemetry(推奨)

  • HTTP サーバ/クライアント、自動計装 + 手動属性(endpoint, customer_tier, region
  • 重要ドメインイベントはスパンイベント or ログで付与(業務成功/失敗の判定に使用)
# otel-collector(抜粋)
exporters:
  otlphttp/newrelic:
    endpoint: https://otlp.nr-data.net
    headers: { api-key: ${NEW_RELIC_API_KEY} }
  otlphttp/datadog:
    endpoint: https://api.datadoghq.com
    headers: { DD-API-KEY: ${DATADOG_API_KEY} }
processors:
  batch:
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp/newrelic, otlphttp/datadog]

APM 導入時の効果的な指標(New Relic / OpenTelemetry)

1. トランザクション(リクエスト)レベル指標

New Relic APM Transaction メトリクス

  • apm.service.transaction.duration(レスポンスタイム)
  • apm.service.transaction.apdex(Apdex スコア)
  • apm.service.transaction.throughput(スループット)

サービス全体の平均レスポンスタイム(p50/p95/p99)

このクエリは、サービス全体のレイテンシ分布を把握するために使用します。エンドポイント別に p50/p95/p99 を確認することで、どのエンドポイントが遅いか、テールレイテンシがどの程度かを特定できます。SLO の設定やボトルネックの特定に必須です。

# サービス全体の平均レスポンスタイム(p50/p95/p99
SELECT average(duration), percentile(duration, 95), percentile(duration, 99)
FROM Transaction
WHERE appName = 'order-service'
FACET transactionName
SINCE 1 hour AGO

エンドポイント別のスループット(RPS)

サービスへの負荷を把握するために必要です。スループットが急激に変化している場合は、トラフィックの異常やボトルネックが発生している可能性があります。また、キャパシティプランニングにも活用できます。

# エンドポイント別のスループット(RPS
SELECT rate(count(*), 1 minute) AS rps
FROM Transaction
WHERE appName = 'api-gateway'
FACET name
SINCE 1 hour AGO

Apdex スコア(満足度の指標)

Apdex(Application Performance Index)は、ユーザーの満足度を数値化した指標です。0-1 の範囲で表され、1 に近いほど満足度が高いことを示します。SLO の設定や、パフォーマンス改善の効果測定に有効です。

# Apdex スコア(満足度の指標)
SELECT apdex(duration, t:0.5) AS apdex_score
FROM Transaction
WHERE appName = 'user-service'
FACET name
SINCE 1 hour AGO

OpenTelemetry 標準メトリクス

HTTP リクエストのレイテンシ分布(OTel 標準メトリクス経由)

OpenTelemetry の標準メトリクスを使用することで、異なる APM ツール間で一貫した指標を取得できます。ヒストグラム形式でレイテンシ分布を確認することで、p50/p95/p99 などのパーセンタイルを後から計算できます。

# HTTP リクエストのレイテンシ分布(OTel 標準メトリクス経由)
SELECT histogram(http.server.request.duration, buckets)
FROM Metric
WHERE service.name = 'api-service'
FACET http.route
SINCE 1 hour AGO

2. データベース依存関係の SLI

スロークエリについて

スロークエリは、実行に時間がかかるデータベースクエリのことです。スロークエリが発生すると、アプリケーション全体のレスポンスタイムが劣化し、データベースの負荷も高くなります。p99 レイテンシを確認することで、最も遅いクエリを特定し、インデックスの追加やクエリの最適化を行うことができます。

New Relic Database メトリクス

  • apm.service.datastore.operation.duration(DB クエリ時間)
  • apm.service.datastore.operation.throughput(DB スループット)
  • apm.service.datastore.instance(接続先 DB インスタンス)

データベース操作の p99 レイテンシ(スロークエリ特定)

データベースクエリのレイテンシを p99 で確認することで、最も遅いクエリを特定できます。db.statement で実際の SQL 文も確認できるため、パフォーマンスチューニングの優先順位を決める際に有効です。LIMIT 20 で上位 20 件を取得し、最も影響の大きいクエリから対策を進めます。

# データベース操作の p99 レイテンシ(スロークエリ特定)
SELECT percentile(duration, 99) AS p99_latency
FROM Span
WHERE appName = 'order-service'
  AND name LIKE 'Datastore/%'
FACET name, `db.instance`, `db.statement`
SINCE 1 hour AGO
ORDER BY p99_latency DESC
LIMIT 20

データベース接続プール使用率

接続プールの使用率が高いと、新しいリクエストがデータベース接続を取得できずにタイムアウトする可能性があります。この指標を監視することで、接続プールサイズの調整が必要かを判断できます。

# データベース接続プール使用率
SELECT average(`db.connection_pool.active`)
FROM Metric
WHERE service.name = 'user-service'
FACET `db.instance`
SINCE 1 hour AGO

データベースエラー率

データベース操作のエラー率を監視することで、接続エラーやクエリエラーが発生していないかを確認できます。エラー率が高い場合は、データベースの可用性や設定に問題がある可能性があります。

# データベースエラー率
SELECT filter(count(*), WHERE error = true) / count(*) * 100 AS error_rate
FROM Span
WHERE appName = 'order-service'
  AND name LIKE 'Datastore/%'
FACET `db.instance`
SINCE 1 hour AGO

OpenTelemetry Database Span 属性

  • db.system(PostgreSQL, MySQL, Redis 等)
  • db.operation(SELECT, INSERT, UPDATE 等)
  • db.statement(SQL 文、要サンプリング)
  • db.connection_pool.active(アクティブ接続数)

Redis キャッシュヒット率の推定(OTel Span 経由)

キャッシュヒット率は、パフォーマンス改善の効果を測定するために重要な指標です。ヒット率が低い場合は、キャッシュキーの設計や TTL の設定を見直す必要があります。

# Redis キャッシュヒット率の推定(OTel Span 経由)
SELECT filter(count(*), WHERE name = 'redis GET' AND tags.cache_hit = 'true')
       / filter(count(*), WHERE name = 'redis GET') * 100 AS cache_hit_rate
FROM Span
WHERE service.name = 'product-service'
  AND name LIKE 'redis%'
SINCE 1 hour AGO

3. 外部 API 依存関係の SLI

外部 API 呼び出しの可用性とレイテンシ

マイクロサービスでは、決済プロバイダーや認証サービスなど外部 API に依存するケースが多く、これらの可用性とレイテンシは SLO に直接影響します。外部 API の可用性を監視することで、SLO 違反の原因が自社システムか外部依存かを特定できます。

# 外部 API 呼び出しの可用性とレイテンシ
SELECT filter(count(*), WHERE name LIKE 'External/%' AND error = false)
       / count(*) * 100 AS availability,
       average(duration) AS avg_latency,
       percentile(duration, 95) AS p95_latency
FROM Span
WHERE appName = 'payment-service'
FACET `external.host`, `external.url`
SINCE 1 hour AGO

サードパーティ API のエラー分類

外部 API でエラーが発生した場合、どのプロバイダーでどのようなエラーが起きているかを分類することで、問題の原因を特定しやすくなります。特に、契約している SLA と比較することで、補償請求の根拠にもなります。

# サードパーティ API のエラー分類
SELECT count(*)
FROM Span
WHERE appName = 'notification-service'
  AND name LIKE 'External/%'
  AND error = true
FACET `external.host`, error.message
SINCE 1 hour AGO
ORDER BY count(*) DESC

OpenTelemetry External Span 属性

  • http.url(外部 API の URL)
  • http.status_code(HTTP ステータスコード)
  • net.peer.name(外部ホスト名)

決済 API のレイテンシとタイムアウト率

決済処理はビジネスに直結するため、特に厳密な監視が必要です。p99 レイテンシとタイムアウト率を監視することで、決済プロバイダーのパフォーマンス問題を早期に発見し、フォールバック処理を適切に実行できます。

# 決済 API のレイテンシとタイムアウト率
SELECT percentile(duration, 99) AS p99_latency,
       filter(count(*), WHERE tags.http.status_code = 504 OR tags.error = 'timeout')
       / count(*) * 100 AS timeout_rate
FROM Span
WHERE service.name = 'payment-service'
  AND tags.http.url LIKE '%payment-provider.com%'
SINCE 1 hour AGO

4. エラー分析とトレース

New Relic Error メトリクス

  • apm.service.error.count(エラー数)
  • apm.service.error.rate(エラー率)

エラートレースの取得(エラー発生時のリクエスト全体を追跡)

エラーが発生した際に、分散トレーシングでリクエスト全体を追跡することで、どのサービス、どのエンドポイントでエラーが発生したかを特定できます。特にマイクロサービス環境では、複数サービスを跨るエラーの根本原因を特定するために必須です。

# エラートレースの取得(エラー発生時のリクエスト全体を追跡)
SELECT trace_id, timestamp, error.message, error.class
FROM Span
WHERE appName = 'order-service'
  AND error = true
FACET transactionName, `error.class`
SINCE 1 hour AGO
ORDER BY timestamp DESC
LIMIT 100

エラー率の推移(トレンド分析)

エラー率の推移を時系列で確認することで、エラーが増加傾向にあるか、特定のタイミングで集中しているかを把握できます。TIMESERIES を使用することで、エラーの発生パターンを可視化し、原因特定の手がかりとなります。

# エラー率の推移(トレンド分析)
SELECT rate(count(*), 5 minutes) AS error_rate
FROM Span
WHERE appName = 'user-service'
  AND error = true
FACET `error.class`
TIMESERIES SINCE 6 hours AGO

エラーの根本原因分析(例外スタックトレース)

エラーの種類とメッセージを集計することで、最も頻繁に発生しているエラーを特定できます。これにより、修正の優先順位を決定し、影響の大きいエラーから対処することができます。

# エラーの根本原因分析(例外スタックトレース)
SELECT count(*), latest(error.message)
FROM Error
WHERE appName = 'api-gateway'
FACET `error.class`, `error.message`
SINCE 1 hour AGO
ORDER BY count(*) DESC
LIMIT 20

OpenTelemetry Error 計装

エラー種別のセグメンテーション

エラーの種類と発生しているエンドポイントを組み合わせて分析することで、特定のエンドポイントで特定のエラーが集中しているかを把握できます。これにより、バグ修正や設定変更の優先順位を決定できます。

# エラー種別のセグメンテーション
SELECT count(*)
FROM Span
WHERE service.name = 'auth-service'
  AND tags.exception.type IS NOT NULL
FACET tags.exception.type, tags.http.route
SINCE 1 hour AGO

5. パフォーマンスボトルネック特定

N+1 クエリについて

N+1 クエリは、アプリケーションコードでよく発生するパフォーマンス問題です。たとえば、ユーザー一覧を取得した後、各ユーザーの詳細情報を個別にクエリする場合、1回のクエリ(ユーザー一覧)と N 回のクエリ(各ユーザーの詳細)が発生します。これを防ぐには、JOIN やバッチ読み込み(Eager Loading)を使用します。同一トランザクション内の DB 呼び出し数が多い場合、N+1 クエリが発生している可能性があります。

New Relic Transaction Breakdown

トランザクション内の時間配分(DB/外部 API/アプリケーションロジック)

レスポンスタイムが遅い原因を特定するために、トランザクション内でどの処理に時間がかかっているかを分解します。データベース、外部 API、アプリケーションロジックのいずれにボトルネックがあるかを把握することで、最適化すべき箇所を特定できます。

# トランザクション内の時間配分(DB/外部 API/アプリケーションロジック)
SELECT average(duration) AS avg_duration,
       average(`database.duration`) AS avg_db_time,
       average(`external.duration`) AS avg_external_time
FROM Transaction
WHERE appName = 'order-service'
  AND transactionName = 'OrdersController#create'
SINCE 1 hour AGO

N+1 クエリの検出(同一トランザクション内の DB 呼び出し数が多いケース)

同一トランザクション内でデータベース呼び出しが多すぎる場合、N+1 クエリや不必要なクエリが発生している可能性があります。このクエリで、データベース呼び出し数が多いトランザクションを特定し、コードの最適化を行います。

# N+1 クエリの検出(同一トランザクション内の DB 呼び出し数が多いケース)
SELECT count(*) AS db_call_count, average(duration) AS transaction_duration
FROM Transaction
WHERE appName = 'product-service'
FACET transactionName
SINCE 1 hour AGO
HAVING db_call_count > 10
ORDER BY db_call_count DESC

OpenTelemetry Span 階層分析

トランザクション内で最も時間がかかっているスパンを特定することで、ボトルネックとなっている処理を特定できます。子スパンも含めて分析することで、どの処理が最も影響を与えているかを把握できます。

# 最も時間がかかっているスパン(子スパン含む)
SELECT percentile(duration, 95) AS p95_duration,
       sum(duration) AS total_time
FROM Span
WHERE service.name = 'checkout-service'
  AND parent.id IS NOT NULL
FACET name, operation
SINCE 1 hour AGO
ORDER BY total_time DESC
LIMIT 30

6. セグメンテーション分析(顧客/リージョン/バージョン別)

カスタム属性によるセグメンテーション

顧客ティア別のレイテンシ

プレミアム顧客とフリー顧客でパフォーマンス要件が異なる場合、顧客ティア別にレイテンシを分析することで、サービスレベルの差別化が適切に行われているかを確認できます。

# 顧客ティア別のレイテンシ(カスタム属性 `customer.tier` を前提)
SELECT percentile(duration, 95) AS p95_latency,
       average(duration) AS avg_latency
FROM Transaction
WHERE appName = 'api-gateway'
FACET `customer.tier`, transactionName
SINCE 1 hour AGO

リージョン別のエラー率

グローバル展開しているサービスでは、リージョンやデータセンターごとにエラー率が異なる可能性があります。この分析により、特定リージョンのインフラやネットワークに問題がないかを確認できます。

# リージョン別のエラー率
SELECT filter(count(*), WHERE error = true) / count(*) * 100 AS error_rate
FROM Span
WHERE appName = 'search-service'
FACET `region`, `datacenter`
SINCE 1 hour AGO

アプリバージョン別のパフォーマンス比較

新しいバージョンをデプロイした際、パフォーマンスが劣化していないかを確認するために必要です。バージョン間の比較により、リグレッションを早期に発見できます。

# アプリバージョン別のパフォーマンス比較
SELECT percentile(duration, 99) AS p99_latency,
       rate(count(*), 1 minute) AS throughput
FROM Transaction
WHERE appName = 'mobile-api'
FACET `app.version`, transactionName
SINCE 1 hour AGO

OpenTelemetry Resource 属性

  • service.version(アプリケーション バージョン)
  • deployment.environment(環境: prod, staging 等)
  • cloud.region(リージョン)

デプロイ環境別のメトリクス比較

本番環境とステージング環境でパフォーマンスを比較することで、環境間の差分を把握できます。また、新しいバージョンをデプロイした際、既存バージョンとパフォーマンスを比較することで、リグレッションを早期に発見できます。

# デプロイ環境別のメトリクス比較
SELECT average(duration), percentile(duration, 95)
FROM Span
WHERE service.name = 'order-service'
FACET resource.attributes.deployment.environment, resource.attributes.service.version
SINCE 1 hour AGO

7. 分散トレーシングによるエンドツーエンド分析

トレース全体の成功率(複数サービスに跨るリクエスト)

マイクロサービス環境では、1 つのリクエストが複数のサービスを跨ります。トレース全体の成功率を確認することで、どのサービスでエラーが発生しているかを把握し、SLO 違反の原因を特定できます。

# トレース全体の成功率(複数サービスに跨るリクエスト)
SELECT filter(count(*), WHERE error = false) / count(*) * 100 AS trace_success_rate
FROM Trace
WHERE trace.id IN (
  SELECT trace.id FROM Span WHERE appName = 'api-gateway' AND transactionName = '/orders' SINCE 1 hour AGO
)
SINCE 1 hour AGO

トレース全体のレイテンシ分解(各サービスがどの程度時間を使っているか)

エンドツーエンドのレスポンスタイムが遅い場合、どのサービスがボトルネックになっているかを特定するために必要です。各サービスが使っている時間を分解することで、最適化すべきサービスを明確にできます。

# トレース全体のレイテンシ分解(各サービスがどの程度時間を使っているか)
SELECT average(duration) AS service_time
FROM Span
WHERE trace.id IN (
  SELECT trace.id FROM Span WHERE appName = 'api-gateway' AND transactionName = '/orders' SINCE 1 hour AGO
)
FACET appName, name
SINCE 1 hour AGO
ORDER BY service_time DESC

8. バックグラウンドジョブ/非同期処理の SLI

メッセージキュー処理のレイテンシ

バックグラウンドジョブや非同期処理のパフォーマンスを監視することで、処理が遅延していないかを確認できます。メッセージキューごとに分析することで、特定のキューに問題がないかを特定できます。

# メッセージキュー処理のレイテンシ
SELECT percentile(duration, 95) AS p95_processing_time
FROM Span
WHERE appName = 'notification-worker'
  AND name LIKE 'messaging.%' OR name LIKE 'kafka.%'
FACET `messaging.destination.name`
SINCE 1 hour AGO

キュー滞留時間(メッセージがキューに入ってから処理開始までの時間)

キューにメッセージが溜まっている場合、ワーカーの処理能力が不足しているか、メッセージの生成速度が処理速度を上回っている可能性があります。滞留時間を監視することで、スケーリングが必要かを判断できます。

# キュー滞留時間(メッセージがキューに入ってから処理開始までの時間)
SELECT average(`messaging.message.enqueued.time` - timestamp) AS avg_queue_time
FROM Span
WHERE service.name = 'order-processor'
  AND name LIKE 'kafka.%'
FACET `messaging.destination.name`
SINCE 1 hour AGO

OpenTelemetry Messaging 属性

  • messaging.system(Kafka, RabbitMQ, SQS 等)
  • messaging.destination.name(トピック/キュー名)
  • messaging.operation(send, receive, process)

メッセージ処理のスループットとエラー率

メッセージキュー処理の健全性を把握するために必要です。スループットが低下している場合、ワーカーの処理能力やネットワークに問題がある可能性があります。エラー率と合わせて監視することで、問題の早期発見が可能になります。

# メッセージ処理のスループットとエラー率
SELECT rate(count(*), 1 minute) AS throughput,
       filter(count(*), WHERE error = true) / count(*) * 100 AS error_rate
FROM Span
WHERE service.name = 'payment-worker'
  AND tags.messaging.operation = 'process'
FACET tags.messaging.destination.name
SINCE 1 hour AGO

9. リソース使用状況(CPU/メモリ/GC)

アプリケーションの CPU/メモリ使用率(インフラ連携時)

アプリケーションのリソース使用状況を監視することで、スケーリングのタイミングを判断できます。CPU やメモリ使用率が継続的に高い場合、インスタンスの増強や最適化が必要です。

# アプリケーションの CPU/メモリ使用率(インフラ連携時)
SELECT average(cpuPercent), average(memoryResidentSizeBytes)
FROM SystemSample
WHERE entityGuid = (
  SELECT entityGuid FROM Metric WHERE appName = 'order-service' LIMIT 1
)
SINCE 1 hour AGO
TIMESERIES

GC の頻度と停止時間(JVM アプリケーション)

Java アプリケーションでは、ガベージコレクション(GC)がアプリケーションのパフォーマンスに大きく影響します。GC の頻度が高すぎる場合や、停止時間が長い場合、メモリリークやヒープサイズの不適切な設定が原因の可能性があります。

# GC の頻度と停止時間(JVM アプリケーション)
SELECT average(`gc.pause.time`), rate(sum(`gc.collections.count`), 1 minute) AS gc_rate
FROM Metric
WHERE service.name = 'user-service'
FACET `gc.type`
SINCE 1 hour AGO

10. ビジネスイベントとの連携(カスタムイベント)

注文完了イベントとトレースの相関

技術的な SLI だけでなく、ビジネスイベント(注文完了、決済成功など)とトレースを相関させることで、ビジネス KPI と技術指標を結びつけることができます。これにより、ビジネス影響を考慮した SLO 設計が可能になります。

# 注文完了イベントとトレースの相関
SELECT t.trace_id, t.duration, e.order_amount, e.order_id
FROM Transaction t
INNER JOIN (
  SELECT * FROM OrderCompletedEvent SINCE 1 hour AGO
) e ON t.trace_id = e.trace_id
WHERE t.appName = 'checkout-service'
LIMIT 100

業務ロジックレベルの SLI(カスタムメトリクス経由)

アプリケーションコードでカスタムメトリクスを計測することで、業務ロジック特有の SLI を定義できます。たとえば、注文処理時間、決済承認時間など、ビジネスプロセスに直結する指標を監視できます。

# 業務ロジックレベルの SLI(カスタムメトリクス経由)
SELECT average(order_processing_time)
FROM CustomMetric
WHERE metricName = 'business.order.processing_time'
  AND environment = 'production'
FACET customer_segment
SINCE 1 hour AGO

実装時の注意点

  1. 変数名・指標名の読み替え:

    • New Relic では appNameentity.nameservice.name になる場合があります
    • OpenTelemetry の属性名は Semantic Conventions に準拠しますが、実装によって異なる場合があります
    • 実際の環境では、New Relic の Metrics API や OpenTelemetry の Semantic Conventions を参照してください
  2. サンプリング:

    • 高トラフィック環境ではトレースサンプリングが必要な場合があります
    • エラーや遅いリクエストは 100% サンプリング、正常なリクエストは低サンプリングレートを推奨
  3. カスタム属性の付与:

    • ビジネスコンテキスト(customer.id, order.id, feature_flag 等)を属性として追加すると、セグメンテーション分析が効果的になります
    • ただし、機密情報(パスワード、トークン等)は属性に含めないでください
  4. パフォーマンスオーバーヘッド:

    • トレーシングのオーバーヘッドは通常 1-3% 程度ですが、高頻度な Span 作成や大量の属性付与は避けてください
    • データベースクエリ文字列(db.statement)は特に長くなる可能性があるため、長さ制限やサンプリングを検討してください

New Relic(基本 NRQL 例)

  • API 成功率(業務成功で補正)
SELECT filter(count(*), WHERE appName = 'api' AND httpResponseCode LIKE '2%%' AND businessSuccess = true)
       / count(*) * 100
FROM Span
WHERE spanKind = 'SERVER' AND name LIKE 'HTTP %'
SINCE 7 days AGO
  • エンドポイント p99 レイテンシ(地域別)
SELECT percentile(duration, 99) FACET endpoint, region
FROM Span
WHERE appName = 'api' AND spanKind = 'SERVER'
SINCE 7 days AGO
  • エラーバジェット消費率(SLO 99.95% 仮定)
FROM Metrics SELECT rate(sum(apm.service.error.count), 5 minutes) AS errors, rate(sum(apm.service.request.count), 5 minutes) AS req
| SELECT (errors / req) AS errorRate,
         (errorRate - (1 - 0.9995)) / (1 - 0.9995) * 100 AS burnPct

Datadog(Monitor/Query 例)

  • 可用性(成功率)
sum:trace.http.server.requests{service:api,env:prod,http.status_code:2xx}.as_count()
/
sum:trace.http.server.requests{service:api,env:prod}.as_count()
  • p99 レイテンシ
p99:trace.http.server.duration{service:api,env:prod,endpoint:/orders}
  • 多窓多焼却率アラート(概念)
# 5m/1h/6h の 3 ウィンドウで burn rate を評価し、任意 2 条件一致で通知
(query1) error_budget_burn{window:5m} > 14
AND
(query2) error_budget_burn{window:1h} > 5
OR
(query3) error_budget_burn{window:6h} > 2

Prometheus/Alertmanager(PromQL 例)

# 成功率(業務成功ラベル success="true" 前提)
sum(rate(http_requests_total{job="api",success="true"}[5m]))
/ sum(rate(http_requests_total{job="api"}[5m]))

# p99 レイテンシ
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{job="api"}[5m])) by (le, endpoint))

ダッシュボード(決め打ちしない最小構成)

  • エグゼクティブ: プロダクト SLO 達成率、エラーバジェット残量、主要 KPI
  • SRE オンコール: 可用性/遅延(p50/p95/p99)、依存健全性、最近のデプロイ
  • チーム別: 担当サービス SLI、バージョン別品質、実験/Feature Flag 影響
  • 分析: セグメント別の逸脱(地域/顧客/端末/ISP)

導入ステップ(90 日プランの例)

  1. 0–30 日: 実計測(現状把握)/ 重要フロー定義 / 暫定 SLO 設定
  2. 31–60 日: アラート多窓化 / 依存 SLI 連鎖 / ダッシュボード整備
  3. 61–90 日: エラーバジェット運用ルールの合意 / レビューサイクル確立

よくあるアンチパターンと回避

  • 指標が多すぎて誰も見ない → トップ 3 の意思決定指標を固定
  • 失敗の定義が曖昧 → 「業務成功」のイベント埋め込みで補正
  • p99 無視 → テール劣化は体験を強く毀損。必ず追う
  • 単窓アラートでノイズ過多 → 多窓多焼却率に切替
  • 依存の可視化不足 → 外部 API/DB/キャッシュの SLI をセットで管理

参考: 重要フロー別 SLI チートシート

  • サインイン
    • 成功率(業務成功)/ p95 レイテンシ / レート制限ヒット率 / MFA 失敗率
  • 検索
    • 結果返却成功率 / p95 レイテンシ / キャッシュヒット率 / ゼロ件率
  • 注文
    • 受付→確定までの業務成功率 / p99 レイテンシ / 決済外部依存の可用性
  • 通知
    • キュー滞留時間 / 配信成功率 / 再送率

参考: SLO 定義テンプレート

- Name: <SLO >
- Owner: <チーム/責任者>
- Customer impact: <顧客影響の説明>
- SLI: <数式/NRQL/PromQL/Datadog Query>
- Target: <99.9% / p99 800ms >
- Window: <7d/30d>
- Segmentation: <region, tier, endpoint, app_version>
- Alerting: <多窓多焼却率条件>
- Error budget policy: <25/50/75/100% 時の対応>
- Review cadence: <毎週/隔週/リリース毎>

参考資料


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?