يا جماعة الخير، السلام عليكم ورحمة الله.
خلوني أحكيلكم قصة صارت معي قبل كم سنة، قصة بتورجي قديش ممكن شغلة بسيطة زي تنظيم “السجلات” (Logs) تفرق بين ليلة هادئة وليلة كلها طوشة وقلق. كنت وقتها مسؤول عن نظام كبير مبني على معمارية الخدمات المصغرة (Microservices)، إشي فخم وشغل مرتب، بس كان موزع على أكثر من 30 سيرفر. كل خدمة الها سيرفراتها الخاصة، وكل سيرفر بخزّن سجلاته في ملفات محلية عنده.
في ليلة من الليالي، الساعة 2 بعد منتصف الليل، رن جوالي. على الطرف الثاني كان مدير المشروع وصوته معصّب: “أبو عمر، النظام واقع! في عملاء مهمين مش قادرين يكملوا عمليات شراء، والمصاري معلّقة!”. قلبي نزل عند ركبي. هاي من أسوأ المكالمات اللي ممكن تجيك كمبرمج.
فتحت اللابتوب بسرعة، وبدأت رحلة العذاب. عشان أفهم شو اللي صار، كنت مضطر أتبع رحلة طلب المستخدم الواحد عبر 5 أو 6 خدمات مختلفة. هالحكي معناه إني لازم أعمل SSH على كل سيرفر من السيرفرات الثلاثين، وأفتح ملفات السجلات، وأقعد أبحث يدويًا باستخدام `grep` و `tail` عن أي إشي اله علاقة بالعميل هداك. كنت زي اللي بدور على إبرة في كومة قش، بس مش كومة واحدة، ثلاثين كومة قش! كل سيرفر كان عبارة عن جزيرة معزولة، وأنا بحاول أسبح بينهم وأجمع خيوط القصة. بعد ساعة ونص من التوتر والبحث اليدوي والقهوة اللي بردت، قدرت ألاقي أصل المشكلة. كانت خدمة دفع صغيرة هي اللي سببت كل هالخبصة.
وقتها حلفت يمين، إنه هادا الوضع ما رح يستمر. لازم ألاقي طريقة أجمع فيها كل هالجزر المعزولة في مكان واحد. ومن هنا بدأت رحلتي مع ما يسمى بـ “التسجيل المركزي” أو Centralized Logging.
ما هو الجحيم الذي كنت أعيش فيه؟ (مشكلة السجلات المبعثرة)
قبل ما نحكي عن الحل، خلينا نفصّل المشكلة أكتر. الوضع اللي كنت فيه، واللي للأسف كثير من الفرق لسا بتعاني منه، يمكن تلخيصه بالنقاط التالية:
- البحث اليدوي المُضني: كما في قصتي، تتبع خطأ واحد يتطلب الدخول لعشرات السيرفرات وتشغيل أوامر بحث على كل واحد. هذا بطيء، ممل، وعرضة للخطأ البشري.
- صعوبة ربط الأحداث (Correlation): كيف تعرف أن الخطأ الذي ظهر في “خدمة المستخدمين” على سيرفر 1 مرتبط برسالة تحذير ظهرت في “خدمة الطلبات” على سيرفر 5 بعد 100 ميللي ثانية؟ شبه مستحيل يدوياً.
- فقدان الصورة الكاملة: كل سيرفر يعطيك قطعة صغيرة من اللغز. أنت لا ترى الصورة الكبيرة للنظام، ولا يمكنك تحليل الأنماط العامة أو اكتشاف المشاكل الكامنة.
- صعوبة المراقبة والإنذار (Alerting): لا توجد طريقة سهلة لإنشاء تنبيهات ذكية. كيف ستعرف أن نسبة الأخطاء زادت 50% في آخر 10 دقائق إذا كانت السجلات موزعة في كل مكان؟
- مشاكل التخزين: مع الوقت، تمتلئ أقراص السيرفرات بملفات السجلات القديمة، مما قد يؤثر على أداء التطبيق نفسه أو حتى يوقفه عن العمل.
باختصار، كانت سجلاتي جزرًا معزولة، وكل جزيرة بتحكي لغتها الخاصة، وأنا كنت المترجم التعبان اللي بحاول يفهم شو القصة.
القارب المنقذ: ما هو التسجيل المركزي (Centralized Logging)؟
بكل بساطة، التسجيل المركزي هو ممارسة جمع السجلات من كل مصادرك (سيرفرات، تطبيقات، قواعد بيانات، حاويات Docker، أي شيء يولد سجلات) وإرسالها إلى مكان واحد مركزي. هذا المكان المركزي مصمم خصيصًا لتخزين كميات هائلة من البيانات النصية، وفهرستها، وتوفير واجهة قوية للبحث والتحليل والتصوير (Visualization).
فكر فيها كأنك تبني مكتبة ضخمة تجمع الكتب من كل الجزر المعزولة. فجأة، بدلاً من السفر لكل جزيرة للبحث عن معلومة، يمكنك الذهاب للمكتبة المركزية واستخدام فهرس ذكي للعثور على كل ما تحتاجه في ثوانٍ.
مكونات نظام التسجيل المركزي النموذجي
أي نظام تسجيل مركزي، سواء كان مفتوح المصدر أو خدمة مدفوعة، يتكون عادةً من أربعة أجزاء رئيسية:
- الناقل (Shipper/Agent): برنامج خفيف يعمل على كل سيرفر من سيرفراتك. وظيفته بسيطة: يقرأ السجلات من الملفات المحلية (أو مصادر أخرى) ويرسلها إلى النظام المركزي. أمثلة مشهورة:
Filebeat,Fluentd,Vector. - المُجمِّع/المُعالج (Collector/Processor): هو المحطة المركزية التي تستقبل السجلات من كل الناقلين. يمكنه القيام بعمليات معالجة على السجلات قبل تخزينها، مثل تحليل النصوص غير المهيكلة وتحويلها إلى حقول منظمة (Parsing)، أو إضافة معلومات إضافية (Enrichment). مثال مشهور:
Logstash. - وحدة التخزين/الفهرسة (Storage/Indexer): قاعدة بيانات متخصصة في تخزين وفهرسة البيانات النصية بسرعة فائقة للبحث. أشهر مثال في هذا المجال هو
Elasticsearch. بديل آخر صاعد بقوة هوLoki. - واجهة المستخدم (UI/Visualization): هي البوابة التي تتفاعل معها أنت كمطور. تتيح لك البحث، إنشاء رسوم بيانية، ولوحات متابعة (Dashboards)، وإعداد تنبيهات. أشهر مثال هو
Kibana(يعمل مع Elasticsearch) وGrafana(يعمل مع Loki وغيرها).
هذه المكونات غالبًا ما تُعرف بحزم مجمعة، أشهرها على الإطلاق حزمة ELK Stack (تُعرف الآن بـ Elastic Stack) والتي تتكون من Elasticsearch, Logstash, and Kibana.
نصيحة من أبو عمر: لنطبق الأمر عمليًا!
الحكي النظري حلو، بس خلينا نشوف كيف ممكن نبدأ بشغل عملي. لنفترض أن لدينا تطبيق ويب يستخدم Nginx كخادم ويب، ونريد جمع سجلات الوصول (access logs) الخاصة به في مكان مركزي باستخدام حزمة ELK.
الخطوة 1: إعداد حزمة ELK بسيطة باستخدام Docker
أسهل طريقة للبدء هي استخدام Docker Compose. أنشئ ملفًا باسم docker-compose.yml وضع فيه الكود التالي. هذا الكود سيقوم بتشغيل Elasticsearch, Logstash, and Kibana في حاويات منفصلة.
version: '3.7'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.5
container_name: elasticsearch
environment:
- discovery.type=single-node
ports:
- "9200:9200"
volumes:
- esdata:/usr/share/elasticsearch/data
logstash:
image: docker.elastic.co/logstash/logstash:7.17.5
container_name: logstash
ports:
- "5044:5044"
volumes:
- ./logstash-pipeline:/usr/share/logstash/pipeline
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:7.17.5
container_name: kibana
ports:
- "5601:5601"
depends_on:
- elasticsearch
volumes:
esdata:
driver: local
قبل تشغيل هذا، نحتاج لتعريف الـ “pipeline” الخاص بـ Logstash. أنشئ مجلدًا بجانب الملف اسمه logstash-pipeline وبداخله ملف logstash.conf:
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
# هنا يمكننا إضافة فلاتر لتحليل سجلات Nginx لاحقًا
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "nginx-logs-%{+YYYY.MM.dd}"
}
}
الآن، في الطرفية (Terminal)، شغّل الأمر: docker-compose up. بعد بضع دقائق، سيكون لديك نظام ELK كامل يعمل على جهازك!
الخطوة 2: إعداد Filebeat لإرسال السجلات
الآن على سيرفر Nginx الخاص بك، تحتاج لتثبيت Filebeat. بعد التثبيت، عدّل ملف الإعدادات الرئيسي /etc/filebeat/filebeat.yml ليبدو مشابهًا لهذا:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log # مسار سجلات الوصول في Nginx
output.logstash:
hosts: ["YOUR_LOGSTASH_IP:5044"] # استبدل بعنوان IP الخاص بسيرفر Logstash
شغّل Filebeat، وسيبدأ فورًا بقراءة ملف access.log وإرسال كل سطر جديد إلى Logstash، الذي بدوره سيحلله ويرسله إلى Elasticsearch.
الخطوة 3: استكشاف السجلات في Kibana
افتح متصفحك واذهب إلى http://localhost:5601 (أو عنوان IP الخاص بسيرفر Kibana). اذهب إلى قسم “Discover”. سترى سجلات Nginx تتدفق بشكل منظم! يمكنك الآن البحث والتصفية وإنشاء الرسوم البيانية بكل سهولة. لا مزيد من الـ SSH والـ `grep`!
نصائح ذهبية من خبرة أبو عمر
بعد سنوات من التعامل مع أنظمة التسجيل، تعلمت بعض الدروس بالطريقة الصعبة. خذوها مني ووفروا على أنفسكم بعض الألم:
1. هيكل سجلاتك (Structure Your Logs)
لا تسجل نصوصًا عادية! أسوأ شيء يمكن أن تفعله هو كتابة سجلات مثل: "An error occurred while processing user 123".
بدلاً من ذلك، استخدم تنسيقًا منظمًا مثل JSON. هذا يجعل عملية التحليل (Parsing) تلقائية ودقيقة جدًا.
مثال سيء (نص عادي):
INFO: User login successful for user 'omar'. Request ID: xyz-123.
مثال ممتاز (JSON):
{
"timestamp": "2023-10-27T10:00:00Z",
"level": "INFO",
"message": "User login successful",
"app": "auth-service",
"fields": {
"username": "omar",
"request_id": "xyz-123"
}
}
لاحظ كيف أن كل معلومة أصبحت في حقل خاص بها. الآن يمكنك بسهولة البحث عن كل السجلات للمستخدم ‘omar’ أو تتبع الطلب ‘xyz-123’.
2. استخدم معرّف الربط (Correlation ID)
هذه أهم نصيحة للعمل مع الخدمات المصغرة. عندما يدخل طلب جديد إلى نظامك (مثلاً، من خلال API Gateway)، قم بإنشاء معرّف فريد (UUID) وأعطه اسم correlation_id. قم بتمرير هذا المعرّف في الـ headers مع كل استدعاء داخلي بين خدماتك. وتأكد من أن كل خدمة تقوم بتضمين هذا المعرّف في كل سطر سجل تكتبه.
عندما تفعل ذلك، يمكنك ببحث واحد في Kibana عن هذا الـ correlation_id أن ترى القصة الكاملة لرحلة الطلب عبر كل الخدمات، مرتبة زمنيًا. هذا سحر خالص! ✨
3. لا تسجل كل شيء، بل سجل بذكاء
تكلفة تخزين ومعالجة السجلات يمكن أن تكون باهظة. استخدم مستويات السجل (Log Levels) بحكمة:
- DEBUG: معلومات تفصيلية جدًا للمطورين أثناء البرمجة. يجب تعطيلها في بيئة الإنتاج.
- INFO: معلومات عن الأحداث الهامة في النظام (بدء تشغيل خدمة، تسجيل دخول مستخدم).
- WARN: تحذيرات عن حالات غير متوقعة ولكنها لا توقف عمل النظام (مثلاً، محاولة استدعاء API خارجي وفشلت، ولكن هناك آلية إعادة محاولة).
- ERROR: أخطاء جدية أوقفت عملية معينة (فشل في الكتابة في قاعدة البيانات، استثناء غير معالج).
- FATAL/CRITICAL: خطأ كارثي أدى إلى توقف التطبيق بالكامل.
في بيئة الإنتاج، عادةً ما يتم تسجيل مستوى INFO فما فوق.
4. انتبه للأمان والخصوصية
إياك ثم إياك ثم إياك أن تسجل معلومات حساسة في السجلات! كلمات المرور، مفاتيح الـ API، أرقام بطاقات الائتمان، معلومات شخصية… كل هذا يجب ألا يظهر أبدًا في أي سجل. تأكد من وجود آليات لتنقية (Sanitize) السجلات من هذه البيانات قبل إرسالها.
الخلاصة: من الفوضى إلى السيطرة
التحول من السجلات المبعثرة إلى نظام تسجيل مركزي كان أحد أفضل القرارات التقنية التي اتخذتها في مسيرتي. لقد حوّل عملية تصحيح الأخطاء من كابوس يستغرق ساعات إلى عملية تحليلية سريعة ومنظمة تستغرق دقائق. لم أعد أخشى مكالمات منتصف الليل، بل أصبحت أراها كتحدٍ يمكن حله بسرعة بفضل الأدوات الصحيحة.
إذا كنت لا تزال تعتمد على الـ SSH والـ `grep`، فاعتبر هذه المقالة دعوة شخصية مني لك. ابدأ صغيرًا، استخدم الأدوات مفتوحة المصدر، وجرّب بنفسك. الاستثمار الذي تضعه اليوم في بناء نظام تسجيل مركزي سيوفر عليك أضعافه من الوقت والجهد والتوتر في المستقبل.
يلا يا جماعة، رتبوا سجلاتكم، لأنه الشغل المرتب هو أساس النجاح وراحة البال. 👍