قياس التطبيقات وتفعيل المراقبة
قياس التطبيقات وتفعيل المراقبة
لا تحدث القابلية للمراقبة تلقائياً. لا يُصدر أي عملية تشغيل أي شيء مفيد حتى يضيف المهندس عمداً كود القياس — وهو الكود الذي يولّد المقاييس والتتبعات والسجلات باعتبارها متطلباً أساسياً لا إضافةً لاحقة. في شركات مثل Google وMeta وStripe، تُعدّ أدوات القياس معياراً لجاهزية الإنتاج: لا يمكن شحن أي خدمة دون تحديد مقاييس SLI والمُصدِّرات المنظمة للسجلات وسياق التتبع المنتشر في جميع مسارات الطلبات.
يغطي هذا الدرس ثلاثة محاور متشابكة: اختيار مكتبات القياس المناسبة وتوصيلها، وتسمية إشاراتك بحيث تظل قابلة للصيانة على نطاق واسع، والتحكم في البعد الأساسي حتى لا تُفلس منصة المراقبة لديك أو تنهار تحت الحمل.
مكتبات القياس: OpenTelemetry أولاً
تقاربت الصناعة على OpenTelemetry (OTel) بوصفه المعيار المحايد من الموردين لأدوات القياس. تشحن OTel حزم SDK لـ Go وJava وPython وNode.js و.NET وRuby وRust وPHP وغيرها. وتنتج الأنواع الثلاثة من الإشارات (المقاييس والتتبعات والسجلات) من خلال واجهة API موحدة، وتُصدّر إلى أي backend — Prometheus وJaeger وTempo وDatadog وHoneycomb — عبر OTel Collector دون تعديل كود التطبيق.
قبل OTel كان عليك الاختيار: StatsD للمقاييس، وOpenTracing للتتبعات، ومكتبة سجلات مخصصة. هذا التشتت يعني أن كل فريق يبني أدواته الوسيطة الخاصة. أما OTel فيُنهي ذلك. الخيار الافتراضي الصحيح في 2025 هو:
- المقاييس — OTel SDK أو مكتبة عميل Prometheus (كلاهما جيد؛ مكتبة Prometheus أكثر رسوخاً للمقاييس الصرفة).
- التتبعات — OTel SDK مع تصدير OTLP. لا تستخدم SDK الأصلي لـ Jaeger — فهو موقوف.
- السجلات — OTel Logs SDK (لا يزال في طور النضج) أو مُسجِّل منظم (zerolog أو zap أو logrus) يُصدر JSON عبر OTel Collector.
db.tenant_id أو تسجيل مقياس أعمال مثل orders.checkout.total_usd.
يبدو خدمة Python بسيطة مُوصَّلة بـ OTel على النحو التالي. ثبّت SDK ومُصدِّر OTLP، ثم هيّئ قبل تشغيل أي كود لإطار العمل:
اصطلاحات التسمية
اسم المقياس عقدٌ ملزم. بمجرد أن تستند لوحات المعلومات والتنبيهات وكتب التشغيل إلى http_requests_total، لا يمكنك إعادة تسميته بصمت دون كسر نصف أدوات المناوبة. تفرض شركات التقنية الكبرى التسمية عبر قواعد المدقق في CI وسجلات المخطط. اتبع هذه الاصطلاحات منذ البداية:
- اصطلاح Prometheus / OTel:
{namespace}_{subsystem}_{name}_{unit}. تأتي الوحدات في النهاية بصيغة الجمع snake_case:_secondsو_bytesو_total(للعدادات). مثال:checkout_payment_requests_totalوcheckout_payment_latency_seconds. - لا اختصارات في الاسم الأساسي.
http_req_dur_sسيُربك المهندس المُستدعى في الثالثة صباحاً. اكتبhttp_server_request_duration_seconds. - قواعد اللاحقة: تنتهي العدادات بـ
_total؛ تتجاهل المدرجات التكرارية والملخصات اللاحقة (Prometheus تُلحقها تلقائياً)؛ تصف المقاييس ما تقيسه (_bytesو_connectionsو_queue_depth). - أسماء الامتدادات (التتبعات): استخدم
فعل اسم—GET /orders/{id}وdb.query ordersوkafka.publish payment-events. لا تُدرج قيم المتغيرات في الاسم؛ ضعها في سمات الامتداد.
http.request.method وdb.system وmessaging.destination.name وrpc.method. استخدامها يعني أن بياناتك متوافقة مع لوحات المعلومات الجاهزة والترابطات عبر أي backend يدعم OTel. أعطِ دائماً الأولوية لسمة الاصطلاح الدلالي على السمة المخصصة.
انضباط البعد الأساسي
البعد الأساسي (Cardinality) هو عدد السلاسل الزمنية الفريدة التي يولّدها مقياس ما. مقياس بتسميات method (5 قيم) × status_code (10 قيم) × route (200 قيم) ينتج 10,000 سلسلة. أضف user_id (مليون مستخدم) وستحصل على عشرة مليارات سلسلة — Prometheus ينهار، وDatadog يُرسل لك فاتورة بستة أرقام.
القيم ذات البعد المرتفع — معرّفات المستخدمين ومعرّفات التتبع وعناوين البريد الإلكتروني والسلاسل الحرة والـ UUID وعناوين IP — يجب ألا تظهر أبداً كقيم لتسميات المقاييس. مكانها في سمات امتدادات التتبع وحقول السجلات المنظمة، حيث يتعامل نموذج التخزين معها بكفاءة.
labels={"customer_id": customer_id} إلى عداد. كل عميل جديد يُنشئ سلسلة جديدة. بعد حملة تسويقية تجلب موجة تسجيلات، يتعطل Prometheus بسبب نفاد الذاكرة وتتوقف التنبيهات تماماً في اللحظة التي تحتاجها فيها أكثر ما يكون. أضف التحقق من تسميات المقاييس إلى قائمة مراجعة PR وثقافة مراجعة الكود.
الأسلوب الصحيح هو تقييد كل تسمية بمجموعة صغيرة ومحدودة من القيم. لمسارات HTTP، قم بتطبيع معلمات المسار: /orders/12345 تصبح قيمة التسمية /orders/{id}. لرموز الحالة، جمّعها في فئات (2xx و4xx و5xx) إذا كان لديك رموز متعددة. لأي شيء آخر، اسأل: "هل ستنمو مجموعة قيم هذه التسمية بلا حدود؟" إذا كانت الإجابة نعم، انقلها إلى التتبعات.
موضع القياس: الإشارات الذهبية الأربع
قِس كل حد خدمة باستخدام الإشارات الذهبية الأربع التي روّج لها Google SRE: زمن الاستجابة وحركة المرور والأخطاء والإشباع. كحد أدنى، يجب أن يُصدر كل معالج HTTP/gRPC وكل استدعاء خارجي لقاعدة البيانات أو الكاش وكل مهمة خلفية هذه الأنواع الأربع من الإشارات. استخدم نمط Middleware أو Interceptor حتى يكون القياس تلقائياً ومتسقاً — لا تعتمد على تذكر المطورين لإضافته في كل نقطة نهاية.
اختبار أدوات القياس
أخطاء القياس صامتة — تعمل الخدمة بشكل جيد لكنها لا تُصدر أي بيانات، أو تُصدر بيانات خاطئة. أضف هذه الفحوصات إلى بيئة التطوير المحلية وخط أنابيب CI:
- استخدم مُصدِّر الذاكرة الداخلية من OTel في اختبارات الوحدة للتحقق من أن امتدادات ومقاييس محددة تنتجها مسارات الكود.
- شغّل OTel Collector محلياً مع مُصدِّر
debugلطباعة جميع بيانات القياس المُستلمة في stdout أثناء التطوير. - أضف نقطة نهاية
/metricsأو/debug/metricsوقم بـ curl عليها كاختبار دخاني في CI بعد النشر في staging. - اضبط تنبيهاً على
absent(up{job="my-service"})في Prometheus — إذا توقف الحصول على البيانات، ستعلم بذلك فوراً.
otelcol_exporter_send_failed_spans_total ونبّه عليه. كثير من الفرق تكتشف ثغرات في بيانات القياس فقط أثناء حادثة، حين تكون البيانات في أشد الحاجة إليها.
القياس هو الأساس الذي يرتكز عليه كل شيء. احصل على اختيار المكتبة والتسمية وحدود البعد الأساسي بشكل صحيح من البداية — إضافتها بأثر رجعي عبر بنية تحتية من 200 خدمة مشروع مُكلف يمتد لأرباع متعددة. ابنِ العادة الآن: كل خدمة جديدة تشحن مع أدوات القياس قبل أن تشحن بأي ميزة واحدة.