OpenTelemetry: المعيار الموحد
OpenTelemetry: المعيار الموحد
قبل عام 2019، كان كل مزود لخدمات المراقبة يشحن عميله الخاص، ومجموعة أدواته البرمجية الخاصة، وبروتوكول نقل بياناته الخاص. كان دمج أدوات المراقبة في تطبيق ما يعني اختيار مزود بعينه مسبقاً وتضمين ذلك الاختيار في شيفرتك البرمجية. أي تغيير لاحق كان يستلزم اقتلاع آلاف الأسطر من استدعاءات أدوات المراقبة. جاء OpenTelemetry (اختصاراً OTel) ليكسر هذا القيد مرة واحدة وإلى الأبد.
ما هو OpenTelemetry فعلياً؟
OpenTelemetry هو معيار مفتوح ومُدرج تحت مظلة CNCF ومجموعة من المكتبات لتوليد بيانات المراقبة وجمعها وتصديرها: التتبع والمقاييس والسجلات. وهو محايد تجاه المزودين بحكم تصميمه. تُعِد الأدوات مرة واحدة، ثم توجّه البيانات إلى أي خلفية تشاء — Jaeger أو Datadog أو Honeycomb أو Grafana Tempo أو AWS X-Ray — بتغيير سطر إعداد واحد فقط، دون المساس بشيفرة تطبيقك.
يُعرِّف OTel ثلاث طبقات متمايزة:
- API — واجهات برمجية لكل لغة لإنشاء الامتدادات (Spans) وتسجيل المقاييس وإصدار سجلات. الـ API خفيف ومتعمَّد. يمكن استدعاؤه من كود المكتبات حتى لو لم يكن هناك SDK (تصبح الاستدعاءات بلا تأثير). هذا ما تُوثِّقه المكتبات مفتوحة المصدر.
- SDK — التنفيذ الفعلي للـ API. يتولى الـ SDK قرارات أخذ العينات (Sampling) وخطوط المعالجة والمُصدِّرين (Exporters). يُعِد مالكو التطبيقات الـ SDK ويزودونه عند بدء التشغيل؛ ولا يتعامل معه مؤلفو المكتبات قط.
- OTLP (بروتوكول OpenTelemetry) — بروتوكول النقل. gRPC (المنفذ 4317) أو HTTP/protobuf (المنفذ 4318). بات OTLP اليوم لغة المراقبة المشتركة: كل خلفية جدية تدعمه بشكل أصلي. استخدام OTLP يعني أنك لم تعد مرتبطاً بنموذج JSON الخاص بـ Zipkin أو صيغة Thrift الخاصة بـ Jaeger.
بنية OTel في لمحة
الحياد تجاه المزودين في الواقع العملي
الفائدة الملموسة: مع OTel يمكنك توجيه بيانات التتبع ذاتها إلى Jaeger (مستضاف ذاتياً ومجاني) لفريق مناوبتك، وفي الوقت نفسه إلى Honeycomb أو Datadog لمنصة SRE الخاصة بك — دون المساس بتطبيقك البتة. يجعل نموذج خط المعالجة في Collector هذا مجرد تغيير في الإعداد، لا تغييراً في الكود.
في Google وUber وغيرهما من المشغّلين الكبار، يكون الإعداد الإنتاجي المعتاد كالتالي:
- تُصدِر التطبيقات OTLP إلى Collector جانبي (sidecar) محلي أو DaemonSet (وليس مباشرةً إلى الخلفية — فأي انقطاع في الشبكة داخل عملية التطبيق سيُضيِّع الامتدادات).
- يُطبِّق Collector أخذ عينات قائم على الذيل (tail-based sampling)، ويُثري الامتدادات ببيانات تعريف Kubernetes، ويوزعها على عدة خلفيات.
- تستطيع الفرق تبديل الخلفيات أو إضافة خلفيات جديدة دون نشر أي تحديث للتطبيق.
التعليم التلقائي مقابل التعليم اليدوي
يوفر OTel تعليماً تلقائياً (auto-instrumentation) لمعظم الأطر الكبرى: يُعالج عميل Java إطار Spring Boot واتصالات JDBC وgRPC وعملاء HTTP عبر حقن البايت كود عند بدء تشغيل JVM. تلتف أداة opentelemetry-instrument في Python على Django/FastAPI/SQLAlchemy تلقائياً. يستخدم Node.js حزمة @opentelemetry/auto-instrumentations-node. تحصل على امتدادات لكل طلب وارد واتصال HTTP صادر واستعلام قاعدة بيانات دون أي تغيير في الكود.
يُحجز التعليم اليدوي — باستخدام OTel API مباشرةً — للامتدادات على مستوى الأعمال: "معالجة الدفعة" و"تقييم درجة المخاطر" و"تصيير خلاصة التوصيات". هذه هي الامتدادات التي تشرح فعلاً لماذا حدث التأخر، لا مجرد أن استدعاء HTTP كان بطيئاً.
order.process لا OrderService.processOrder).
إعداد OTel SDK باختصار (Python)
يوضح ما يلي كيفية إعداد الـ SDK مع مُصدِّر OTLP — هذا ما يُشغَّل عند بدء التطبيق، في خطاف تهيئة الإطار أو في وحدة tracing.py مخصصة:
لاحظ الـ resource: كل امتداد يُصدره هذا الـ SDK يحمل service.name وservice.version وdeployment.environment. هذه اتفاقيات دلالية (Semantic Conventions) من OTel — أسماء سمات موحدة تستخدمها الخلفيات لتجميع آثار التتبع وتصفيتها. الاتساق عبر أسطولك من الخدمات أمر بالغ الأهمية: إذا ابتكر خمسة فرق مفاتيح خاصة بهم لأسماء الخدمات، لن تستطيع أي خلفية ربطها ببعض.
OTLP: بروتوكول النقل
OTLP بروتوكول معرَّف بـ Protocol Buffers يعمل فوق gRPC أو HTTP. نقل gRPC (المنفذ 4317) هو المفضل لأحمال العمل الإنتاجية ذات الحجم الكبير: يُعدِّد الطلبات عبر اتصال TCP واحد، ويُطبِّق الضغط الخلفي، ويضغط البيانات بكفاءة. أما نقل HTTP (المنفذ 4318) فيفيد حين يكون gRPC محجوباً بالوكلاء أو عند الإرسال من المتصفح.
تفصيل تشغيلي مهم: تُجمِّع مُصدِّرات OTLP الامتدادات افتراضياً. يُخزِّن BatchSpanProcessor الامتدادات في الذاكرة ويُفرِّغها وفق جدول زمني (افتراضياً: كل 5 ثوانٍ، بحد أقصى 512 امتداداً للدفعة الواحدة). وهذا يعني:
BatchSpanProcessor ستُفقد. استدعِ دائماً provider.shutdown() في معالج SIGTERM الخاص بك، واضبط max_export_batch_size بتحفظ. Collector الجانبي يُخفف من هذه المخاطرة — الامتدادات في بفر Collector تنجو من إعادة تشغيل Pod التطبيق.
الاتفاقيات الدلالية
يُوفر OTel سجلاً من أسماء السمات الموحدة لـ HTTP وقواعد البيانات والرسائل وRPC وغيرها. هذه ليست اقتراحات — إنها المفردات المشتركة التي تجعل آثار التتبع عبر الفرق واللغات مقروءةً في أي خلفية. أمثلة:
http.methodوhttp.status_codeوhttp.url— امتدادات HTTPdb.systemوdb.statementوdb.name— امتدادات قواعد البياناتmessaging.systemوmessaging.destination— امتدادات Kafka/RabbitMQrpc.systemوrpc.serviceوrpc.method— امتدادات gRPC
اعتماد الاتفاقيات منذ البداية يعني أن لوحات Grafana وقواعد التنبيه ستعمل لخدمات كل فريق دون تخصيص لكل فريق على حدة. تجاهلها يعني أن كل فريق سيبني مخطط سماته الخاص، وسيقضي فريق المنصة وقته في كتابة تحويلات رسم السمات (attribute-mapping transforms) في Collector — وهو دين تقني باهظ الثمن على نطاق واسع.
ضمان OpenTelemetry بسيط لكنه عميق الأثر: استثمارك في المراقبة ملكٌ لك أنت، لا لمزودك. مع تطور الخلفيات والمزودين، يظل توثيق أدواتك ثابتاً. على نطاق الشركات الكبرى — آلاف الخدمات وعشرات الفرق ونشر متعدد السحابة — هذه القابلية للنقل ليست ميزة كمالية، بل متطلب معماري أساسي.