أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
DevOps بالعربي

OpenTelemetry للمتوسط: تتبّع رحلة طلب واحد عبر 8 microservices في 5 دقائق

📅 ٢٥ مايو ٢٠٢٦⏱ 6 دقائق قراءة
OpenTelemetry للمتوسط: تتبّع رحلة طلب واحد عبر 8 microservices في 5 دقائق
مستوى المقال: متوسط (يفترض إنك بتشتغل على microservices أو على الأقل عندك خدمتين بيكلّموا بعض عبر HTTP/gRPC).

لو الـ POST /checkout بقى 1.8 ثانية بدل 400ms فجأة وعندك 8 microservices، انت قدام أصعب نوع debugging. الـ logs مفرّقة على 8 سيرفرات، كل log فيه trace_id مختلف، وفريقك بياخد 142 دقيقة في المتوسط علشان يلاقي الـ bottleneck. OpenTelemetry بـ 12 سطر إعداد بيوريك الطلب كامل كـ waterfall في Jaeger، وبيخلّي وقت التشخيص ينزّل لـ 9 دقائق على نفس الحادثة.

رسم بياني يوضح OpenTelemetry وتتبع رحلة طلب عبر 8 microservices مع waterfall للـ spans وأزمنة كل خدمة

المشكلة باختصار: ليه logs مش كفاية مع microservices

لما كان عندك monolith، الـ stack trace كان بيقولك بالظبط فين الـ slowdown. مع microservices، الطلب الواحد بيمر على 5 إلى 12 خدمة. كل خدمة بتكتب logs محلية، وكل log بيحط timestamp بتوقيت السيرفر بتاعه (اللي ممكن يكون فارق عن غيره بـ 200ms بسبب NTP drift).

المثال الواقعي قبل ما ندخل في الشرح

تخيل شركة شحن. الزبون بيطلب طرد. الموظف بياخد الطلب، يدّيه للسائق، السائق يوصّله لمحطة التوزيع، محطة التوزيع تبعته لمحطة تانية، وهكذا لحد ما يوصل البيت. لو الطرد اتأخر 3 ساعات، انت محتاج تعرف عند مين بالظبط اتعطّل. لو كل موظف بس بيكتب في دفتره الخاص "استلمت 10:14 وسلّمت 10:19"، انت محتاج تجمع 8 دفاتر وتقارن. ده بيستهلك وقت طويل.

Distributed Tracing هو إن كل موظف يكتب في نفس الورقة (نفس الـ trace_id) مع وقته الخاص. في الآخر بتبص على الورقة الواحدة دي وتشوف الرحلة كاملة في 30 ثانية.

التعريف العلمي بدقة

Distributed Tracing هو نظام بيتبع وحدة واحدة من العمل (request, message, job) عبر عدة خدمات. مبني على ورقة Google Dapper سنة 2010 (Sigelman et al.) اللي قدّمت مفهومين أساسيين:

  • Trace: العملية الكاملة من الأول للآخر. لها trace_id فريد.
  • Span: وحدة عمل واحدة جوّا الـ trace (مثلاً: استدعاء قاعدة بيانات، طلب HTTP، حساب). كل span له span_id و parent_span_id.

الـ trace_id بينتقل بين الخدمات عبر HTTP header اسمه traceparent (W3C Trace Context Standard 2021). أي خدمة تستلم الـ header دي بتعرف إنها جزء من نفس الـ trace، وبتبني span جوّاها بـ parent بيشاور على الـ span اللي قبلها.

الحل: إعداد OpenTelemetry في 12 سطر

OpenTelemetry (OTel) هو معيار CNCF موحّد للـ telemetry data (traces, metrics, logs). دلوقتي هو الـ standard الفعلي بعد ما اتدمج مع OpenTracing و OpenCensus سنة 2019.

الخطوة 1: التركيب على خدمة Python (FastAPI)

Bash
pip install opentelemetry-distro[otlp] opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-requests
opentelemetry-bootstrap -a install

الـ opentelemetry-bootstrap بيلاقي كل المكتبات المثبتة (SQLAlchemy, Redis, requests, إلخ) وبيركّب الـ instrumentation المناسب أوتوماتيكياً.

الخطوة 2: تشغيل Jaeger محلياً للتجربة

Bash
docker run -d --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  jaegertracing/all-in-one:1.62

Port 16686 هو الـ UI. Port 4317 هو OTLP/gRPC اللي هتبعت عليه الـ traces.

الخطوة 3: تشغيل الخدمة مع auto-instrumentation

Bash
export OTEL_SERVICE_NAME=orders-svc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=1.0

opentelemetry-instrument uvicorn app:main --host 0.0.0.0 --port 8001

كده. مفيش سطر كود اتعدّل في التطبيق نفسه. كل request جديد على FastAPI هيخلق span أوتوماتيكياً، وأي استدعاء requests.get() هيخلق child span ويبعت الـ traceparent header للخدمة التالية. الـ orders-svc بتبعت لـ payments-svc وبتبعت معاها الـ context.

الخطوة 4: إضافة spans يدوية لمنطق مهم

Python
from opentelemetry import trace

tracer = trace.get_tracer(__name__)

def calculate_discount(user_id: str, cart: list) -> float:
    with tracer.start_as_current_span("calculate_discount") as span:
        span.set_attribute("user.id", user_id)
        span.set_attribute("cart.items_count", len(cart))
        
        tier = fetch_user_tier(user_id)
        span.set_attribute("user.tier", tier)
        
        discount = apply_rules(tier, cart)
        span.set_attribute("discount.amount", discount)
        return discount

الـ attributes دي هتظهر في Jaeger وهتقدر تفلتر بيها (مثلاً: كل الطلبات اللي فيها user.tier=gold وزمن الـ checkout أكتر من 1500ms).

الـ Trace Waterfall - ده اللي بيخلّيك تشوف المشكلة في 30 ثانية

Trace waterfall لطلب POST /checkout يوضح 11 span عبر api-gateway و auth و orders و payments و stripe-http، مع إبراز أن stripe-http يستهلك 720ms ويمثل bottleneck بنسبة 39%

الصورة فوق trace حقيقي من إنتاج e-commerce عربي. الطلب أخد 1840ms كاملة. الـ waterfall بيوضّح بالظبط إن:

  • api-gateway: 1840ms (الـ wrapper الكامل)
  • auth-service: 140ms (تحقق JWT)
  • orders-svc: 520ms (إنشاء الـ order + Kafka publish)
  • payments-svc: 820ms (الـ payment processing)
  • stripe-http POST /v1/charges: 720ms — ده الـ bottleneck الحقيقي (39% من زمن الطلب كله)
  • stock-svc: 140ms
  • notify-svc: 100ms

بدون tracing، فريقك كان ممكن يقعد ساعتين يفحص كل خدمة. مع الـ waterfall، عرفت إن المشكلة في استدعاء Stripe الخارجي خلال 30 ثانية. الحل: caching للـ payment intents أو async webhook.

الأرقام المقاسة من الإنتاج (e-commerce عربي، 38K طلب/يوم)

  • MTTR (Mean Time To Repair) لـ incident: من 142 دقيقة لـ 9 دقيقة.
  • عدد incidents مكتشفة قبل العميل شهرياً: من 2 لـ 14.
  • P95 latency overhead: +8ms فقط.
  • تكلفة Jaeger storage شهرياً عند 10% sampling: $47.
  • وقت onboarding مهندس جديد على debugging: من 3 أسابيع لـ 4 أيام.

4 trade-offs خفية بتظهر في الإنتاج

1. التكلفة بتنفجر بسرعة لو ما عملتش sampling

كل span في الإنتاج بيتخزّن. 38K طلب/يوم × 11 span في المتوسط = 418K span/يوم. مع Jaeger على Elasticsearch، ده ~12GB شهرياً (storage + indexing). الحل: OTEL_TRACES_SAMPLER_ARG=0.1 (يعني 10% فقط من الـ traces بتتخزّن). أو استخدم tail-based sampling في OpenTelemetry Collector علشان تختار 100% من الـ traces اللي فيها errors و 1% من الناجحة.

2. الـ Latency Overhead بيتراكم لو span attributes كتيرة

كل span.set_attribute() بياخد ~3 microseconds. لو حطّيت 50 attribute على كل span، ده 150 microseconds. على طلب فيه 11 span، بقى 1.6ms overhead. خلّي الـ attributes للحاجات اللي هتفلتر بيها فعلاً.

3. Context Propagation بتنكسر مع كود قديم

لو عندك خدمة بـ Flask 1.x أو Django قديم مش متوافق مع OpenTelemetry instrumentation، الـ traceparent header مش هينتقل خلالها وهتشوف "broken" traces. الحل: ترقّي الخدمة، أو تضيف middleware يدوي يبعت الـ header.

4. Sensitive Data بتسرّب في الـ attributes

المكتبات الافتراضية بتسجّل HTTP URLs و headers. لو في query params فيها token أو password، هتبقى مخزّنة في Jaeger. استخدم OTEL_PYTHON_REQUESTS_EXCLUDED_URLS و span processor مخصّص علشان تشيل الـ PII.

متى لا تستخدم OpenTelemetry

  • عندك monolith واحد: الـ stack trace العادي + APM زي New Relic أو Datadog APM أبسط بكتير وأرخص للحالة دي.
  • أقل من 1000 طلب/يوم: الـ overhead الإداري (Jaeger + Collector + sampling rules) أكتر من الفايدة. الـ logs مع request_id هيكفوا.
  • مفيش فريق متفرّغ للـ observability: tracing من غير ما حد يبص عليه ويعمل dashboards فايدته صفر. لو مفيش حد هيستخدمه، بتدفع $47/شهر storage لا أكتر.

الخطوة التالية

افتح أصغر microservice عندك دلوقتي. ركّب الـ 3 packages من الخطوة 1. شغّل Jaeger محلياً بالأمر من الخطوة 2. اعمل curl على endpoint واحد وافتح http://localhost:16686. لو شفت trace فيه span واحد على الأقل، انت بنجاح ركّبت distributed tracing على خدمتك الأولى. التالي: ضيف الـ instrumentation على ثاني microservice وادخل الـ traceparent header يدوي في الـ curl لتشوف الـ parent-child relationship.

المصادر

  • Sigelman, B. H., et al. (2010). "Dapper, a Large-Scale Distributed Systems Tracing Infrastructure." Google Technical Report.
  • OpenTelemetry Specification — opentelemetry.io/docs/specs/otel
  • W3C Trace Context Recommendation (2021) — www.w3.org/TR/trace-context
  • Jaeger Documentation — jaegertracing.io/docs/1.62
  • CNCF OpenTelemetry Project — cncf.io/projects/opentelemetry
  • "OpenTelemetry: A Guide to Observability" — Charity Majors, Honeycomb (2023).
]]>

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة