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 全部整合——建立一個完整的可觀測性平台。