الدرس 1 من 8 · الأساسيات
قابلية الرصد (Observability): المقاييس، السجلات، التتبّعات، SLI وSLO
الهدف
فهم ما نقيسه عندما « نراقب » تطبيقًا، والتمييز بين الإشارات الكبرى الثلاث (المقاييس، السجلات، التتبّعات)، ومعرفة كيفية تحديد هدف خدمة مرقّم، مع ميزانية الأخطاء الخاصة به. هذا هو أساس التكوين كله.
أهم النقاط
- تجيب المراقبة (monitoring) عن سؤال « هل يعمل؟ »؛ أما قابلية الرصد (observability) فتسمح بالإجابة عن سؤال « لماذا لا يعمل؟ » دون إضافة شيفرة أثناء التشغيل.
- تتكامل ثلاث إشارات: المقاييس (metrics، أرقام عبر الزمن)، والسجلات (logs، أحداث نصية)، والتتبّعات (traces، مسار طلب عبر عدة خدمات).
- SLI (Service Level Indicator) هو مقياس للجودة كما يراها المستخدم: نسبة الطلبات الناجحة، نسبة الطلبات المخدومة في أقل من 300 ms…
- SLO (Service Level Objective) هو الهدف المحدّد لهذا الـ SLI على نافذة زمنية: « 99.9 % من عمليات الدفع ناجحة على مدى 30 يومًا ».
- ميزانية الأخطاء (error budget) = 100 % − SLO. ما دام منها شيء متبقٍّ، يمكن للفريق أن يُسلّم؛ وعندما تنفد، نعطي الأولوية للموثوقية.
- نُطلق التنبيهات على الأعراض التي يعانيها المستخدم (الأخطاء، البطء)، لا على كل سبب محتمل (CPU عند 80 %).
المراقبة أم قابلية الرصد؟
لنأخذ متجرًا إلكترونيًا في الدار البيضاء يبيع منتجات الصناعة التقليدية. مساء يوم جمعة، يشتكي الزبائن: « الدفع يدور في الفراغ ».
- مع مراقبة تقليدية، لديك ضوء أخضر أو أحمر لكل خادم: خادم الويب يجيب على ping، وقاعدة البيانات تعمل. كل شيء أخضر… ومع ذلك لا يتمكّن الزبائن من الدفع.
- مع قابلية الرصد، ترى أن نسبة أخطاء الـ API
/api/paiementارتفعت من 0.05 % إلى 4 % عند الساعة 21:12، وأن السجلات تُظهر « timeout » نحو بوابة الدفع، وأن تتبّع طلب بطيء يُظهر 9 ثوانٍ قضاها في الاتصال بمزوّد الخدمة البنكية.
قابلية الرصد لا تعوّض المراقبة: بل تُغنيها. والكلمة مأخوذة من علم التحكّم الآلي: يكون النظام قابلًا للرصد إذا أمكن استنتاج حالته الداخلية انطلاقًا مما يُصدره.
الإشارات الثلاث
| الإشارة | الشكل | مثال | الكلفة | سؤال نموذجي |
|---|---|---|---|---|
| المقياس (metric) | عدد + طابع زمني + وسوم | http_requests_total{route="/api/paiement",status="503"} 17 |
ضعيفة، حجم ثابت | « كم؟ بأي سرعة؟ منذ متى؟ » |
| السجلّ (log) | سطر نصي أو JSON | 2026-10-18T21:12:04 ERROR paiement timeout cmi 9001ms |
متوسطة إلى مرتفعة، تزداد مع حجم الحركة | « ماذا حدث بالضبط؟ » |
| التتبّع (trace) | شجرة من الـ spans المؤقّتة | الطلب 7f3a…: web 12 ms → api 40 ms → banque 9 001 ms | مرتفعة، غالبًا بأخذ عيّنات | « أين قُضي الوقت؟ » |
المسار المعتاد للتشخيص: مقياس يُطلق التنبيه، ولوحة قيادة (dashboard) تحدّد موقع المشكلة في الزمن، والسجلات والتتبّعات تعطي التفاصيل.
المقاييس
المقياس سلسلة زمنية (time series): اسم، ووسوم (labels)، وقيم متتالية. يميّز Prometheus، الأداة المحورية في هذا التكوين، بين أربعة أنواع:
# عدّاد (counter): لا يفعل إلا الارتفاع (أو يعود إلى الصفر عند إعادة التشغيل)
http_requests_total{route="/api/paiement", status="200"} 184532
# مقياس لحظي (gauge): يرتفع وينخفض
node_memory_MemAvailable_bytes{instance="srv-web-rabat:9100"} 2147483648
# مدرّج تكراري (histogram): عدّادات لكل شريحة مدّة (« bucket »)
http_request_duration_seconds_bucket{le="0.3"} 181020
http_request_duration_seconds_bucket{le="+Inf"} 184532
# ملخّص (summary): قيم مئينية (quantiles) تُحسب من جهة التطبيق
rpc_duration_seconds{quantile="0.95"} 0.41
المقاييس قليلة الكلفة: سواء كان هناك 10 طلبات أو 10 000 طلب في الثانية، يشغل العدّاد الحيّز نفسه. ولهذا نحتفظ بها طويلًا ونُطلق التنبيهات بناءً عليها.
انتبه إلى الوسوم: كل تركيبة من القيم تُنشئ سلسلة جديدة. وسم client_id مع 200 000 زبون يُنشئ 200 000 سلسلة: هذا هو خطأ الكاردينالية (cardinality) الذي يُفجّر ذاكرة خادم المقاييس.
السجلات
تروي السجلات الأحداث واحدًا تلو الآخر. وهي لا غنى عنها لفهم حالة محدّدة (« لماذا فشلت الطلبية 88412؟ »). الممارسات الجيدة:
{"ts":"2026-10-18T21:12:04Z","niveau":"error","service":"paiement","commande":88412,"msg":"timeout passerelle","duree_ms":9001}
- صيغة مهيكلة (JSON) بدل النص الحرّ: يمكن التصفية حسب الحقل؛
- مستوى (
debug،info،warn،error)؛ - أبدًا لا رقم بطاقة، ولا كلمة مرور، ولا رقم البطاقة الوطنية (CIN) بشكل واضح في سجلّ (القانون 09-08 المتعلق بالمعطيات الشخصية في المغرب).
التتبّعات
يتبع التتبّع طلبًا واحدًا عبر جميع الخدمات. كل مرحلة هي span لها بداية ومدّة ومعرّف تتبّع مشترك. المعيار المفتوح الحالي هو OpenTelemetry (مكتبات، بروتوكول OTLP)، مع أدوات مثل Jaeger أو Tempo لتخزين التتبّعات وعرضها. أما Prometheus فلا يخزّن التتبّعات: إنه يهتم بالمقاييس.
طرق اختيار ما نقيسه
شبكتان بسيطتان تجنّبان قياس كل شيء عشوائيًا:
- RED لخدمة تستقبل طلبات: Rate (معدّل الطلبات)، Errors (الأخطاء)، Duration (المدّة).
- USE لمورد (CPU، قرص، شبكة): Utilization (نسبة الانشغال)، Saturation (التشبّع، أي طابور الانتظار)، Errors.
« الإشارات الذهبية الأربع » التي روّجت لها Google تأخذ الفكرة نفسها: زمن الاستجابة (latency)، حجم الحركة، الأخطاء، التشبّع.
Service « paiement » (RED) Serveur srv-bdd-casa (USE)
débit : requêtes/s CPU : % occupé, file d'exécution
erreurs : % de réponses 5xx disque : % plein, temps d'attente E/S
durée : 95e centile en ms réseau : débit, paquets perdus
SLI وSLO وSLA
ثلاثة اختصارات كثيرًا ما يُخلط بينها:
| الاختصار | الاسم | من يحدّده | مثال بالنسبة للدفع |
|---|---|---|---|
| SLI | مؤشّر مستوى الخدمة | الفريق التقني | نسبة طلبات /api/paiement دون خطأ 5xx |
| SLO | هدف مستوى الخدمة | الفريق، مع الجانب التجاري (المهنة) | 99.9 % على مدى 30 يومًا متحرّكة |
| SLA | اتفاق مستوى الخدمة | العقد التجاري | 99.5 %، وإلا غرامة بنسبة 10 % من الاشتراك |
الـ SLA دائمًا أقل تشدّدًا من الـ SLO: يُستعمل الـ SLO كإنذار داخلي قبل الإخلال بالعقد.
يُحسب الـ SLI الجيد على شكل نسبة بين الأحداث الجيدة ومجموع الأحداث:
SLI disponibilité = requêtes réussies / requêtes totales
SLI latence = requêtes servies en moins de 300 ms / requêtes totales
ميزانية الأخطاء
إذا كان الـ SLO هو 99.9 % على مدى 30 يومًا، فمن حقّك نسبة فشل قدرها 0.1 %:
30 jours × 24 h × 60 min = 43 200 minutes
43 200 × 0,001 = 43,2 minutes d'indisponibilité tolérée par mois
Même calcul en requêtes : sur 2 millions de paiements par mois,
2 000 000 × 0,001 = 2 000 requêtes en échec tolérées.
| SLO | عدم التوافر المسموح به شهريًا (30 يومًا) | سنويًا |
|---|---|---|
| 99 % | 7 h 12 min | 3.65 يوم |
| 99.5 % | 3 h 36 min | 1.83 يوم |
| 99.9 % | 43 min | 8 h 46 min |
| 99.99 % | 4 min 19 s | 52 min |
كل « 9 » إضافية تكلّف غاليًا جدًا (التكرار الاحتياطي، المناوبة، الاختبارات). مدرسة إلكترونية في فاس لا تحتاج إلى الـ SLO نفسه الذي يحتاجه بنك. اختر هدفًا يلاحظه مستخدموك فعلًا.
تصبح ميزانية الأخطاء أداة لاتخاذ القرار: هل بقي منها شيء؟ نُسلّم النسخة الجديدة. هل نفدت؟ نجمّد المستجدات ونصلح الموثوقية.
كتابة الـ SLO بالأبيض والأسود
الـ SLO الذي لا يوجد إلا في رأس شخص واحد لا فائدة منه. ضعها في مستودع Git الخاص بالفريق، بصيغة بسيطة:
# slo/paiement.yml
service: paiement
sli: requêtes /api/paiement sans réponse 5xx / requêtes totales
objectif: 99.9 # بالنسبة المئوية
fenetre: 30d # 30 يومًا متحرّكة
responsable: equipe-paiement
revue: trimestrielle # نعيد مناقشة الهدف كل ثلاثة أشهر
حساب SLI يدويًا
قبل أن يتوفّر Prometheus، يكفي سجلّ وصول (access log) بسيط للقياس. مع سجلّ بالصيغة المركّبة (combined) لـ nginx، يكون رمز الحالة هو الحقل التاسع:
# العدد الإجمالي للطلبات
wc -l < /var/log/nginx/access.log
# عدد الاستجابات 5xx (أخطاء من جهة الخادم)
awk '$9 ~ /^5/ {n++} END {print n+0}' /var/log/nginx/access.log
# التوافر بالنسبة المئوية
awk '{t++} $9 !~ /^5/ {ok++} END {printf "%.2f %%\n", ok*100/t}' /var/log/nginx/access.log
لماذا الـ 5xx فقط؟ الخطأ 404 أو 401 يكون عمومًا خطأ الزبون (عنوان خاطئ، كلمة مرور خاطئة): لا ينبغي أن يستهلك ميزانية أخطاء الخدمة. وعلى العكس، يعني الخطأ 503 أنك أنت لم تتمكّن من الإجابة.
في الدروس التالية، سيُجري Prometheus هذا الحساب بشكل مستمر:
sum(rate(http_requests_total{status!~"5.."}[30d])) / sum(rate(http_requests_total[30d]))
موقع كل أداة
Applications et serveurs
│ métriques (/metrics) journaux traces (OTLP)
▼ ▼ ▼
Prometheus ──règles──▶ Alertmanager ──▶ e-mail, chat, astreinte
│ Loki / Elasticsearch Jaeger / Tempo
└──────────────┬─────────────┴──────────────────────┘
▼
Grafana (tableaux de bord, exploration)
| الحاجة | الأدوات الشائعة |
|---|---|
| المقاييس | Prometheus، VictoriaMetrics، InfluxDB، Zabbix (مقاربة أكثر تقليدية) |
| التنبيهات | Alertmanager، Grafana Alerting |
| السجلات | Loki، ELK (Elasticsearch، Logstash، Kibana)، OpenSearch |
| التتبّعات | OpenTelemetry + Jaeger أو Tempo |
| لوحات القيادة | Grafana، Perses |
يناسب Prometheus جيدًا السلاسل الرقمية البحتة، ويبقى قابلًا للاستعمال أثناء العطل، لأن كل خادم مستقل بذاته. ولا يناسب الحالات التي تتطلّب دقّة بنسبة 100 %، مثل فوترة كل طلب: استعمل حينها قاعدة بيانات أو السجلات.
أخطاء متكررة
- التنبيه على كل شيء: 200 تنبيه في اليوم، ولا أحد يقرؤها. نبّه على الأعراض (الأخطاء، البطء الذي يشعر به المستخدم)، واحتفظ بالأسباب (CPU، الذاكرة) للوحات القيادة.
- SLO بنسبة 100 %: يستحيل الالتزام به، ويمنع أي تحديث. حتى كبار مزوّدي السحابة يستهدفون أقل من ذلك.
- احتساب الـ 4xx كأعطال: موجة من كلمات المرور الخاطئة ستوهم بعطل في الخدمة.
- وسوم ذات كاردينالية مرتفعة (معرّف الزبون، عنوان IP، رقم الطلبية) داخل المقاييس: ضعها في السجلات، لا في الوسوم.
التطبيق العملي (Lab)
أنت مهندس الاستغلال (operations) في متجر إلكتروني. يحتوي السجلّ /root/obs/acces.log على 1 000 استدعاء لـ API الدفع. ستقوم بما يلي:
- وصف هدف الخدمة في ملف YAML صغير؛
- حساب ميزانية الأخطاء الموافقة، بالدقائق؛
- عدّ استجابات 5xx في السجلّ بواسطة
awk؛ - تقرير ما إذا كان الهدف متحقّقًا على هذه العيّنة.
اختبار قصير
- اذكر الإشارات الثلاث لقابلية الرصد وسؤالًا يجيب عنه كلٌّ منها.
- ما الفرق بين SLO وSLA؟ أيّهما أكثر تشدّدًا؟
- لخدمة ما SLO بنسبة 99.5 % على مدى 30 يومًا. كم دقيقة من عدم التوافر مسموح بها؟
- لماذا لا ينبغي وضع معرّف الزبون في وسم مقياس؟
- هل يجب إطلاق تنبيه عندما يتجاوز CPU خادمٍ ما 80 %؟ علّل.
الأجوبة
- المقاييس: « كم، وبأي سرعة؟ »؛ السجلات: « ماذا حدث بالضبط؟ »؛ التتبّعات: « أين قُضي وقت هذا الطلب؟ ».
- الـ SLO هدف داخلي يحدّده الفريق؛ أما الـ SLA فالتزام تعاقدي مع غرامات. الـ SLO أكثر تشدّدًا، لكي نُنبَّه قبل الإخلال بالـ SLA.
- 43 200 × 0.005 = 216 دقيقة، أي 3 h 36 min.
- كل قيمة وسم تُنشئ سلسلة زمنية: مئات الآلاف من الزبائن ستُفجّر الذاكرة والتخزين (الكاردينالية). هذه المعلومة مكانها السجلات.
- عمومًا لا: ارتفاع CPU لا يشعر به المستخدم بالضرورة. نُطلق التنبيهات على الأعراض (الأخطاء، زمن الاستجابة) ونطّلع على CPU في لوحة قيادة أثناء التشخيص. استثناء واحد: التشبّع المستمر الذي يُنذر بعطل وشيك.
المراجع: توثيق Prometheus (Apache 2.0). نص أصلي من MasterLinux.