OpenTelemetry 分散式追蹤

Vibe Prompt

「幫我在 FastAPI 中加上 OpenTelemetry 追蹤,將 trace 匯出到 Jaeger。」

安裝

pip install opentelemetry-distro opentelemetry-exporter-otlp

FastAPI 整合

from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

provider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://jaeger:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

app = FastAPI()
FastAPIInstrumentor.instrument_app(app)

@app.get("/api/items/{item_id}")
async def get_item(item_id: int):
    with trace.get_tracer(__name__).start_as_current_span("get_item") as span:
        span.set_attribute("item_id", item_id)
        result = await db.query("SELECT * FROM items WHERE id = ?", item_id)
        span.set_attribute("db.query", "true")
        return result

Jaeger 部署

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"

Span 結構

Trace ID: abc123def456
├── Span: /api/checkout (HTTP POST)
│   ├── Span: validate_cart (0.2ms)
│   ├── Span: process_payment (342ms) ← 瓶頸在這裡!
│   │   ├── Span: stripe.api.charge (310ms)
│   │   └── Span: db.update_order (28ms)
│   └── Span: send_email (45ms)
└──

常見使用場景

  • 找出跨服務的效能瓶頸
  • 追蹤錯誤的真實根源
  • 視覺化微服務呼叫關係

關鍵要點

  • ✅ OpenTelemetry = 統一的觀測性標準(合併 OpenTracing + OpenCensus)
  • ✅ 三大信號:Tracing(追蹤)、Metrics(指標)、Logs(日誌)
  • ✅ 架構:API → SDK → Exporter → Backend
  • ✅ 支援多種語言:Go、Java、Python、JS、.NET、Ruby、PHP
  • ✅ 廠商中立:可輸出到 Jaeger、Zipkin、Prometheus、Grafana、Datadog 等

Span 的生命週期

from opentelemetry import trace

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("process_order") as span:
    span.set_attribute("order_id", 12345)
    span.set_attribute("customer_tier", "premium")
    
    with tracer.start_as_current_span("validate_payment") as child_span:
        child_span.add_event("payment_authorized", {"amount": 99.99})
        # 模擬付款驗證...
    
    with tracer.start_as_current_span("update_inventory") as child_span:
        child_span.set_status(trace.StatusCode.OK)
    
    span.set_status(trace.StatusCode.OK)

Context Propagation(上下文傳遞)

Trace 之所以能跨服務追蹤,靠的是 HTTP Header 傳遞 Context:

# 服務 A 發出請求時自動注入
# W3C Trace-Context 標準:
traceparent: 00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01

常見錯誤

程式碼範例



分散式追蹤:請求從哪裡到哪裡?

在微服務架構中,一個請求可能經過 API Gateway → Auth Service → Order Service → Payment Service → Database。如果請求變慢,你要怎麼知道是哪個環節的問題?

分散式追蹤(Distributed Tracing)把一個請求經過的所有服務串起來——每個服務都加上 Span(時間區段),最終形成一個 Trace。

OpenTelemetry 的三大元件

| 元件 | 功能 | |:----|:----| | Tracing | 追蹤請求經過的每個服務和耗時 | | Metrics | 收集 CPU、記憶體、請求數等指標 | | Logging | 結構化日誌(跟 trace 關聯) |

下一章預告:完整監控系統

最後一章把 Prometheus、Grafana、Loki、OpenTelemetry 全部整合——建立一個完整的可觀測性平台。

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!