座学と実技で学ぶSLI/SLO設計・管理
※起動に時間がかかるため、先に実施します
Codespacesの起動には数分かかります
起動を開始したら、次の座学セクションに進んでください。Codespacesの準備が完了する頃には座学が終わっています。
開発環境の選択肢
起動完了の確認
VS Codeのような画面がブラウザ上に表示され、ターミナルが使えるようになれば準備完了です。
推奨時間: 20分
推奨時間: 30分
⚠️ 重要: この画面を閉じるとキーを再表示できません
作成したキーは必ずこの時点でコピーしてください。画面を閉じた後は再度表示することができません。閉じてしまった場合は、再度キーを作成してください。
slm-handson-frontend)して「Save and continue」スニペットから抽出する値
// スニペット内の NREUM.loader_config から抽出
NREUM.loader_config={
accountID:"9999999", // ← NEXT_PUBLIC_NEW_RELIC_ACCOUNT_ID
applicationID:"111111111", // ← NEXT_PUBLIC_NEW_RELIC_APPLICATION_ID
licenseKey:"NRBR-*****" // ← NEXT_PUBLIC_NEW_RELIC_BROWSER_KEY
}
プロジェクトルートに.envファイルを作成し、取得した値を設定:
# .envファイルを作成
cp .env.example .env
# エディタで.envファイルを開き、以下を設定
# APM用(手順1で取得)
NEW_RELIC_API_KEY=your-license-key-here
# RUM用(手順2で取得)
NEXT_PUBLIC_NEW_RELIC_BROWSER_KEY=NRBR-xxxxx
NEXT_PUBLIC_NEW_RELIC_ACCOUNT_ID=9999999
NEXT_PUBLIC_NEW_RELIC_APPLICATION_ID=111111111
⚠️ 注意
License Keyは秘密情報です。Gitにコミットしないよう注意してください(.gitignoreに.envが登録済み)
💡 RUM設定が必要な理由
RUM(Real User Monitoring)を有効にすることで、フロントエンドのページビュー、Ajax、エラー、Core Web Vitalsを計測し、APMと統合したエンドツーエンドの監視が可能になります。
Docker Composeでアプリケーション全体を起動します。
docker compose up -d --build
💡 コマンドの説明
up -d: バックグラウンドでコンテナ起動--build: イメージを再ビルドしてから起動# コンテナの起動状態を確認
docker compose ps
全てのコンテナが「Up」状態になっていることを確認してください。
GitHub Codespacesの場合
VS Codeの下部にある「PORTS」タブからアクセスします。
ローカル環境の場合
✅ 動作確認のポイント
複数回操作することで、New Relicに十分なデータが蓄積されます。いろいろな商品を閲覧・カート追加してみましょう!
アプリケーションを操作した後、New Relicでデータを確認します。
💡 Distributed Tracingで連携確認
「Distributed tracing」メニューから、フロントエンド(Browser)→ バックエンド(API)の完全なリクエストフローを可視化できます。
⏱️ データ反映までの時間
New Relicへのデータ送信には数分かかる場合があります。データが表示されない場合は、少し待ってからリロードしてください。
エラーが発生した場合は、以下のコマンドでログを確認してください。
各サービスのログを確認することで、エラーの原因を特定できます。
APIサーバーのログ確認
# APIサーバーのログを表示
docker compose logs api-server
# リアルタイムでログを追跡
docker compose logs -f api-server
# 最新100行のログを表示
docker compose logs --tail 100 api-server
フロントエンドのログ確認
# フロントエンドのログを表示
docker compose logs frontend
# リアルタイムでログを追跡
docker compose logs -f frontend
全サービスのログ確認
# 全サービスのログを表示
docker compose logs
# リアルタイムで全サービスのログを追跡
docker compose logs -f
エラーが解消しない場合は、コンテナを再起動してください。
# 全サービスを再起動
docker compose restart
# 特定のサービスのみ再起動
docker compose restart api-server
docker compose restart frontend
環境変数の変更が反映されない場合や、イメージに問題がある場合は完全に再構築します。
# 全コンテナを停止して削除
docker compose down
# イメージを再ビルドして起動
docker compose up -d --build
⚠️ よくあるエラーと対処法
docker compose psでステータスを確認し、ログで詳細を確認してください推奨時間: 30分
このセクションでは、実際のアプリケーションでSLOを設計・設定・管理する実技を体験します。
SLO設計の第一歩は、ユーザーにとって最も重要な機能フローを特定することです。
💡 ディスカッション
問: このECサイトで、最も重要なユーザージャーニーは何でしょうか?
例: 商品購入フロー(TOPページ → 商品詳細 → カート追加 → カート確認 → 決済完了)
1. TOPページ
商品一覧表示
GET /api/products
2. 商品詳細
商品情報確認
GET /api/products/{"{id}"}
3. カート追加
商品をカートに追加
POST /api/cart/items
4. カート確認
カート内容確認
GET /api/cart
5. 決済完了
注文確定
POST /api/orders
✅ 重要なポイント
このユーザージャーニーは、ECサイトにおける最も重要なコンバージョン経路です。この経路の可用性とパフォーマンスがビジネスに直結します。
ユーザージャーニーを特定したら、各ステップのSLIを設計します。
📊 成功率ベースのSLI(APM)
計算式: 成功したリクエスト数 / 全リクエスト数
対象: APIエンドポイント(バックエンド)
例: 商品詳細APIの成功率
⏱️ レスポンスタイムベースのSLI(APM)
計算式: 指定時間内に完了したリクエスト数 / 全リクエスト数
対象: APIエンドポイント(バックエンド)
例: カート追加APIのレスポンスタイム
🖼️ Core Web VitalsベースのSLI(RUM / Browser)
計算式: 基準値内のページビュー数 / 全ページビュー数
対象: フロントエンドのユーザー体験(ブラウザ側)
例: 商品一覧ページのLCP(Largest Contentful Paint)
💡 APMとの違い: APMはサーバー側の処理時間を計測しますが、RUMはブラウザ側の実際のユーザー体験(ネットワーク遅延、レンダリング時間含む)を計測します。
🎯 SLI設計の3ステップ
設計したSLIをNew Relic UIで実装しましょう。
🎯 推奨アプローチ: ユーザージャーニー全体を1つのSLOで管理
個別のエンドポイントごとではなく、購入フロー全体を1つのSLOとして設定することで、 ビジネス価値と直結した可用性を測定できます。
対象エンドポイント: 商品一覧 → 商品詳細 → カート追加 → カート確認 → 注文確定
📊 購入フロー可用性SLO(推奨)
エンティティ: slm-handson-api (APM)
SLIタイプ: Success(成功率ベース)
SLO目標: 99.9%
Time window: 28 days(推奨)
Valid events(全リクエスト):
FROM Transaction
SELECT count(*) as 'Valid'
WHERE
request.uri = '/api/products'
OR request.uri LIKE '/api/products/%'
OR request.uri = '/api/cart/items'
OR request.uri = '/api/cart'
OR request.uri = '/api/orders'
Good events(成功リクエスト):
FROM Transaction
SELECT count(*) as 'Good'
WHERE
(request.uri = '/api/products'
OR request.uri LIKE '/api/products/%'
OR request.uri = '/api/cart/items'
OR request.uri = '/api/cart'
OR request.uri = '/api/orders')
AND httpResponseCode < 500
AND error IS false
💡 このSLOの意味
⏱️ エンドポイント特性に応じた条件付き閾値
APIの特性によって許容できるレスポンスタイムは異なります。参照系(GET)は高速であるべきですが、 更新系(POST)は処理が重いため、より長い時間を許容します。 これらを1つのSLOで統合的に管理します。
| 分類 | 対象API | 閾値 |
|---|---|---|
| 参照系 | GET /api/products, GET /api/products/{id}, GET /api/cart | 300ms |
| 更新系 | POST /api/cart/items, POST /api/orders | 1000ms |
⏱️ 購入フローレイテンシSLO
エンティティ: slm-handson-api (APM)
SLIタイプ: Latency(レスポンスタイムベース)
SLO目標: 95%
Time window: 28 days(推奨)
Valid events(購入フロー全リクエスト):
FROM Transaction
SELECT count(*) as 'Valid'
WHERE
request.uri = '/api/products'
OR request.uri LIKE '/api/products/%'
OR request.uri = '/api/cart'
OR request.uri = '/api/cart/items'
OR request.uri = '/api/orders'
Good events(閾値内に完了 - 条件付き):
FROM Transaction
SELECT count(*) as 'Good'
WHERE
-- 参照系: 300ms以内
((request.uri = '/api/products'
OR request.uri LIKE '/api/products/%'
OR request.uri = '/api/cart')
AND duration < 0.3)
OR
-- 更新系: 1000ms以内
((request.uri = '/api/cart/items'
OR request.uri = '/api/orders')
AND duration < 1.0)
💡 このSLOの意味
🖼️ LCP (Largest Contentful Paint) とは
ページ内で最も大きなコンテンツ(商品画像など)が表示されるまでの時間です。 ECサイトでは商品画像の表示速度が第一印象を決め、離脱率に直結します。
Googleの推奨基準
| 評価 | LCP時間 |
|---|---|
| Good | 2.5秒以内 |
| Needs Improvement | 2.5〜4秒 |
| Poor | 4秒超 |
🖼️ フロントエンド表示速度SLO(LCP)
エンティティ: slm-handson-frontend (Browser)
SLIタイプ: Latency(Core Web Vitals - LCP)
SLO目標: 90%
Time window: 28 days(推奨)
Valid events(購入フローのページビュー):
FROM PageViewTiming
SELECT count(*) as 'Valid'
WHERE
pageUrl LIKE '%/products%'
OR pageUrl LIKE '%/cart%'
OR pageUrl LIKE '%/checkout%'
OR pageUrl RLIKE '^https?://[^/]+/?$'
※ 最後の行はTOPページ(ドメイン直下)にマッチ。localhost でも Codespaces でも動作します。
Good events(LCP 2.5秒以内):
FROM PageViewTiming
SELECT count(*) as 'Good'
WHERE
(pageUrl LIKE '%/products%'
OR pageUrl LIKE '%/cart%'
OR pageUrl LIKE '%/checkout%'
OR pageUrl RLIKE '^https?://[^/]+/?$')
AND largestContentfulPaint < 2500
💡 このSLOの意味
📋 ハンズオンで作成するSLOまとめ
| SLO名 | タイプ | 目標 | 対象 |
|---|---|---|---|
| 購入フロー可用性 | Success | 99.9% | APM: 全購入フローAPI |
| 購入フローレイテンシ | Latency | 95% | APM: 参照系 < 300ms / 更新系 < 1000ms |
| フロントエンド表示速度 | Latency (LCP) | 90% | Browser: LCP < 2.5秒 |
📝 ワークショップTips
今回は3つのSLOを作成します(APM 2つ + Browser 1つ)。実運用でも1〜3つのSLOから始めることをお勧めします。多すぎるSLOは管理が困難になり、本質的な改善活動から遠ざかる原因になります。
環境変数を変更して、意図的にパフォーマンスを劣化させ、SLO違反を体験しましょう。
⚠️ 環境変数の変更
プロジェクトルートの.envファイルを編集します。
# エラー率を30%に上昇(デフォルト: 10%)
ERROR_RATE=0.3
# 最大レスポンスタイムを2000msに増加(デフォルト: 500ms)
RESPONSE_TIME_MAX=2000
# 最小レスポンスタイムを500msに増加(デフォルト: 50ms)
RESPONSE_TIME_MIN=500
環境変数を変更したら、APIサーバーを再起動して反映させます。
# APIサーバーのみ再起動
docker compose up -d api-server
# 起動確認
docker compose ps api-server
Playwrightベースの自動ユーザージャーニー負荷生成を開始し、継続的なアクセスを生成します。
# 2段階起動でネットワークエラー回避
docker compose up -d
docker compose --profile playwright up playwright-generator
# カスタム設定での実行(短時間テスト: 5分間、10秒間隔)
DURATION=300 ACCESS_INTERVAL=10 docker compose --profile playwright up playwright-generator
💡 負荷生成スクリプトの動作
Playwrightスクリプトは、リアルなブラウザ操作を自動実行します:
✅ 体験のポイント
パフォーマンス劣化により、実際にSLOが違反される様子を観察できます。これにより、SLO管理の重要性と、リアルタイム監視の価値を体感できます。
エラーバジェットを理解し、SLO違反時のアラート設定と意思決定プロセスを学びましょう。
📊 エラーバジェットの定義
エラーバジェットとは、SLO目標値を達成するために許容される「失敗の余地」です。
計算例: SLO 99.9%の場合
エラーバジェットが枯渇する前にアラートを設定し、事前に対応できるようにします。
🤔 ディスカッション: エラーバジェットが枯渇したら?
シナリオA: 機能凍結(Feature Freeze)
シナリオB: リスクを取る
シナリオC: SLO目標の再評価
💡 SLM運用のベストプラクティス
おめでとうございます!🎉
SLOの設定が完了しました。でも、ここからが本当のスタートです。
SLOは「設定して終わり」ではなく「設定してからが本番」です。 継続的な改善と運用の中で、SLOの真価が発揮されます。
📈 SLOの継続的改善
💰 エラーバジェット活用の最適化
🔥 バーンレートアラートの設定
🏢 組織への展開
🎯 覚えておいてほしいこと
🚀 SLOの旅は始まったばかり
今日学んだことを活かして、ユーザーに価値を届け続けるサービスを目指しましょう。
SLOは、そのための強力な羅針盤になります。
ハンズオン終了後は、以下の手順でリソースを削除してください。
🗑️ GitHub Codespacesの削除
Codespacesは停止していてもストレージの無料枠を消費します。不要になったら削除しましょう。
💡 Tip: 無料枠(月間15GBストレージ・120コア時間)を節約するため、使わないCodespacesは早めに削除することをお勧めします。
🔑 New Relic API Keyの削除
ハンズオン用に作成したAPI Keyは、不要になったら削除してセキュリティリスクを軽減しましょう。
⚠️ 注意: 本番環境で使用しているキーは削除しないでください。ハンズオン用に作成したキーのみを削除します。
💡 作成したSLOについて
New Relicで作成したSLOは、そのまま残しておいても課金に影響はありません。学習のために残しておくか、不要であれば「Service levels」から削除できます。