كانت سجلاتنا متناثرة وضائعة: كيف أنقذنا التجميع المركزي (ELK/Loki) من جحيم تتبع الأخطاء؟

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.

خلوني أحكي لكم قصة صارت معي قبل كم سنة، قصة علّمتني درس ما بنساه للموت. كانت الساعة حوالي 2 بعد نص الليل، وأنا قاعد بشتغل على مشروع ضخم لعميل مهم. فجأة، بلّشت توصلني تنبيهات على الموبايل زي المطر: “فشل في عملية الدفع”، “بوابة الدفع لا تستجيب”. قلبي نزل عند ركبي. هاي كارثة بتعني خسارة فلوس للعميل، وخسارة سمعة إلنا.

جمّعت الفريق بسرعة على اتصال طارئ. التطبيق تبعنا كان مبني على نظام الخدمات المصغرة (Microservices)، يعني عندنا حوالي 7 أو 8 خدمات مختلفة بتتكلم مع بعض عشان تكمل عملية دفع واحدة. خدمة للمستخدمين، خدمة للمنتجات، خدمة للسلة، خدمة للطلبات، وخدمة بتتكلم مع بوابة الدفع نفسها. المشكلة وين؟ الله أعلم.

وبدأ الجحيم. كل واحد فينا صار يعمل SSH على سيرفر مختلف. أنا على سيرفر الطلبات، وزميلي على سيرفر بوابة الدفع، والثالث على سيرفر المستخدمين. كل واحد فاتح الطرفية (Terminal) وعم بكتب tail -f /var/log/app.log | grep ERROR. عيوننا صارت حمرا وإحنا بنحاول نلاقي أي إشي يدل على المشكلة. بنشوف خطأ في خدمة، بس ما بنعرف شو اللي سببه في الخدمة اللي قبلها. السجلات متناثرة، غير متزامنة، وكل واحد بصيغة. بعد ساعتين من التخبيص والضياع، اكتشفنا المشكلة: تحديث بسيط في مكتبة خارجية غيّر طريقة تعاملها مع الـ Timezone، فكانت الطلبات بتوصل لبوابة الدفع بتوقيت غلط فبترفضها. ساعتين ضاعوا من عمرنا، وكثير من أعصابنا، عشان نلاقي مشكلة كان ممكن نلاقيها بدقايق.

في هداك اليوم، بعد ما حلينا المصيبة، عملت اجتماع وقلت للفريق: “يا جماعة، هالحكي ما بنفع. شغلنا هيك زي اللي بدور على إبرة بكومة قش… وكل كومة بسيرفر مختلف. لازم نلاقي حل يجمع كل هالسجلات بمكان واحد”. ومن هنا بدأت رحلتنا مع التجميع المركزي للسجلات.

ما هو الجحيم الذي كنا نعيشه؟ (مشاكل السجلات المتناثرة)

قبل ما نحكي عن الحل، خلونا نفصّل أكتر بالمشكلة عشان نحس بقيمة الحل. الوضع اللي كنا فيه، واللي للأسف كثير من الفرق لسا عايشة فيه، كان عبارة عن:

  • الدخول المتعدد للخوادم: عشان تتبع طلب واحد، كنت محتاج تفتح 4 أو 5 نوافذ SSH على سيرفرات مختلفة. هذا بحد ذاته مرهق وبضيع وقت.
  • أدوات بدائية: الاعتماد على grep, tail, less و awk. هاي الأدوات عظيمة للملفات المحلية، لكنها كابوس لما بدك تربط أحداث بين عدة ملفات على عدة سيرفرات.
  • فقدان السياق (Correlation): لما تشوف خطأ في خدمة “الطلبات”، كيف بدك تعرف شو هي البيانات اللي استقبلتها من خدمة “السلة” واللي أدت لهذا الخطأ؟ بدون وجود مُعرّف موحد للطلب (Correlation ID) يمر بين كل الخدمات، أنت فعليًا أعمى.
  • ضياع السجلات: السجلات على الخوادم عادةً بيصيرلها عملية تدوير (Log Rotation) عشان ما تملأ القرص الصلب. يعني ممكن سجلات خطأ قديم إلها كم يوم تكون انمسحت للأبد.
  • مشاكل أمنية وصلاحيات: هل من المنطقي تعطي كل مطور صلاحية SSH على خوادم الإنتاج (Production) عشان يشوف السجلات؟ طبعًا لأ. هذا بيفتح باب لمشاكل أمنية لا حصر لها.

الضوء في نهاية النفق: التجميع المركزي للسجلات (Centralized Logging)

الفكرة بكل بساطة عبقرية: بدل ما كل خدمة تكتب سجلاتها في ملف محلي على السيرفر تبعها، بنخلي كل الخدمات “تبث” أو “ترسل” سجلاتها إلى مكان مركزي واحد. هذا المكان المركزي هو عبارة عن نظام متخصص في استقبال، تخزين، فهرسة، والبحث في كميات هائلة من السجلات.

لما يصير عندك نظام زي هيك، الفوائد بتكون خرافية:

  1. مكان واحد للحقيقة (Single Source of Truth): كل سجلاتك، من كل خدماتك، في مكان واحد. بدك تبحث عن خطأ؟ بتروح على واجهة مستخدم واحدة وبتبحث.
  2. بحث وتحليل قوي: هاي الأنظمة بتوفر لغات استعلام (Query Language) قوية جدًا بتخليك تفلتر السجلات، تبحث عن أنماط معينة، وتشوف الأخطاء اللي صارت في خدمة معينة خلال فترة زمنية محددة بضغطة زر.
  3. ربط الأحداث (Event Correlation): بتقدر تبحث عن “Correlation ID” معين وتشوف رحلة هذا الطلب بالكامل عبر كل الخدمات المصغرة، من لحظة دخوله للنظام للحظة خروجه.
  4. تنبيهات ذكية (Alerting): بتقدر تعمل تنبيهات ذكية. مثلاً: “إذا صار عندي أكتر من 100 خطأ من نوع 500 في خدمة الدفع خلال دقيقة واحدة، ابعثلي إيميل واتصل فيي”.
  5. رسوم بيانية ولوحات عرض (Visualization & Dashboards): تحويل السجلات من مجرد نصوص إلى رسوم بيانية جميلة. بتقدر تعمل داشبورد يعرض لك صحة النظام، عدد الأخطاء في كل خدمة، أبطأ العمليات، إلخ.

أشهر الأبطال في ساحة المعركة: ELK Stack و Loki

في عالم تجميع السجلات، في بطلين مشهورين كل واحد إله فلسفته الخاصة. خلونا نتعرف عليهم.

مكدس ELK: الوحش الكلاسيكي (The Classic Beast)

ELK هو اختصار لثلاثة مشاريع مفتوحة المصدر بتشتغل مع بعضها بشكل رائع:

  • E – Elasticsearch: هو القلب النابض. محرك بحث وتحليل قوي جدًا مبني على مكتبة Lucene. هو اللي بخزن كل السجلات وبيفهرسها عشان يخلي عملية البحث سريعة بشكل صاروخي، حتى لو عندك مليارات السجلات.
  • L – Logstash: هو عامل التوصيل والمعالجة. Logstash هو عبارة عن “pipeline” بيستقبل السجلات من مصادر مختلفة (ملفات، Docker, …)، بيقدر يعالجها ويغير صيغتها (مثلاً يحول سطر نص عادي إلى صيغة JSON منظمة)، وبعدين يرسلها إلى Elasticsearch.
  • K – Kibana: هي الواجهة الجميلة. Kibana بتخليك تتصفح، تبحث، وتعمل رسوم بيانية ولوحات عرض (Dashboards) مذهلة من البيانات المخزنة في Elasticsearch.

نصيحة أبو عمر: في نسخة أحدث من المكدس اسمها Elastic Stack، وصاروا يستخدموا أداة أخف من Logstash اسمها Beats (مثل Filebeat) عشان تجمع السجلات وترسلها. الفكرة العامة ما زالت نفسها.

متى تختار ELK؟ لما تكون محتاج تحليل عميق جدًا للبيانات، لما تكون سجلاتك غنية بالمعلومات وبدك تعمل استعلامات معقدة على محتوى السجلات نفسها. ELK قوي جدًا، لكنه بيستهلك موارد (رام ومعالج) بشكل كبير، وإعداده ممكن يكون معقد شوي.

Grafana Loki: البطل الخفيف والرشيق (The Lean and Agile Hero)

Loki هو لاعب أحدث في الساحة، لكنه اكتسب شعبية جبارة بسبب فلسفته المختلفة والمبتكرة. الفلسفة تبعته هي: “زي Prometheus، بس للسجلات”.

فكرته كالتالي: بدل ما يفهرس محتوى السجل بالكامل (زي Elasticsearch)، لوكي بيفهرس فقط “الوسوم” أو “العلامات” (Labels) المرتبطة بالسجل، زي اسم الخدمة، اسم السيرفر، البيئة (انتاج، تجريبي)، إلخ. أما نص السجل نفسه، فبيتم ضغطه وتخزينه كما هو.

هذا النهج له ميزتين أساسيتين:

  1. خفيف جدًا: لأنه ما بفهرس كل كلمة في السجلات، فهو بيحتاج موارد أقل بكثير من Elasticsearch.
  2. أقل تكلفة: تخزين الفهارس (Indexes) هو اللي بكلف مساحة وموارد. بما إنه فهارس Loki أصغر بكثير، فالتكلفة الإجمالية أقل.

المكدس الخاص بـ Loki عادةً يتكون من:

  • Loki: الخادم الرئيسي اللي بخزن وبيستعلم عن السجلات.
  • Promtail: هو العميل (Agent) اللي بيشتغل على سيرفراتك، بيقرأ السجلات وبيضيفلها الـ Labels الصحيحة (مثلاً من Docker labels أو Kubernetes labels) وبيرسلها لـ Loki.
  • Grafana: نعم، نفس Grafana اللي بنستخدمها للرسوم البيانية للمقاييس (Metrics) من Prometheus. Grafana عندها دعم ممتاز لـ Loki كمصدر بيانات (Data Source)، فبتقدر تشوف مقاييسك وسجلاتك في نفس الداشبورد.

متى تختار هذا أو ذاك؟ قرار أبو عمر

ببساطة يا جماعة:

  • إذا كنت شركة كبيرة، عندك فريق DevOps متخصص، وبتحتاج تعمل تحليلات معقدة جدًا على محتوى السجلات (Full-text search on content)، وعندك الميزانية والموارد اللازمة، ELK Stack هو وحش لا يُعلى عليه.
  • إذا كنت فريق صغير أو متوسط، أو بتستخدم Grafana و Prometheus أصلًا، وبهمك بشكل أساسي إنك تبحث وتفلتر السجلات بناءً على الخدمة أو السيرفر أو معرف الطلب (Correlation ID)، وبدك حل خفيف وسهل الإعداد وقليل التكلفة، Grafana Loki هو خيارك الأمثل. بصراحة، لـ 90% من حالات تتبع الأخطاء اليومية، Loki أكتر من كافي.

لنطبق الأمر عملياً: مثال بسيط مع Docker و Loki

الحكي النظري حلو، بس خلينا نشوف شغل عملي. رح نعمل مثال بسيط جدًا باستخدام Docker Compose عشان نشغّل Loki, Promtail, Grafana, وتطبيق بسيط يطبع سجلات.

أنشئ مجلد جديد، وداخله أنشئ الملفات التالية:

1. ملف docker-compose.yml:


version: "3"

services:
  loki:
    image: grafana/loki:2.9.2
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml

  promtail:
    image: grafana/promtail:2.9.2
    volumes:
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"

  # تطبيق بسيط يطبع سجلات كل ثانية
  my-app:
    image: alpine
    command: sh -c 'while true; do echo "[`date`] INFO: Processing user request..."; sleep 5; echo "[`date`] WARN: User cache is getting full."; sleep 5; done'

2. ملف promtail-config.yml:


server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
- job_name: containers
  static_configs:
    - targets:
        - localhost
      labels:
        job: container-logs
        __path__: /var/lib/docker/containers/*/*-json.log
  pipeline_stages:
    - docker: {}
    - static_labels:
        # نضيف علامة ثابتة لتمييز السجلات القادمة من هذا الـ Promtail
        host: my-local-machine

الشرح السريع:

  • docker-compose.yml: يقوم بتشغيل 4 خدمات: Loki (الخادم)، Promtail (جامع السجلات)، Grafana (الواجهة)، و `my-app` (تطبيق وهمي يطبع سجلات كل 5 ثواني).
  • promtail-config.yml: هذا هو العقل المدبر لـ Promtail. نحن نقول له أن يقرأ سجلات Docker مباشرة من النظام (من المسار /var/lib/docker/containers). سيقوم تلقائيًا بإضافة وسوم (labels) لكل سجل بناءً على معلومات الحاوية (اسم الحاوية، اسم الصورة، إلخ).

خطوات التشغيل:

  1. ضع الملفين في نفس المجلد.
  2. افتح الطرفية (Terminal) في هذا المجلد وشغل الأمر: docker-compose up
  3. انتظر قليلاً حتى تعمل كل الحاويات.
  4. افتح المتصفح واذهب إلى http://localhost:3000 (هذا هو Grafana).
  5. اسم المستخدم وكلمة المرور الافتراضية هما admin / admin. سيطلب منك تغيير كلمة المرور.
  6. من القائمة الجانبية، اذهب إلى Connections > Data Sources > Add data source.
  7. اختر Loki.
  8. في حقل URL، اكتب: http://loki:3100
  9. اضغط “Save & Test”. المفروض تشوف رسالة خضراء تقول “Data source connected”.
  10. الآن، من القائمة الجانبية، اذهب إلى “Explore”.
  11. من القائمة المنسدلة في الأعلى، تأكد من اختيار “Loki”.
  12. في حقل “Log browser”، اضغط على {job="container-logs"} ثم {container_name="your-folder-name-my-app-1"}.
  13. مبروك! سترى الآن السجلات القادمة مباشرة من حاوية my-app. جرب كتابة استعلامات مثل {container_name="your-folder-name-my-app-1"} |= "WARN" للبحث عن السجلات التي تحتوي على كلمة “WARN”.

هذا مثال بسيط جدًا، لكنه يوضح قوة الفكرة. تخيل أن لديك 50 خدمة، Promtail سيقوم بجمع سجلاتها كلها وإرسالها إلى Loki، وستتمكن من تصفحها والبحث فيها من مكان واحد. شغل مرتب!

نصائح أبو عمر الذهبية

بعد سنوات من التعامل مع السجلات، اسمحولي أقدم لكم كم نصيحة من القلب:

  • وحّدوا صيغة سجلاتكم (Standardize Your Logs): أهم نصيحة على الإطلاق. اتفقوا مع الفريق على صيغة موحدة للسجلات، وأفضل صيغة هي JSON. السجلات بصيغة JSON سهلة جدًا على الأنظمة مثل Logstash أو Promtail أنها تحللها وتستخرج منها حقول ووسوم بشكل تلقائي. بدل ما يكون السجل مجرد نص، بصير عبارة عن كائن (object) منظم.
  • استخدموا مُعرّف الطلب (Correlation ID): لما يوصل طلب جديد لنظامك (مثلاً لـ API Gateway)، قم بإنشاء مُعرّف فريد (UUID مثلاً)، وضعه في Header الطلب. كل خدمة مصغرة تستلم هذا الطلب، يجب أن تقرأ هذا المُعرّف وتضعه في كل سجلاتها المتعلقة بهذا الطلب. بهذه الطريقة، يمكنك البحث عن هذا الـ ID في Loki/Kibana ورؤية قصة حياة الطلب كاملة عبر كل الخدمات.
  • لا تسجل كل شيء، ولا تسجل القليل جدًا: استخدم مستويات السجلات (Log Levels) بحكمة (DEBUG, INFO, WARN, ERROR, FATAL). في بيئة الإنتاج، عادةً ما يتم تسجيل INFO فما فوق. سجل ما يكفي لتشخيص المشاكل، ولكن تجنب إغراق النظام بسجلات DEBUG غير الضرورية.
  • لا تسجل معلومات حساسة: إياك ثم إياك أن تسجل كلمات مرور، أرقام بطاقات ائتمان، أو مفاتيح API في سجلاتك. هذه كارثة أمنية. استخدم تقنيات “Masking” لإخفاء هذه المعلومات تلقائيًا.

الخلاصة: من الفوضى إلى النظام 🚀

يا جماعة، الانتقال من السجلات المتناثرة إلى نظام تجميع مركزي هو ليس رفاهية، بل هو ضرورة قصوى لأي تطبيق حديث. هو الفرق بين قضاء ليلة كاملة في البحث عن خطأ، وبين إيجاده في خمس دقائق وأنت تشرب فنجان قهوتك.

سواء اخترت وحش الـ ELK أو رشاقة Loki، المهم أن تبدأ. ابدأ صغيرًا، حتى لو بالمثال اللي عرضناه. ستكتشف أن الوقت والجهد الذي ستستثمره في إعداد هذا النظام سيعود عليك بأضعاف مضاعفة من راحة البال، وسرعة حل المشاكل، وجودة المنتج النهائي.

لا تنتظروا حريق الساعة الثانية صباحًا عشان تبنوا محطة الإطفاء الخاصة بكم. ابدأوا اليوم.

والله ولي التوفيق.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

الحوسبة السحابية

كنا ندفع ثمن الخوادم الخاملة: كيف أنقذتنا ‘الحوسبة بلا خوادم’ (Serverless) من جحيم التكاليف المهدرة؟

في هذه المقالة، أشارككم قصة حقيقية من تجربتي كمطور برمجيات عن كيفية انتقالنا من الخوادم التقليدية باهظة الثمن إلى معمارية الحوسبة بلا خوادم (Serverless). سنغوص...

21 مايو، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

كانت طلباتنا تتعثر في أوقات الذروة: كيف أنقذتنا ‘طوابير الرسائل’ (Message Queues) من جحيم الاختناقات؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف كاد تطبيقنا أن ينهار تحت ضغط المستخدمين في يوم إطلاق مهم، وكيف كانت "طوابير الرسائل" (Message Queues)...

21 مايو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

كانت بياناتنا المالية سجينة البنوك: كيف حررتها واجهات ‘الصيرفة المفتوحة’ (Open Banking)؟

من واقع تجربتي كمبرمج، كانت بياناتنا المالية حبيسة جدران البنوك الرقمية. في هذه المقالة، أسرد لكم كيف حولت واجهات برمجة التطبيقات للصيرفة المفتوحة (Open Banking)...

21 مايو، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

كانت ساحة لتبادل الاتهامات: كيف أنقذتنا ‘ثقافة ما بعد الحوادث عديمة اللوم’ من جحيم الخوف؟

من واقع تجربتي كمبرمج، تحولت اجتماعات مراجعة الحوادث التقنية من جلسات لوم واتهامات إلى بيئة آمنة للتعلم والنمو. في هذه المقالة، أشارككم كيف يمكن لـ...

21 مايو، 2026 قراءة المزيد
اختبارات الاداء والجودة

وداعاً لكابوس “هل كسرنا شيئاً؟”: كيف أنقذ اختبار التراجع البصري واجهاتنا الأمامية

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

21 مايو، 2026 قراءة المزيد
البودكاست