Chuyển đến nội dung chính

レッスン 26: フルスタックの可観測性 — ログ、メトリクス、トレース

可観測性の 3 つの柱: ログ、メトリクス、トレース。 Node.js/React の OpenTelemetry セットアップ。分散トレーシング: マイクロ フロントエンドから API ゲートウェイを介してマイクロサービスへのリクエストをトレースします。グラファナ スタック: ロキ、プロメテウス、テンポ。

🏗️ 建築 — レッスン 26 レッスン 26: フルスタックの可観測性 — ログ、 メトリクスとトレース

マイクロサービスとマイクロ フロントエンドのシステム設計 — 基本から運用まで

パート 9: 可観測性と実稼働の準備状況

xdev.asia

はじめに

分散アーキテクチャでは、デバッグは次のことに相当します。 console.log 実現不可能です。リクエストが 5 つのサービスを経由する場合、リクエストがどこに送信されるか、どれくらいの時間がかかるか、どこで失敗するかを知るには可観測性が必要です。

可観測性の 3 つの柱 — ログ、メトリクス、トレース


1. 可観測性の 3 つの柱

┌─────────────────────────────────────────────┐
│              Observability                  │
├──────────────┬──────────────┬───────────────┤
│    Logs      │   Metrics    │   Traces      │
│              │              │               │
│ What happened│ How system   │ Request flow  │
│ (events)     │ performs     │ across svcs   │
│              │ (numbers)    │ (journey)     │
│              │              │               │
│ Loki/ELK     │ Prometheus   │ Tempo/Jaeger  │
└──────────────┴──────────────┴───────────────┘

2. 分散トレーシング

2.1 エンドツーエンドのリクエストをトレースする

User clicks "Place Order" trên frontend:

Trace ID: abc-123-def
├── Span 1: Shell App → POST /api/orders (200ms)
│   ├── Span 2: API Gateway → route to Order Service (5ms)
│   │   ├── Span 3: Order Service → validate (10ms)
│   │   ├── Span 4: Order Service → call Product Service (50ms)
│   │   │   └── Span 5: Product Service → DB query (15ms)
│   │   ├── Span 6: Order Service → call Payment Service (100ms)
│   │   │   └── Span 7: Payment Service → Stripe API (80ms)
│   │   └── Span 8: Order Service → publish OrderPlaced event (5ms)
│   └── Span 9: API Gateway → response (5ms)
└── Total: 200ms

→ Bottleneck: Payment Service → Stripe API (80ms) = 40% total

2.2 OpenTelemetry のセットアップ (Node.js)

// tracing.js - Setup OpenTelemetry
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'http://otel-collector:4318/v1/traces',
  }),
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-http': { enabled: true },
      '@opentelemetry/instrumentation-express': { enabled: true },
      '@opentelemetry/instrumentation-pg': { enabled: true },
    }),
  ],
  serviceName: 'product-service',
});

sdk.start();

3. メトリクス (プロメテウス)

3.1 主要な指標 (RED メソッド)

メトリクス何をアラートいつ
料金1 秒あたりのリクエスト突然の下落
エラーエラー率 (5xx)> 1%
期間レイテンシー (p50、p95、p99)p99 > 2秒

3.2 カスタムメトリクス

const { meter } = require('@opentelemetry/api');

const orderCounter = meter.createCounter('orders_created_total', {
  description: 'Total orders created',
});

const orderDuration = meter.createHistogram('order_processing_duration_ms', {
  description: 'Order processing time',
});

// Usage
orderCounter.add(1, { status: 'success', payment_method: 'stripe' });
orderDuration.record(duration, { service: 'order-service' });

4. 構造化ログ (Loki)

// Structured JSON logs
const logger = require('pino')({
  level: 'info',
});

app.use((req, res, next) => {
  const traceId = req.headers['x-trace-id'] || generateTraceId();
  req.log = logger.child({
    traceId,
    service: 'product-service',
    requestId: req.id,
  });
  next();
});

// Usage
req.log.info({ productId: '123', action: 'getProduct' }, 'Product fetched');
req.log.error({ error: err.message, stack: err.stack }, 'Product not found');

5. グラファナ スタック

┌──────────────────────────────────────────┐
│              Grafana UI                  │
│  Dashboards │ Alerts │ Explore │ Traces  │
├──────────┬──────────┬────────────────────┤
│  Loki    │Prometheus│     Tempo          │
│  (Logs)  │(Metrics) │    (Traces)        │
├──────────┴──────────┴────────────────────┤
│         OpenTelemetry Collector          │
│  Receives → Processes → Exports          │
├──────────────────────────────────────────┤
│         Applications                     │
│  Microservices → OTLP → Collector        │
│  MFE → Web Vitals → Collector            │
└──────────────────────────────────────────┘

6. フロントエンドの可観測性 (マイクロフロントエンド)

// Web Vitals tracking
import { onLCP, onFID, onCLS } from 'web-vitals';

onLCP((metric) => {
  sendToCollector('web_vitals_lcp', metric.value, {
    mfe: 'product-mfe',
    page: window.location.pathname,
  });
});

// Error tracking
window.addEventListener('error', (event) => {
  sendToCollector('frontend_error', {
    message: event.message,
    stack: event.error?.stack,
    mfe: detectMFE(event.filename),
  });
});

概要

柱ツール目的
ログロキ+ピノ何が起こったのか (構造化された JSON)
メトリクスプロメテウスシステムの動作方法 (RED メソッド)
痕跡テンポ + OTELサービス間のリクエスト フロー
フロントエンドウェブバイタルMFE ごとのコア Web バイタル
ダッシュボードグラファナ統合された視覚化

次の記事: レッスン 27: パフォーマンスの最適化 — フロントエンドとバックエンド