Distributed Tracing بـ OpenTelemetry: خريطة الطلب من أوله لآخره
لو عندك 4 أو 5 microservices، وطلب واحد من الـ frontend بياخد 2800ms بدل 200ms، ومفيش طريقة تعرف بالظبط أنهي service هو السبب — المقال ده هيوفّرلك أسبوع كامل من التخمين. Distributed Tracing بـ OpenTelemetry بيديك خريطة دقيقة للطلب من لحظة دخوله لحد رجوع الرد، ومعاه زمن كل خطوة.
المشكلة باختصار
في monolith، لو طلب بطيء، بتفتح APM واحد وبتشوف أنهي function بتستهلك الوقت. في microservices، الطلب الواحد بيعدّي على auth-service ثم orders-service ثم payment-service ثم notifications-service. logs كل service موجودة في مكان مختلف، ومفيش حاجة تربطهم. بتقعد ساعتين بتدوّر في kibana و request-id يدوي علشان تعرف إن البطء في استعلام واحد في payment-service بياخد 1600ms.
Distributed Tracing بيحل المشكلة دي جذريًا: كل طلب بياخد trace_id واحد بيتنقل مع الهيدر بين كل الـ services، وكل عملية جوّا service بتتسجل كـ span تحت نفس الـ trace. النتيجة: شجرة كاملة بتوريك مين استنى مين.
المفهوم بمثال بسيط قبل أي كود
تخيّل شركة توصيل طلبات. العميل طلب أوردر في 9:00 صباحًا. الأوردر عدّى على 4 موظفين: استقبال، محاسبة، مخزن، ثم سائق. العميل استلم الأوردر 9:45. أنت كمدير عايز تعرف مين فيهم أخد وقت. لو كل موظف كتب في كراسته وقت استلامه ووقت تسليمه، تقدر تطلع جدول زي ده:
- الاستقبال: 9:00 → 9:05 (5 دقائق)
- المحاسبة: 9:05 → 9:08 (3 دقائق)
- المخزن: 9:08 → 9:35 (27 دقيقة) ← هنا المشكلة
- السائق: 9:35 → 9:45 (10 دقائق)
دلوقني عرفت إن المخزن هو المشكلة، من غير ما تقف على كل موظف وتسأله. ده بالظبط اللي Distributed Tracing بيعمله: كل "موظف" هو service، كل "كراسة" هي span، ورقم الأوردر المشترك هو trace_id.
المصطلحات العلمية بدقة
بعد ما فهمت المثال، دي التعريفات الرسمية من وثائق OpenTelemetry:
- Trace: تمثيل لرحلة طلب واحد عبر النظام بالكامل. كل trace ليه
trace_idفريد بـ 128 bit. - Span: عملية واحدة لها اسم، وقت بداية، وقت نهاية، وattributes. الـ span ممكن يكون له parent span ومنها بنبني الشجرة.
- Context Propagation: آلية نقل الـ trace_id و span_id بين الـ services. المعيار الرسمي هو W3C Trace Context، وبيتبعث في هيدر اسمه
traceparent. - Instrumentation: الكود اللي بيولّد الـ spans. ممكن يكون auto-instrumentation (بيشتغل من غير ما تعدّل كودك) أو manual (بتكتب spans مخصوصة).
- Exporter: المكوّن اللي بيبعت الـ spans لمكان تخزين (Jaeger, Tempo, Datadog, Honeycomb...).
إعداد Node.js في 3 دقائق (auto-instrumentation)
أسرع طريقة تبدأ بيها هي الـ auto-instrumentation. في Node.js، الحزمة بتـ patch تلقائيًا مكتبات زي Express و http و pg و ioredis، وبتولّد spans من غير ما تعدّل سطر في الكود الأساسي.