LESSON 40分

ストーリー

高橋アーキテクト
トレースの概念はわかった。でも、生データを見ても分析しにくい

高橋アーキテクトがJaegerのUIを開いた。ウォーターフォールチャートにリクエストの流れが美しく表示されている。

高橋アーキテクト
JaegerやZipkinは、トレースデータを可視化してくれるツールだ。これを使えば、どこがボトルネックなのか一目でわかる

Jaegerとは

Jaegerは、Uber社が開発した分散トレーシングのバックエンドです。CNCFのGraduatedプロジェクトとして、広く利用されています。

┌────────────────────────────────────────┐
│              Jaeger Architecture        │
│                                        │
│  ┌──────────┐  ┌──────────┐           │
│  │ Collector │←─│  Agent   │←─ App     │
│  │          │  │(Sidecar) │           │
│  └────┬─────┘  └──────────┘           │
│       │                               │
│  ┌────▼─────┐                         │
│  │ Storage  │ (Elasticsearch/Cassandra)│
│  └────┬─────┘                         │
│       │                               │
│  ┌────▼─────┐                         │
│  │  Query   │ (API + UI)              │
│  └──────────┘                         │
└────────────────────────────────────────┘

Jaegerのセットアップ(Docker Compose)

# docker-compose.yml
version: '3.8'
services:
  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"   # UI
      - "4317:4317"     # OTLP gRPC
      - "4318:4318"     # OTLP HTTP
    environment:
      - COLLECTOR_OTLP_ENABLED=true

  app:
    build: .
    environment:
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318
      - OTEL_SERVICE_NAME=order-service
    depends_on:
      - jaeger

アプリケーション側の設定

import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { Resource } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';

const sdk = new NodeSDK({
  resource: new Resource({
    [ATTR_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || 'my-service',
  }),
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT + '/v1/traces',
  }),
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-http': { enabled: true },
      '@opentelemetry/instrumentation-express': { enabled: true },
      '@opentelemetry/instrumentation-pg': { enabled: true },
    }),
  ],
});

sdk.start();

Jaeger UIの使い方

1. トレース検索

検索条件:
  - Service: order-service
  - Operation: POST /api/orders
  - Tags: error=true(エラーのみ)
  - Min Duration: 2s(2秒以上のリクエスト)
  - Lookback: Last 1 Hour

結果:
  TraceID: abc123  | 12 Spans | 3.5s | order-service, payment-service, ...
  TraceID: def456  | 8 Spans  | 2.1s | order-service, inventory-service, ...

2. ウォーターフォールビュー

Trace: abc123 (Total: 3.5s)

order-service: POST /api/orders    ━━━━━━━━━━━━━━━━━━━━━━━━━━  3500ms

  ├─ auth-service: validateToken   ━━━  30ms

  ├─ order-service: db.query       ━━  15ms
  │   └─ attributes: { db.statement: "INSERT INTO orders..." }

  ├─ inventory-service: checkStock ━━━━━  50ms
  │   └─ inventory-service: db.query  ━━  20ms

  ├─ payment-service: charge       ━━━━━━━━━━━━━━━━━━━━━━  3200ms  ⚠️
  │   ├─ payment-service: validate  ━━  10ms
  │   └─ payment-service: stripe    ━━━━━━━━━━━━━━━━━━━━  3150ms  ⚠️
  │       └─ attributes: { http.url: "https://api.stripe.com/charges" }
  │       └─ events: [{ name: "retry", attempt: 3 }]

  └─ notification-service: send    ━━━  20ms

3. トレースの比較

Jaegerでは2つのトレースを並べて比較できます。正常なリクエストと異常なリクエストを比較することで、問題箇所を特定します。


Zipkinとの比較

項目JaegerZipkin
開発元Uber(現CNCF)Twitter
言語GoJava
ストレージElasticsearch, Cassandra, KafkaElasticsearch, MySQL, Cassandra
UI高機能(比較、DAG等)シンプルで直感的
OpenTelemetry対応ネイティブ対応エクスポーター経由
適したケース大規模、高度な分析小〜中規模、シンプルな運用

トレースデータの分析パターン

// パターン1: 遅いリクエストの特定
// Jaeger UIで Duration > 2s のトレースをフィルタ

// パターン2: エラートレースの分析
// Tags: error=true でフィルタし、エラーSpanの属性を確認

// パターン3: 特定ユーザーのリクエスト追跡
// Tags: user.id=USR-042 でフィルタ

// パターン4: サービス間の依存関係
// DAG (Directed Acyclic Graph) ビューでサービスマップを確認

// パターン5: 統計的分析
// 同じOperationのトレースを集計し、P50/P95/P99を比較

ストレージの設計

// トレースの保持期間設計
interface TraceRetention {
  hotStorage: {
    backend: 'Elasticsearch';
    retention: '7日';
    purpose: '直近のトレースを高速検索';
  };
  coldStorage: {
    backend: 'S3';
    retention: '30日';
    purpose: '過去のトレースをアーカイブ';
  };
  samplingRate: {
    errors: 1.0;      // エラーは100%保存
    slowRequests: 1.0; // 2秒以上は100%保存
    normal: 0.05;      // 通常は5%保存
  };
}

まとめ

ポイント内容
JaegerCNCFの分散トレーシングバックエンド
セットアップDocker Compose + OTel SDKで簡単に導入
UIの活用ウォーターフォール、比較、DAGビュー
ストレージホット/コールドの階層設計 + サンプリング

チェックリスト

  • Jaegerのアーキテクチャと構成を理解した
  • Docker ComposeでJaegerをセットアップできる
  • Jaeger UIでトレースを検索・分析できる
  • Jaegerのストレージと保持期間を設計できる

次のステップへ

次は「サービス依存関係の可視化」を学びます。トレースデータからサービスマップを生成し、システム全体の構造を把握する方法を見ていきましょう。


推定読了時間: 40分