در معماری microservice، یک درخواست کاربر ممکن است از API Gateway به ده سرویس، دو صف، یک cache و یک دیتابیس برود. وقتی latency بالا میرود یا error میآید، log خام و metric میانگین کافی نیست — باید مسیر دقیق همان درخواست را ببینید.
Jaeger برای همین ساخته شد:
open source, distributed tracing platform — Monitor and troubleshoot workflows in complex distributed systems.
یعنی متصل کردن نقطهها بین سرویسهای پراکنده: پیدا کردن bottleneck، ریشهٔ خطا، و وابستگی سرویسها — با مقیاس ابری و بدون قفل vendor.
CNCF Graduated — یکی از اولین پروژههای graduated بنیاد. خاستگاه: Uber (اهدا به CNCF). لایسنس: Apache 2.0. سایت: jaegertracing.io · Docs: docs · Repo: github.com/jaegertracing/jaeger
مشکل: بدون Trace، Blind Debugging
بدون tracing:
Service A ──?──► B ──?──► C
metric: p99 بالا — کجا؟
log: خطای timeout در C — چرا A کند بود؟
با Jaeger:
Trace ID = abc123
A (12ms) → B (80ms) → C (410ms) ← bottleneck
هر span: tags، logs، status، parent/child| معیار | فقط Log | فقط Metric | Distributed Tracing (Jaeger) |
|---|---|---|---|
| مسیر یک درخواست | سخت | نه | بله — Trace |
| Latency بین سرویسها | حدس | میانگین | per-span / waterfall |
| Dependency map | دستی | محدود | از دادهٔ واقعی |
| Root cause در cascade | زمانبر | گمکننده | هدف اصلی |
| هزینهٔ volume | بالا | متوسط | نیاز به sampling |
Tracing جایگزین log یا metric نیست — ستون سوم observability کنار آنهاست. برای log یکپارچه ببینید: Fluentd. برای mesh و proxy: Istio و Envoy.
Jaeger چیست؟
طبق جاegertracing.io و Features:
- پلتفرم distributed tracing برای مانیتور و عیبیابی workflowهای توزیعشده
- طراحیشده برای high scalability (مثلاً استقرار Uber: میلیاردها span در روز)
- Cloud Native: image کانتینر، binary، Operator و Helm برای Kubernetes
- دریافت داده با OTLP (پروتکل استاندارد OpenTelemetry) بهعلاوه پروتکلهای legacy Jaeger و Zipkin
- UI مدرن (React) برای جستجوی trace، timeline، dependency graph و SPM
- Sampling سر/دم برای کنترل سربار و هزینهٔ storage
مفاهیم پایه
| مفهوم | معنی |
|---|---|
| Trace | کل مسیر یک درخواست end-to-end (گراف spanها) |
| Span | یک واحد کار (مثلاً HTTP call، DB query) با زمان شروع/پایان |
| Span context | trace_id، span_id، flags — در headerها propagate میشود |
| Tags / Attributes | متادیتای کلید-مقدار (http.status_code, db.statement, …) |
| Baggage | دادهٔ contextual که همراه درخواست بین سرویسها سفر میکند |
| Sampling | تصمیم اینکه کدام trace ذخیره شود (کاهش هزینه و سربار) |
مدل داده در UI همچنان نزدیک OpenTracing است (DAG با span references، نه فقط درخت ساده)، در حالی که ingestion مدرن روی OTLP متمرکز است.
تاریخچهٔ کوتاه: از OpenTracing تا Jaeger v2
| دوره | تحول |
|---|---|
| Uber | Jaeger برای scale داخلی؛ بعد اهدا به CNCF |
| OpenTracing | استاندارد instrumentation اولیه که Jaeger روی آن شکل گرفت |
| OpenTelemetry | ادغام OpenTracing + OpenCensus؛ SDK و پروتکل واحد |
| OTLP در Jaeger | از حدود v1.35 دریافت بومی OTLP |
| Jaeger v2 | بازسازی روی OpenTelemetry Collector — یک binary، نقشهای مختلف، YAML pipeline |
| v2.18+ | پشتیبانی native ClickHouse بهعنوان storage (alpha) |
پیام جامعه امروز: instrument کنید با OpenTelemetry SDK؛ backend میتواند Jaeger باشد. exporterهای بومی Jaeger در SDKها بهتدریج به نفع OTLP کنار میروند.
معماری Jaeger v2
Jaeger v2 یک binary انعطافپذیر است که با config به نقشهای مختلف درمیآید:
| نقش | کار |
|---|---|
| collector | دریافت trace از appها و نوشتن به storage |
| query | API + UI برای جستجو و نمایش |
| ingester | خواندن از Kafka و نوشتن به storage |
| all-in-one | collector + query در یک process |
| agent | sidecar/host forwarder — توصیهٔ رسمی: بهجای آن از OpenTelemetry Collector استفاده کنید |
Apps (OTel SDK / Zipkin / legacy Jaeger)
│ OTLP :4317/:4318 (یا Zipkin :9411)
▼
┌───────────────────┐ اختیاری ┌─────────────┐
│ Jaeger collector │ ───────────────► │ Kafka │
│ (+ processors) │ └──────┬──────┘
└─────────┬─────────┘ │
│ direct ▼
│ ┌─────────────┐
▼ │ ingester │
┌───────────────────┐ └──────┬──────┘
│ Storage backend │ ◄─────────────────────┘
│ ES / Cassandra / │
│ OpenSearch / │
│ ClickHouse / │
│ Badger / memory │
└─────────┬─────────┘
▼
┌───────────────────┐
│ query + Jaeger UI │ :16686
└───────────────────┘دو الگوی استقرار مقیاسپذیر
- Direct-to-storage — collector مستقیم به DB مینویسد. ساده؛ storage باید peak را تحمل کند.
- Via Kafka — collector به Kafka export میکند؛ ingester میخواند و به storage مینویسد. بافر پایدار در برابر spike و outage کوتاه storage.
all-in-one چه وقت؟
| حالت | مناسب |
|---|---|
| all-in-one + in-memory | dev / demo — داده با restart از بین میرود |
| all-in-one + Badger | production کوچک، تکنود — بدون scale افقی |
| collector / query جدا + storage خارجی | production واقعی — scale جدا برای write و read |
جزئیات: Architecture.
Jaeger روی OpenTelemetry Collector
Jaeger v2 عملاً یک توزیع سفارشی از OpenTelemetry Collector است با:
- کامپوننتهای upstream (OTLP receiver، batch، attributes، …)
- contrib (Kafka، tail sampling، …)
- کامپوننتهای خود Jaeger: Storage Extension/Exporter، Query Extension، Adaptive Sampling، Remote Sampling
میتوانید با OpenTelemetry Collector Builder (ocb) توزیع سفارشی بسازید.
Receivers مهم
| Receiver | کاربرد |
|---|---|
| OTLP | مسیر پیشنهادی امروز |
| Jaeger | gRPC / Thrift legacy |
| Zipkin | سازگاری با instrumentation قدیمی |
| Kafka | ingest از صف |
| No-op | فقط query/UI بدون pipeline ورودی |
Processors و قابلیتهای pipeline
- Batch — کارایی نوشتن
- Memory Limiter — back-pressure زیر فشار
- Attributes / Filter — غنیسازی، redact دادهٔ حساس، کاهش volume (Filter میتواند trace را بشکند — با احتیاط)
- Tail Sampling — تصمیم بعد از دیدن کل trace (مثلاً نگه داشتن فقط errorها)
OTel Collector جلوتر از Jaeger؟
اجباری نیست — خود Jaeger همان نقش collector را دارد. اگر قبلاً OTel Collector برای metrics/logs دارید، میتواند sidecar، DaemonSet یا remote cluster جلوی Jaeger باشد برای enrichment (نام Pod، namespace) یا sharding / tail sampling متمرکز.
Storage backends
| Backend | وضعیت معمول | نکته |
|---|---|---|
| Elasticsearch 7/8 / OpenSearch | رایج در بسیاری از تیمها | جستجوی غنی؛ هزینه و index |
| Cassandra 4.0+ | مقیاس write بالا | عملیات کلاستر سنگینتر |
| ClickHouse | از v2.18 بومی (alpha) | columnar، فشردهسازی عالی، analytics |
| Badger | embedded | تکنود، حجم متوسط |
| In-memory | تست | بدون دوام |
| Remote Storage API | افزونه | backendهای certified |
چرا ClickHouse مهم شد؟
حجم span نیمهساختیافته بالاست؛ نیاز به جستجو روی service، operation، tag، duration و trace ID دارید. گزارشهای جامعه (از جمله CNCF blog و پست Introducing Native ClickHouse Support):
- ingestion بالای ۵۰k spans/sec در بنچمارک تکنود
- فشردهسازی حدود ۸.۶× روی جدول spans
- بازیابی trace حدود ~۱۰۰ ms؛ بسیاری از searchها زیر ۵۰ ms
اسکیما برای مدل OTel در v2 بازطراحی شده: جدول spans با ستونهای Nested، مرتبسازی برای search، Bloom filter روی trace_id، و materialized view برای بهینهسازی FindTraceIDs.
Sampling: کنترل هزینه و سربار
بدون sampling، هر درخواست = هزینهٔ storage و CPU روی مسیر hot.
| نوع | کی تصمیم میگیرد؟ | کاربرد |
|---|---|---|
| Head-based (static) | ابتدای trace، درصد ثابت | ساده و قابل پیشبینی |
| Head-based (adaptive / remote) | سرویس مرکزی احتمال را تنظیم میکند | تعادل coverage و هزینه |
| Tail-based | بعد از کامل شدن trace | نگه داشتن error / slow traces |
Remote Sampling از طریق extension در Jaeger (و سازگاری با OTel Collector) سرو میشود. جزئیات در Sampling docs.
UI، Dependency Graph و SPM
Jaeger UI (:16686)
- جستجو بر اساس service، operation، tags، مدت، بازهٔ زمانی
- waterfall / timeline برای دهها هزار span (بهبودهای v1.0+؛ آزمایش با ~۸۰٬۰۰۰ span گزارش شده)
- contextual logs روی span
دو نوع گراف وابستگی
| نوع | معنی |
|---|---|
| System Architecture | وابستگی یکگام (A–B، B–C)؛ مثل دید mesh — لزوماً زنجیرهٔ کامل A–B–C در یک trace نیست |
| Deep Dependency (Transitive) | با focal service؛ زنجیرهٔ تراگذاری A→B→C؛ granularity سرویس یا endpoint |
System Architecture میتواند از memory ساخته شود یا با jobهای Spark/Flink روی storage توزیعشده.
Service Performance Monitoring (SPM)
از spanها metricهای تجمیعی (latency، error rate، throughput) میسازد و بهصورت time series نشان میدهد — پلی بین tracing و «مانیتورینگ عملکرد سرویس» بدون اینکه جایگزین Prometheus کامل شود. اجزای backend معمولاً Prometheus metrics و log ساختیافته (zap) هم expose میکنند.
سازگاری با Zipkin
اگر instrumentation قدیمی Zipkin دارید، لازم نیست همه را یکشبه عوض کنید. Jaeger spanهای Zipkin (Thrift، JSON v1/v2، Protobuf روی HTTP، پورت رایج :9411) را میپذیرد. مسیر پیشنهادی بلندمدت: مهاجرت به OpenTelemetry و OTLP.
شروع سریع
all-in-one با Docker
طبق Getting Started (نسخه را با آخرین release عوض کنید):
docker run --rm --name jaeger \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 5778:5778 \
-p 9411:9411 \
cr.jaegertracing.io/jaegertracing/jaeger:2.20.0- UI:
http://localhost:16686 - OTLP gRPC:
4317· OTLP HTTP:4318 - Zipkin:
9411· Remote sampling:5778
با config سفارشی:
docker run --rm --name jaeger \
-p 16686:16686 -p 4317:4317 -p 4318:4318 \
-v /path/to/config.yaml:/jaeger/config.yaml \
cr.jaegertracing.io/jaegertracing/jaeger:2.20.0 \
--config /jaeger/config.yamlHotROD — دموی رسمی
HotROD (Rides on Demand) چند microservice دارد و برای یادگیری latency، concurrency، baggage و instrumentation OTel عالی است:
export JAEGER_VERSION=2.20.0 # آخرین نسخهٔ پایدار
git clone https://github.com/jaegertracing/jaeger.git jaeger
cd jaeger/examples/hotrod
docker compose upApp: http://localhost:8080 · Jaeger UI معمولاً کنار همان compose بالا میآید.
ارسال span با OTLP (مفهومی)
# مثال مفهومی — endpoint OTLP HTTP به all-in-one
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_SERVICE_NAME=checkout-api
# سپس اپ را با OpenTelemetry SDK / auto-instrumentation اجرا کنیددر Kubernetes معمولاً:
- Operator یا Helm chart Jaeger
- Instrumentation با OTel Operator / sidecars / SDK
- Service mesh (Istio، Linkerd) برای spanهای شبکه بدون تغییر همهٔ کد
مقایسه: Jaeger در برابر گزینههای رایج
| معیار | Jaeger | Zipkin | Grafana Tempo | APM تجاری |
|---|---|---|---|---|
| مدل | tracing backend + UI غنی | سبکتر، legacy رایج | object store، Grafana-centric | کامل + قفل |
| OTLP / OTel | مرکز v2 | محدودتر | قوی | وابسته |
| جستجوی مستقل | قوی (با ES/CH) | متوسط | بیشتر با TraceQL/Grafana | قوی |
| هزینه در مقیاس | وابسته به storage | کمتر ویژگی | اغلب ارزانتر در حجم | گران |
| CNCF | Graduated | — | — | — |
| SPM / dependency | بله | محدود | از طریق Grafana | بله |
انتخاب سریع:
- میخواهید UI و جستجوی standalone قوی + CNCF → Jaeger
- قبلاً همه چیز داخل Grafana stack و object storage ارزان → Tempo را هم ارزیابی کنید
- فقط migration کوتاه از Zipkin → Jaeger بهعنوان drop-in backend خوب است
عملیات روزمره
| کار | اقدام |
|---|---|
| سلامت backend | metrics Prometheus روی اجزا؛ health extension |
| دادهای در UI نیست | sampling، endpoint OTLP، clock skew، retention storage |
| فشار write | Kafka buffer، scale collector، batch processor |
| PII در span | Attributes processor برای redact قبل از storage |
| حجم بالا | adaptive / tail sampling؛ retention و ILM روی ES یا TTL روی ClickHouse |
| امنسازی UI | جدا کردن query از collector؛ auth در Ingress / mesh |
برای شبکه و observability مبتنی بر eBPF کنار tracing: Cilium. برای runtime security: Falco.
یکپارچگی با استک P30Light
| لایه | مقالهٔ مرتبط |
|---|---|
| Service mesh | Istio · Linkerd |
| Data plane | Envoy · Contour |
| Logs | Fluentd |
| GitOps استقرار | Flux · Helm |
| رویداد | CloudEvents |
| App runtime | Dapr |
الگوی رایج production:
Apps / Mesh ──OTLP──► OTel Collector (enrich) ──► Jaeger collector
└──► (اختیاری) metrics/logs backends
Jaeger storage ◄── collector / Kafka+ingester
UI / SPM ◄── queryخلاصه
| موضوع | جمعبندی |
|---|---|
| چیست | پلتفرم distributed tracing open source (CNCF Graduated) |
| v2 | مبتنی بر OpenTelemetry Collector؛ نقشهای collector/query/… |
| ورود داده | OTLP اول؛ Zipkin و Jaeger legacy پشتیبانی میشوند |
| Storage | ES/OpenSearch، Cassandra، Badger، ClickHouse (native از 2.18) |
| UI | جستجوی trace، waterfall، dependency، SPM |
| Scale | بدون SPOF؛ Kafka برای بافر؛ میلیاردها span/روز در مقیاس Uber |
| Instrument | OpenTelemetry SDK توصیهٔ رسمی |
قدم بعدی
- all-in-one را با Docker بالا بیاورید و UI را روی
:16686باز کنید. - HotROD را با
docker composeاجرا کنید و یک latency cascade را در waterfall ببینید. - یک سرویس واقعی را با OTel SDK به
4317/4318وصل کنید. - برای staging، collector/query جدا + Elasticsearch یا ClickHouse انتخاب کنید.
- sampling (adaptive یا tail) را قبل از production کامل روشن کنید.
- با mesh یا Fluentd، سه ستون metrics / logs / traces را همتراز کنید.
منابع
- Jaeger — سایت رسمی
- Architecture
- Features
- Getting Started
- Sampling
- GitHub — jaegertracing/jaeger
- Native ClickHouse support (blog)
- CNCF — ClickHouse backend benchmarks
- OpenTelemetry
منتشر شده در P30Light — بخش زیرساخت و سرور