ストーリー
ミッション概要
| ミッション | テーマ | 目安時間 |
|---|---|---|
| Mission 1 | OpenTelemetry計装設計 | 15分 |
| Mission 2 | メトリクス設計とPromQLクエリ | 15分 |
| Mission 3 | 分散トレーシングの設計 | 15分 |
| Mission 4 | 統合ダッシュボードの設計 | 15分 |
前提条件
system: "OrderFlow - 注文処理システム"
services:
- name: "order-api"
tech: "Node.js + Express"
role: "注文の受付・管理"
- name: "inventory-service"
tech: "Node.js + Fastify"
role: "在庫管理・引当"
- name: "payment-service"
tech: "Node.js + Express"
role: "決済処理"
- name: "notification-service"
tech: "Node.js + Express"
role: "メール・SMS通知"
infrastructure:
- PostgreSQL (orders DB)
- PostgreSQL (inventory DB)
- Redis (caching)
- RabbitMQ (messaging)
request_flow:
"order-api → inventory-service → payment-service → notification-service"
Mission 1: OpenTelemetry計装設計(15分)
要件
OrderFlowシステムの各サービスに対するOpenTelemetry計装を設計してください。 以下を含めること:
- 共通の計装設定(全サービス共通)
- サービス固有のカスタムSpan設計(各サービス最低2つ)
- Span属性(Attributes)の設計
- Context Propagation戦略(同期呼び出しとメッセージキュー)
解答例
1. 共通計装設定:
// shared/telemetry.ts
const sdk = new NodeSDK({
resource: new Resource({
'service.name': process.env.SERVICE_NAME,
'service.version': process.env.APP_VERSION,
'deployment.environment': process.env.NODE_ENV,
}),
traceExporter: new OTLPTraceExporter({ url: 'http://otel-collector:4318/v1/traces' }),
instrumentations: [
getNodeAutoInstrumentations(), // HTTP, Express, pg, amqplib自動計装
],
});
2. サービス固有のカスタムSpan:
| サービス | Span名 | 種類 | 主要属性 |
|---|---|---|---|
| order-api | createOrder | INTERNAL | order.id, order.total, order.items_count |
| order-api | validateOrder | INTERNAL | order.id, validation.result |
| inventory-service | reserveStock | INTERNAL | item.id, quantity, warehouse.id |
| inventory-service | checkAvailability | CLIENT | item.id, available_quantity |
| payment-service | processPayment | INTERNAL | payment.amount, payment.provider |
| payment-service | callStripeAPI | CLIENT | stripe.charge_id |
| notification-service | sendEmail | CLIENT | email.to, email.template |
| notification-service | sendSMS | CLIENT | sms.phone, sms.provider |
3. Context Propagation:
同期呼び出し: W3C Trace Context ヘッダーで自動伝搬
メッセージキュー(RabbitMQ): メッセージヘッダーにTrace Contextを注入
// RabbitMQ Producer
const headers: Record<string, string> = {};
propagation.inject(context.active(), headers);
channel.publish(exchange, routingKey, content, { headers });
// RabbitMQ Consumer
const parentContext = propagation.extract(ROOT_CONTEXT, message.properties.headers);
context.with(parentContext, () => { /* 処理 */ });
Mission 2: メトリクス設計とPromQLクエリ(15分)
要件
OrderFlowシステムのSLI/SLOに必要なPrometheusメトリクスを設計し、PromQLクエリを記述してください。
- 各サービスに必要なカスタムメトリクス(最低3つ/サービス)
- SLI計算用のRecording Rules
- 障害検知用のPromQLクエリ
解答例
1. カスタムメトリクス:
| サービス | メトリクス名 | タイプ | 説明 |
|---|---|---|---|
| order-api | order_created_total | Counter | 注文作成数 |
| order-api | order_processing_duration_seconds | Histogram | 注文処理時間 |
| order-api | order_status | Gauge | ステータス別の注文数 |
| inventory-service | stock_reserved_total | Counter | 在庫引当数 |
| inventory-service | stock_available | Gauge | 利用可能在庫数 |
| payment-service | payment_processed_total | Counter | 決済処理数(status別) |
| payment-service | payment_amount_total | Counter | 決済金額合計 |
2. Recording Rules:
groups:
- name: orderflow_sli
rules:
- record: sli:order_success_rate:5m
expr: |
sum(rate(order_created_total{status="success"}[5m]))
/
sum(rate(order_created_total[5m]))
- record: sli:order_latency_p99:5m
expr: |
histogram_quantile(0.99,
sum(rate(order_processing_duration_seconds_bucket[5m])) by (le)
)
- record: sli:payment_success_rate:5m
expr: |
sum(rate(payment_processed_total{status="success"}[5m]))
/
sum(rate(payment_processed_total[5m]))
3. 障害検知クエリ:
# 在庫引当の失敗率が5%を超えた
sum(rate(stock_reserved_total{result="failed"}[5m]))
/
sum(rate(stock_reserved_total[5m])) > 0.05
# RabbitMQキューの滞留
rabbitmq_queue_messages{queue="orders"} > 1000
# DB接続プール枯渇
pg_stat_activity_count / pg_settings_max_connections > 0.8
Mission 3: 分散トレーシングの設計(15分)
要件
注文処理フロー全体のトレーシング設計を行ってください。
- 典型的な注文フローのTrace構造(Span階層図)
- サンプリング戦略の設計
- 障害時のトレース活用シナリオ
解答例
1. Trace構造:
Trace: createOrder (order-api)
├── validateOrder (order-api) [50ms]
├── reserveStock (inventory-service) [120ms]
│ ├── checkAvailability (inventory-service) [30ms]
│ │ └── pg.query SELECT (inventory-db) [15ms]
│ └── pg.query UPDATE (inventory-db) [20ms]
├── processPayment (payment-service) [800ms]
│ ├── pg.query INSERT (orders-db) [10ms]
│ └── callStripeAPI (external) [700ms]
├── publishOrderEvent (order-api → RabbitMQ) [5ms]
└── sendNotification (notification-service) [200ms] ※非同期
├── sendEmail (external SMTP) [150ms]
└── sendSMS (external API) [100ms]
2. サンプリング戦略:
tail_based_sampling:
policies:
- name: errors
type: status_code
status_codes: [ERROR]
sample_rate: 100%
- name: slow_orders
type: latency
threshold_ms: 3000
sample_rate: 100%
- name: payment_traces
type: string_attribute
key: service.name
values: [payment-service]
sample_rate: 50%
- name: default
type: probabilistic
sample_rate: 10%
3. 障害シナリオ:
シナリオ: 決済の遅延が発生
1. アラート: payment_latency_p99 > 3s
2. Grafanaダッシュボードで確認
3. Tempoで遅いトレースを検索: duration > 3s
4. Trace詳細: callStripeAPI Spanが2.5s(通常300ms)
5. Span属性: stripe.response_code=429 (Rate Limited)
6. 根本原因: Stripe APIのレート制限に到達
7. 対策: リトライバックオフ + レート制限の緩和申請
Mission 4: 統合ダッシュボードの設計(15分)
要件
メトリクス、トレース、ログを統合した障害対応ダッシュボードを設計してください。
- ダッシュボードのパネル構成
- メトリクスからトレースへのドリルダウン方法
- トレースからログへの相関検索方法
解答例
1. パネル構成:
graph TD
subgraph Dashboard["OrderFlow 統合ダッシュボード"]
subgraph Row1["Row 1: SLO概要"]
R1A["注文成功率"]
R1B["決済成功率"]
R1C["バジェット残"]
R1D["MTTR"]
end
subgraph Row2["Row 2: リクエストフロー"]
R2A["サービス別レイテンシ<br/>(Time Series)"]
R2B["エラー率 by サービス<br/>(Time Series)"]
end
subgraph Row3["Row 3: トレース & ログ"]
R3A["遅いトレース一覧<br/>(Tempo Exemplar)"]
R3B["最新エラーログ<br/>(Loki Stream)"]
end
subgraph Row4["Row 4: インフラ"]
R4A["DB接続数"]
R4B["RabbitMQキュー"]
R4C["Redis Hit Rate"]
end
end
classDef slo fill:#198754,stroke:#146c43,color:#fff
classDef flow fill:#0d6efd,stroke:#0a58ca,color:#fff
classDef trace fill:#f5a623,stroke:#c47d10,color:#fff
classDef infra fill:#6c757d,stroke:#495057,color:#fff
class R1A,R1B,R1C,R1D slo
class R2A,R2B flow
class R3A,R3B trace
class R4A,R4B,R4C infra
2. ドリルダウンフロー:
メトリクス(エラー率上昇を検知)
│
├─ Exemplar機能: メトリクスのグラフ上にTrace IDがプロット
│ └─ クリックでTempoのトレース詳細に遷移
│
└─ 時間範囲で絞り込み → Tempoで検索
conditions: {service="payment-service", status=error}
3. トレース→ログ相関:
トレース詳細画面で Trace ID をコピー
│
└─ GrafanaのExplore画面 → Lokiデータソース
クエリ: {service=~".*"} | json | traceId = "<copied_trace_id>"
→ 全サービスの関連ログを時系列で表示
達成度チェック
| ミッション | テーマ | 完了 |
|---|---|---|
| Mission 1 | OpenTelemetry計装設計 | |
| Mission 2 | メトリクス設計とPromQL | |
| Mission 3 | 分散トレーシング設計 | |
| Mission 4 | 統合ダッシュボード設計 |
まとめ
| ポイント | 内容 |
|---|---|
| 計装設計 | 共通設定 + サービス固有のカスタムSpan |
| メトリクス | SLI計算用のRecording Rules + 障害検知クエリ |
| トレーシング | Tail-basedサンプリングでエラー・遅延を確実に記録 |
| 統合ダッシュボード | Exemplarでメトリクス→トレース→ログのドリルダウン |
チェックリスト
- マイクロサービスのOpenTelemetry計装を設計できた
- SLI用のRecording RulesとPromQLクエリを記述できた
- サンプリング戦略を設計できた
- 3本柱を統合したダッシュボードを設計できた
次のステップへ
次は理解度チェッククイズです。Step 3で学んだオブザーバビリティ基盤の理解度を確認しましょう。
推定読了時間: 60分