SLI(Service Level Indicator、サービスレベル指標)は、ユーザーから見たサービスの良し悪しを数値で表す指標です。Google SREは「良いイベントの数÷全イベントの数」という比率で定義することを推奨しており、SLO(目標値)もSLA(契約)も、このSLIの値を土台にして成り立ちます。この記事では、SLIの定義とSLO・SLAとの役割の違い、サービスの種類ごとの指標の選び方、測る場所によって見えなくなる障害を整理します。後半では、Prometheus 3.14.0で実際に動かして確かめた記録ルールも掲載します。なお、NVIDIAのグラフィックボード連結技術(Scalable Link Interface)も「SLI」と呼ばれますが、この記事で扱うのは運用監視のSLIです。
まとめ:SLIは「良いイベント÷全イベント」で測る指標
- SLIは測った値、SLOはその値に置く目標、SLAは顧客との契約です。SLIが決まっていないと、SLOを達成できているかどうかを判定できません。
- Google SRE Workbookは、SLIを「良いイベントの数÷全イベントの数」の比率で表すことを推奨しています。0%〜100%に収まるので、サービスが違っても同じ尺度で比べられます。
- 指標の型はサービスの種類で決まります。リクエストを処理するサービスなら可用性・レイテンシ・品質、データパイプラインなら鮮度・正確性・網羅性、ストレージなら耐久性です。
- 同じSLIでも、どこで測るかで捕まえられる障害が変わります。サーバーログでは、バックエンドに届かなかったリクエストを数えられません。
- PrometheusでSLIを比率として計算すると、リクエストがゼロの時間帯は0÷0でNaNになります。NaNに対する大小比較は偽になるため、閾値超過で通知するアラートは発火しません。ただし、不等比較の
!=は真になります。
SLIの定義とSLO・SLAとの役割分担
Google SRE本によるSLIの定義と代表的な指標
Google SRE本(Site Reliability Engineering)の第4章「Service Level Objectives」は、SLIを「提供するサービスレベルのある側面について、慎重に定義した定量的な尺度(a carefully defined quantitative measure of some aspect of the level of service that is provided)」と定義しています。代表例として同章が挙げているのは、リクエストのレイテンシ、エラー率、スループット、可用性、耐久性です。
同章は、平均値ではなく分布で見るように注意を促しています。平均値ではロングテールの遅延が隠れてしまうためです。例として挙げられているシステムでは、典型的なリクエストは約50msで処理される一方、5%のリクエストはその20倍遅くなっています。レイテンシのSLIを「平均応答時間」だけで定義すると、遅い5%のリクエストが平均値に埋もれ、その遅さや割合を判別できません。
SLI・SLO・SLAの役割と未達時の対応の比較
| 項目 | SLI | SLO | SLA |
|---|---|---|---|
| 正式名 | Service Level Indicator | Service Level Objective | Service Level Agreement |
| 中身 | サービスレベルの定量指標 | SLIに置く目標値 | 顧客との契約 |
| 例 | 成功リクエスト比率 99.95% | 30日間で99.9%以上 | 99.5%未満なら返金 |
| 下回ったとき | 値が変わるだけ | リリース判断などを見直す | 契約所定の補償等の対象になる |
目標値の決め方とエラーバジェットの運用はSLOとは?SLA・SLIとの違いと設定方法をわかりやすく解説で、稼働率を契約にするときの交渉項目はSLAとは?SLO・SLIとの違いと稼働率の決め方・監視実装をエンジニア視点で解説で扱っています。この記事は、その土台になる「何をどう測るか」に絞ります。
SLIとKPIの測定目的と対象範囲の違い
KPIは、事業や業務の目標達成度を測る重要指標です。売上・コンバージョン率・解約率のほか、運用上の指標を選ぶこともあります。SLIはサービスレベルの特定の側面を測る指標で、成功率のほか、レイテンシやスループットなども含みます。たとえば決済APIの成功リクエスト比率はSLIですが、決済完了件数そのものは事業のKPIです。この2つは連動することはありますが、同じものではありません。CPU使用率は運用上のKPIにはなり得ますが、この記事ではユーザー体験を測るSLIには採用しません。ユーザーが直接体験する値ではないので、原因を調べるための内部指標として扱います。
サービスの種類ごとに決まるSLIの型
SRE Workbookの「Implementing SLOs」章は、サービスの種類ごとに使えるSLIを表2-1として示しています。要点は次のとおりです。
| サービスの種類 | SLIの型 | 良いイベントの例 |
|---|---|---|
| リクエスト駆動 | 可用性 | 成功応答を返したリクエスト |
| リクエスト駆動 | レイテンシ | 閾値より速かったリクエスト |
| リクエスト駆動 | 品質 | 縮退せずに返した応答 |
| パイプライン | 鮮度 | 一定時間内に更新されたデータ |
| パイプライン | 正確性 | 正しい値を出力したレコード |
| パイプライン | 網羅性 | 処理できたデータ |
| ストレージ | 耐久性 | 読み出せたデータ |
リクエスト駆動型は可用性・レイテンシ・品質の3つ
Web APIやフロントエンドでは、まず可用性とレイテンシを置きます。レイテンシは「平均◯ms」ではなく、「100msより速かったリクエストの比率」のように、閾値を使って良いイベントを数える形にします。Workbookは、閾値を複数置く例として「90%のリクエストが100msより速い」「99%のリクエストが400msより速い」を挙げています。品質は、負荷が高いときに検索結果を一部省いて返すなど、機能を落としてでも応答を返す設計のサービスで必要になります。そうしたサービスでは、成功した応答のうち縮退していないものの比率を別に測らないと、品質の低下が可用性のSLIに現れません。
リクエスト数・エラー数・所要時間の3つで見るREDメソッドとは?マイクロサービス監視の3指標(流量・失敗・所要時間)と実装手順を解説や、飽和度まで含めたGolden Signals(4つのゴールデンシグナル)とは?SREの監視指標と実装・アラート設計を解説は、SLIの候補を洗い出すときの出発点になります。
パイプライン型の鮮度SLIとウォーターマークによる計測
バッチ処理やETLには、リクエストの成否という概念がありません。そのため、データそのものの状態を測ります。Workbookの例では、パイプラインがテーブルを更新するときに更新時刻(ウォーターマーク)を記録しておき、定期的なクエリで「新しいレコードの数÷全レコードの数」を数える実装が示されています。ただし同章は、この方法ではすべての古いレコードが同じ重さで数えられ、何人のユーザーがそのデータを見たかは反映されないとも注記しています。
リクエスト単位と時間枠単位で変わるSLIの数え方
Google Cloud Monitoringのドキュメントは、SLIを2つの数え方に分けています。リクエスト単位(request-based)は「良いリクエスト数÷全リクエスト数」です。時間枠単位(windows-based)は「良さの基準を満たした計測区間の数÷全区間の数」です。
違いが出るのは、負荷が時間帯によって偏るときです。同じ1分間の全面停止でも、1分あたり10,000リクエストのピーク時なら10,000件の失敗として数えられ、1分あたり100リクエストの深夜なら100件です。月間1億リクエストのサービスで計算すると、前者はSLIを約0.01ポイント、後者は約0.0001ポイント下げます。一方、1分単位の時間枠で数えると、どちらも30日間の43,200区間のうち1区間の失敗です。ドキュメントには、Cloud Monitoringで生の値としてレイテンシのパーセンタイルしか取れない場合は、時間枠単位を使う必要があるという注記もあります。利用者数に比例して影響を見たいならリクエスト単位、「利用者が何分間困ったか」を見たいなら時間枠単位を選びます。
SLI仕様・SLI実装の区別と測定地点の選定
SRE Workbookは、SLIを初めて定義するときに2段階に分けることを勧めています。
- SLI仕様(specification):測り方とは切り離して、ユーザーにとって大事な結果を定めたもの。例は「ホームページのリクエストのうち100ms未満で読み込めた比率」です。
- SLI実装(implementation):SLI仕様に、具体的な測り方を組み合わせたもの。
1つのSLI仕様に対して、SLI実装は複数考えられます。Workbookは、実装ごとに品質(ユーザー体験をどれだけ正確に表すか)、カバレッジ(どれだけ多くのユーザーの体験を拾えるか)、コストが違うと説明しています。測定地点は、同章が挙げる4つから選びます。
| 測定地点 | 取りこぼすもの | 導入コスト |
|---|---|---|
| アプリサーバーのログ | バックエンドに届かない失敗 | 低い |
| ロードバランサーの監視 | LBより手前の経路の失敗 | 低い |
| ブラックボックス監視 | 一部ユーザーだけの障害 | 中程度 |
| クライアント側の計装 | 比較的少ない | 高い |
Workbookが例に挙げるサービスでは、ロードバランサーの監視を採用しています。理由として、メトリクスがすでにあり、アプリサーバーのログよりユーザーの体験に近いことが挙げられています。一方、サーバーログで測る実装は「バックエンドに届かなかったリクエストを取りこぼす」と明記されています。ブラウザを動かすプローバーはネットワークに届かない失敗を拾えますが、一部のユーザーにだけ起きる問題は見逃す可能性があります。ページ内のJavaScriptで計測する方法が最も正確ですが、計測結果を受け取る基盤を新たに作る必要があり、その基盤にも信頼性が求められます。
判断の順番としては、まずロードバランサーのメトリクスでSLIを作り、SLIが正常なのにユーザーから苦情が来るようになったら測定地点をユーザー側に寄せるのが現実的です。Workbookも、SLIを改善する方法として「測定をユーザーに近づける」と「カバレッジを広げる」の2つを挙げています。外形監視はCloudWatch Syntheticsとは?Canaryの作り方・ランタイム選定・料金をAWS外形監視の実装目線で解説、クライアント計装はリアルユーザーモニタリング(RUM)とは|実ユーザー計測の仕組み・合成監視との違い・導入判断で扱っています。
PrometheusでSLIを記録ルールにする手順
ここからは、2026年8月17日にリリースされたPrometheus 3.14.0に同梱のpromtoolで、実際にテストが通ったルールを掲載します。Prometheus本体の構築はPrometheusで監視を構築する手順|exporter設計・PromQL・保持期間の見積りを参照してください。
可用性・レイテンシSLIの記録ルール定義
可用性は「5xx以外の応答÷全応答」、レイテンシは「300ms以下のバケットの件数÷全件数」で定義します。クラシックヒストグラムの累積バケットは「le以下」の件数です。この例では、0.3秒の境界を持つバケットとcount系列が公開されていることが前提です。また、応答コード別のカウンタは、発生前から0で公開してください。
可用性の分子に or vector(0) を付けているのは、全面障害のときにSLIが消えるのを防ぐためです。5xx以外の応答の系列が一度も作られていない状態で500応答だけが増えると、分子は0ではなく「結果なし」になり、SLI全体も結果を返しません。つまり、最も知りたい全面障害の瞬間にSLIが0%ではなく空になります。下のテストの2件目は、この状況で0が返ることを確かめるものです。
# rules.yml
groups:
- name: sli-api
rules:
- record: sli:availability:ratio_rate5m
expr: |
(sum(rate(http_requests_total{job="api",code!~"5.."}[5m])) or vector(0))
/
sum(rate(http_requests_total{job="api"}[5m]))
- record: sli:latency_300ms:ratio_rate5m
expr: |
sum(rate(http_request_duration_seconds_bucket{job="api",le="0.3"}[5m]))
/
sum(rate(http_request_duration_seconds_count{job="api"}[5m]))
SRE Workbookも、同じ章でPrometheusの例を示しています。ただし、Workbookのレイテンシの例は histogram_quantile(0.9, ...) でパーセンタイルを求める式です。こちらは「値」を返すので、「良いイベントの比率」の形にはなりません。比率として扱いたい場合は、上のようにバケットの件数から計算します。
promtoolのユニットテストによるSLI値の検証
1分ごとに200応答が99件、500応答が1件増えるデータを与えると、可用性は0.99になるはずです。レイテンシは、300ms以下が95件、全体が100件増えるので0.95になるはずです。
# test.yml
rule_files:
- rules.yml
evaluation_interval: 1m
tests:
- interval: 1m
input_series:
- series: 'http_requests_total{job="api",code="200"}'
values: '0+99x10'
- series: 'http_requests_total{job="api",code="500"}'
values: '0+1x10'
- series: 'http_request_duration_seconds_bucket{job="api",le="0.3"}'
values: '0+95x10'
- series: 'http_request_duration_seconds_count{job="api"}'
values: '0+100x10'
promql_expr_test:
- expr: sli:availability:ratio_rate5m
eval_time: 10m
exp_samples:
- labels: 'sli:availability:ratio_rate5m'
value: 0.99
- expr: sli:latency_300ms:ratio_rate5m
eval_time: 10m
exp_samples:
- labels: 'sli:latency_300ms:ratio_rate5m'
value: 0.95
# 500応答の系列しか無い(全面障害)
- interval: 1m
input_series:
- series: 'http_requests_total{job="api",code="500"}'
values: '0+5x10'
promql_expr_test:
- expr: sli:availability:ratio_rate5m
eval_time: 10m
exp_samples:
- labels: 'sli:availability:ratio_rate5m'
value: 0
$ promtool test rules test.yml
SUCCESS
無通信時のNaNと閾値アラートの不発
上のテストの入力を、11分目以降はカウンタが増えない値('0+99x10 990x10' など)に延ばし、18分目の値を「結果なし」と期待して評価しました。すると結果は空にならず、次のように NaN が返りました。分子も分母も0なので、0÷0になるためです。
FAILED:
expr: "sli:availability:ratio_rate5m", time: 18m,
exp: nil
got: {__name__="sli:availability:ratio_rate5m"} NaN
NaNに対する大小比較は偽になりますが、不等比較の != は真になります。「エラー比率が閾値を超えたら通知する」ルールで確かめた結果は次のとおりです。エラー率2%が続くデータではアラートが発火し、70分間トラフィックが止まったデータではエラー比率がNaNになり、アラートは発火しませんでした。
# rules2.yml
groups:
- name: sli-api
rules:
- record: sli:error:ratio_rate5m
expr: |
sum(rate(http_requests_total{job="api",code=~"5.."}[5m]))
/
sum(rate(http_requests_total{job="api"}[5m]))
- record: sli:error:ratio_rate1h
expr: |
sum(rate(http_requests_total{job="api",code=~"5.."}[1h]))
/
sum(rate(http_requests_total{job="api"}[1h]))
- alert: SLIErrorBudgetFastBurn
expr: |
sli:error:ratio_rate1h > (14.4 * 0.001)
and
sli:error:ratio_rate5m > (14.4 * 0.001)
labels:
severity: page
# test2.yml
rule_files:
- rules2.yml
evaluation_interval: 1m
tests:
# 2%のエラー率が続く(SLO 99.9%に対しバーンレート20)
- interval: 1m
input_series:
- series: 'http_requests_total{job="api",code="200"}'
values: '0+98x90'
- series: 'http_requests_total{job="api",code="500"}'
values: '0+2x90'
alert_rule_test:
- eval_time: 70m
alertname: SLIErrorBudgetFastBurn
exp_alerts:
- exp_labels:
severity: page
promql_expr_test:
- expr: sli:error:ratio_rate1h
eval_time: 70m
exp_samples:
- labels: 'sli:error:ratio_rate1h'
value: 0.02
# 70分間トラフィックが止まる(0/0=NaN)
- interval: 1m
input_series:
- series: 'http_requests_total{job="api",code="200"}'
values: '500x90'
- series: 'http_requests_total{job="api",code="500"}'
values: '500x90'
alert_rule_test:
- eval_time: 80m
alertname: SLIErrorBudgetFastBurn
exp_alerts: []
promql_expr_test:
- expr: count(sli:error:ratio_rate1h != sli:error:ratio_rate1h)
eval_time: 80m
exp_samples:
- labels: '{}'
value: 1
NaNだけは自分自身と等しくならないので、x != x でNaNの系列を抽出できます。上流の障害でリクエストがまったく届かなくなったときも、SLIのアラートは鳴りません。そのため、通常はリクエストがある時間帯に無通信が続いた場合は、別のアラートで検知します。夜間や休日の予定された無通信は通知対象から除外し、メトリクス自体の欠損や外形監視の失敗も別に監視します。
Prometheus 3系のleラベル正規化と整数指定ルールの不一致
Prometheus 3系では、クラシックヒストグラムの le ラベルとサマリーの quantile ラベルが、取り込み時に浮動小数点の表記へ正規化されます。公式の移行ガイドには、le="1" として公開されたメトリクスは、どのプロトコルで取り込んでも le="1.0" として保存されると書かれています。そのため、2系で le="1" と整数で書いていたSLIのルールは、3系に上げると何にも一致しなくなります。一致する系列がないと、比率の式は結果を返しません。そのため、NaNの場合と同じく、アラートは鳴らないままになります。移行ガイドが推奨しているのは、整数で書いた参照を le="1.0" の形に直す方法です。
SLIをアラートにつなぐバーンレートの設計
SLIの比率は、そのまま閾値と比べるより、「エラーバジェットをどれだけの速さで使っているか」(バーンレート)に換算してアラートにします。SRE Workbookの「Alerting on SLOs」章は、SLO 99.9%のサービス向けに、長い時間窓と短い時間窓を組み合わせる出発点として次の値を示しています。
| 通知 | 長い窓 | 短い窓 | バーンレート | 予算消費 |
|---|---|---|---|---|
| ページ | 1時間 | 5分 | 14.4 | 2% |
| ページ | 6時間 | 30分 | 6 | 5% |
| チケット | 3日 | 6時間 | 1 | 10% |
先ほどのルールの 14.4 * 0.001 は、この表の1行目に当たります。SLO 99.9%のエラー比率0.001の14.4倍のペースが1時間続くと、30日(720時間)分の予算の2%を使い切ります(14.4×1÷720=2%)。短い窓の5分は、障害が収まったあとにアラートがすぐ解除されるようにするための条件です。予算の配分と使い切ったときの運用ルールは、SLO側の設計になるためSLOとは?SLA・SLIとの違いと設定方法をわかりやすく解説に譲ります。通知の量を抑える考え方はアラート疲れとは|原因と対策を監視の実装視点で解説【2026年時点】も参考になります。
SLIの選び方で失敗しやすい場面と生成ツールの使いどころ
避けるべきSLIの置き方
- CPU使用率やメモリ使用率をSLIにする:CPU使用率が90%でもユーザーの体験は問題ないことがあり、逆に20%でもエラーを返していることがあります。これらは原因を調べるための指標として残し、SLIには使いません。
- 平均レイテンシで定義する:前述のとおり、平均ではロングテールの遅延が隠れます。閾値を使って件数で数える形にします。
- SLIを増やしすぎる:SRE本の第4章は、指標を選びすぎると重要な指標に目が向かなくなり、少なすぎると重要な挙動を見落とすと述べています。そのうえで、代表的な指標がいくつかあれば十分だとしています。まずは可用性とレイテンシの2本から始めるのが妥当です。
- 4xxの扱いを決めずに数える:404や認可エラーの多くは、クライアントの誤りによるものです。5xxだけを失敗として数えるのか、特定の4xx(429など)も失敗に含めるのかは、SLI仕様の段階で文書にしておきます。
OpenSLO・Sloth・Pyrraの導入判断とルール管理量
SLIの定義を宣言的に書く仕様として、OpenSLOがあります。現行の apiVersion は openslo/v1 で、SLIは ratioMetric(良いイベントと全体、悪いイベントと全体、またはraw)か thresholdMetric で表します。Prometheusのルールを自動生成するツールとしては、Sloth(2026年4月4日公開のv0.16.0が最新)とPyrra(2026年6月25日公開のv0.10.1が最新)があります。Slothは slo:sli_error:ratio_rate2h のように時間窓ごとの記録ルールを生成し、Pyrraは元のメトリクス名を基にしたルール名を生成します。
対象サービスが少なく、管理するSLIと時間窓も少ない場合は、手書きのルールとpromtoolによるテストから始められます。少数サービスでもルール数が多い場合や、チーム共通の仕様が必要な場合は、早い段階で生成ツールやOpenSLOを検討します。一方、サービスが増えて複数の時間窓とバーンレートのルールをサービスごとに書くようになると、手書きでは書き間違いが出やすくなります。その段階で生成ツールを導入するのが適切です。
よくある質問
SLIとは何の略で、どういう意味ですか?
Service Level Indicatorの略で、日本語ではサービスレベル指標と訳されます。成功したリクエストの比率や、一定時間内に応答できたリクエストの比率など、ユーザーから見たサービスの良し悪しを数値で表す指標です。
SLIとSLOの違いは何ですか?
SLIは実際に測った値で、SLOはそのSLIに対して置く目標値です。たとえば「成功リクエスト比率」がSLIで、「30日間で99.9%以上」がSLOです。
グラフィックボードの「SLI」とは関係がありますか?
関係ありません。グラフィックボードのSLIは、NVIDIAの複数GPU連結技術「Scalable Link Interface」の略です。NVIDIAは、RTX 20シリーズ以前のGPU向けに、2021年1月1日以降は新しいSLIドライバープロファイルを追加しないとサポート記事で告知しています。
SLIの測定はどのツールから始められますか?
すでにロードバランサーやWebサーバーのメトリクスをPrometheusで集めているなら、記録ルールを追加するだけで始められます。Google Cloud Monitoringのように、SLIをリクエスト単位と時間枠単位から選べるマネージドサービスもあります。
4xxエラーはSLIの失敗に含めるべきですか?
多くの4xxはクライアント側の誤りなので、5xxだけを失敗として数えるのが一般的です。ただし、レート制限の429のように、サービス側の都合でユーザーの操作が失敗するものは失敗に含める判断もあります。どちらにするかは、SLI仕様として文書に残しておきます。