يا جماعة الخير، السلام عليكم ورحمة الله. اسمي أبو عمر، وأنا اليوم جاي أحكي لكم قصة صارت معي قبل كم سنة، قصة علمتني درسًا قاسيًا لكنه ثمين، درس ما بتتعلمه في الجامعات ولا في الدورات، بتتعلمه “عالحديدة” زي ما بنقول.
كانت الساعة حوالي 2 بعد منتصف الليل، وأنا في سابع نومة. فجأة، رن الجوال بصوت مزعج. على الطرف الثاني كان صوت مدير المشروع لأحد أهم عملائنا، صوته كان يرجف من القلق: “أبو عمر، الموقع واقع! مش شغال بالمرة!”.
قفزت من السرير وقلبي يدق زي طبول الحرب. فتحت اللابتوب بسرعة، ودخلت على لوحة المراقبة الرئيسية (Dashboard). كل شيء كان يبدو أخضر! استخدام المعالج طبيعي، الذاكرة تمام، الشبكة مستقرة. يا زلمة، شو القصة؟ حاولت أفتح الموقع بنفسي، وبالفعل، الصفحة تدور وتدور ثم تعطي خطأ 503 Service Unavailable.
هنا بدأ الجحيم الحقيقي. كان نظامنا مكونًا من حوالي 10 خدمات مصغرة (Microservices) تعمل على خوادم مختلفة. بدأت رحلة التحقيق الأعمى: أدخل عبر SSH على الخادم الأول، أكتب tail -f /var/log/app1.log، لا شيء غريب. أدخل على الخادم الثاني، أبحث في سجلات Nginx باستخدام grep " 50"، أرى الأخطاء لكن لا أعرف سببها. ثم على الخادم الثالث، والرابع… كنت كمن يبحث عن إبرة في عشرة أكوام من القش في غرفة مظلمة. كل سجل يحكي جزءًا صغيرًا من القصة، ومن المستحيل تجميع الصورة الكاملة.
بعد ساعتين من التوتر والبحث المحموم، اكتشفت المشكلة بالصدفة البحتة. إحدى الخدمات الصغيرة المسؤولة عن صلاحيات المستخدمين كانت تعيد استجابة فارغة بشكل متقطع بسبب تحديث صغير في قاعدة البيانات، مما كان يسبب انهيارًا متسلسلًا في الخدمات التي تعتمد عليها. لم أكتشف هذا إلا عندما فتحت نافذتين طرفيتين (terminals) جنبًا إلى جنب، وراقبت سجلات خدمتين في نفس اللحظة. في تلك اللحظة، أقسمت أن هذا الكابوس لن يتكرر. ومن هنا، بدأت رحلتي مع “التسجيل المركزي”.
ما هو جحيم “التحقيق الأعمى”؟
ما مررت به تلك الليلة هو ما أسميه “التحقيق الأعمى”. هو الوضع الذي تكون فيه لديك مشكلة في نظامك الموزع، لكنك لا تملك رؤية شاملة لما يحدث. أنت تتنقل بين الخوادم والخدمات المختلفة، كل واحدة لها سجلاتها الخاصة، وتنسيقها الخاص، وتوقيتها الخاص. هذا الأسلوب التقليدي في التعامل مع السجلات (Logs) له مشاكل قاتلة:
- مضيعة للوقت: الدخول لكل خادم على حدة والبحث في الملفات النصية عملية بطيئة ومملة للغاية، خاصة تحت الضغط.
- صعوبة ربط الأحداث: من شبه المستحيل أن تعرف أن الخطأ في “خدمة الدفع” الساعة 10:05:03 كان سببه مشكلة في “خدمة المصادقة” الساعة 10:05:01 إذا كانت السجلات متفرقة.
- فقدان السجلات: إذا انهار خادم أو حاوية (Container) ولم تتمكن من استعادتها، فغالبًا ما تضيع سجلاتها معها إلى الأبد.
- مشاكل أمنية: إعطاء المطورين صلاحية الدخول عبر SSH إلى خوادم الإنتاج (Production) لمجرد فحص السجلات يمثل ثغرة أمنية كبيرة.
الحل السحري: التسجيل المركزي (Centralized Logging)
ببساطة، التسجيل المركزي هو نظام يقوم بجمع كل السجلات من كل مصادرك (تطبيقات، خوادم، قواعد بيانات، أجهزة شبكة…) في مكان واحد، مركزي، قابل للبحث والتحليل. فكر فيه كأنه المكتبة المركزية الضخمة لمدينتك. بدلًا من أن تذهب إلى ألف مكتبة صغيرة غير منظمة، تذهب إلى مكان واحد فيه فهرس ممتاز يمكنك من إيجاد أي معلومة خلال ثوانٍ.
المكونات الأساسية لنظام التسجيل المركزي
أي نظام تسجيل مركزي، سواء بنيته بنفسك أو استخدمت خدمة جاهزة، يتكون عادة من الأجزاء التالية:
- الناقل (Shipper/Agent): برنامج خفيف يعمل على خوادمك وتطبيقاتك، وظيفته قراءة السجلات وإرسالها إلى مكان مركزي. أشهر الأمثلة: Filebeat, Fluentd.
- المُعالج (Processor/Aggregator): (اختياري لكن مهم) يستقبل السجلات من الناقلين، يقوم بتنظيفها، تحليلها (Parsing)، وإثرائها (Enrichment) قبل تخزينها. أشهر مثال: Logstash.
- وحدة التخزين (Storage/Backend): قاعدة بيانات مُحسّنة لتخزين وفهرسة كميات ضخمة من البيانات النصية بسرعة. أشهر مثال: Elasticsearch.
- واجهة المستخدم (UI/Visualization): الواجهة التي تستخدمها للبحث في السجلات، إنشاء الرسوم البيانية، ولوحات المراقبة (Dashboards). أشهر مثال: Kibana, Grafana.
هذه المكونات مجتمعة تُعرف غالبًا باسم ELK Stack (Elasticsearch, Logstash, Kibana) أو EFK Stack (Elasticsearch, Fluentd, Kibana).
كيف تبني نظام تسجيل مركزي خاص بك؟ (مثال عملي باستخدام ELK)
دعنا نأخذ مثالًا عمليًا. لنفترض أن لدينا خادم ويب يعمل عليه Nginx وتطبيق مكتوب بلغة Python، ونريد جمع سجلاتهما.
الخطوة الأولى: إعداد الناقل (Filebeat)
سنقوم بتثبيت Filebeat على خادم الويب. وظيفته هي مراقبة ملفات السجلات وإرسال أي سطر جديد إلى Logstash. هذا مثال على ملف الإعدادات filebeat.yml:
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
log_type: nginx_access # نضيف حقل لتمييز نوع السجل
- type: log
enabled: true
paths:
- /var/log/my_app/app.log
multiline.pattern: '^{' # إذا كان سجل JSON يمتد على عدة أسطر
multiline.negate: true
multiline.match: after
fields:
log_type: my_app_json
# نرسل الخرج إلى خادم Logstash
output.logstash:
hosts: ["logstash-server-ip:5044"]
نصيحة من أبو عمر: استخدم حقل
fieldsفي Filebeat لإضافة “وسوم” ثابتة للسجلات. هذا يساعدك لاحقًا في الفلترة والبحث بسهولة، مثل التمييز بين سجلات الواجهة الأمامية (frontend) والخلفية (backend).
الخطوة الثانية: معالجة السجلات (Logstash)
الآن يستقبل Logstash السجلات. هنا يحدث السحر الحقيقي. سنقوم بتحليل سجلات Nginx النصية وتحويلها إلى حقول منظمة، وسجلات التطبيق التي هي بصيغة JSON ستُحلل تلقائيًا.
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
# إذا كان السجل من نوع Nginx
if [fields][log_type] == "nginx_access" {
# استخدم نمط Grok لتحليل السطر النصي إلى حقول
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
# استخرج الموقع الجغرافي من IP المستخدم
geoip {
source => "clientip"
}
}
# إذا كان السجل من نوع JSON
else if [fields][log_type] == "my_app_json" {
# قم بتحليله كـ JSON
json {
source => "message"
}
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch-server-ip:9200"]
index => "logs-%{[fields][log_type]}-%{+YYYY.MM.dd}" # إنشاء فهرس يومي لكل نوع
}
}
نمط grok في المثال أعلاه هو أداة قوية جدًا تحول سطرًا نصيًا غير منظم مثل سجل Nginx إلى كائن JSON منظم يحتوي على حقول مثل clientip, response_code, request_path.
الخطوة الثالثة: البحث والتصوير (Kibana)
بمجرد أن تصل البيانات إلى Elasticsearch، يمكنك فتح Kibana والبدء في استكشاف عالمك الجديد. يمكنك الآن أن تسأل أسئلة لم تكن تحلم بطرحها من قبل:
- “أرني كل الأخطاء التي تحمل الكود 500 من كل خدماتي في آخر 15 دقيقة.”
- “ما هي أكثر 10 صفحات تسببت في أخطاء 404 اليوم؟”
- “ارسم لي خريطة توضح توزيع المستخدمين جغرافيًا بناءً على سجلات Nginx.”
- “أنشئ تنبيهًا يرسل لي إشعارًا على Slack إذا زاد معدل زمن الاستجابة (response time) عن 500ms.”
لقد انتقلت من التحقيق الأعمى إلى الرؤية الكاملة والشاملة 360 درجة لنظامك.
نصائح من “الختيار”: خلاصة خبرتي في إدارة السجلات
بعد سنوات من التعامل مع هذه الأنظمة، اسمحوا لي أن أقدم لكم بعض النصائح العملية التي أتمنى لو أن أحدًا أخبرني بها في البداية:
1. السجلات المنظمة (Structured Logging) هي الكنز الحقيقي
أفضل نصيحة يمكن أن أقدمها لك: لا تسجل نصًا عشوائيًا، سجل بصيغة JSON مباشرة من تطبيقك. هذا يوفر عليك عناء التحليل (Parsing) في Logstash ويجعل سجلاتك قابلة للاستخدام فورًا. كل لغات البرمجة الحديثة لديها مكتبات للقيام بذلك بسهولة.
مثال في Python:
import logging
import json
from pythonjsonlogger import jsonlogger
logger = logging.getLogger()
logHandler = logging.StreamHandler()
# استخدم هذا الـ formatter لتحويل السجل إلى JSON
formatter = jsonlogger.JsonFormatter('%(asctime)s %(name)s %(levelname)s %(message)s')
logHandler.setFormatter(formatter)
logger.addHandler(logHandler)
logger.setLevel(logging.INFO)
# هكذا تسجل الأحداث مع سياق إضافي
extra_data = {
'user_id': 'user-123',
'request_id': 'abc-xyz-789' # هذا مهم جدا لتتبع الطلب عبر الخدمات
}
logger.error('Failed to process payment', extra=extra_data)
# الناتج سيكون سطر JSON منظم:
# {"asctime": "...", "name": "root", "levelname": "ERROR", "message": "Failed to process payment", "user_id": "user-123", "request_id": "abc-xyz-789"}
2. السياق هو الملك (Context is King)
سجل يقول “حدث خطأ” لا قيمة له. سجل يقول “فشل في معالجة الدفعة للطلب رقم #5543 للمستخدم ‘user-123’ بسبب انتهاء صلاحية البطاقة” هو سجل من ذهب. أضف دائمًا معرفات فريدة (مثل request_id أو trace_id) لكل طلب يمر عبر نظامك. هذا يسمح لك بتتبع رحلة الطلب الواحد عبر جميع خدماتك المصغرة ببحث واحد بسيط.
3. فكر في التكلفة والتخزين
السجلات تستهلك مساحة تخزين كبيرة، والمساحة تكلف مالًا. ضع سياسة للاحتفاظ بالبيانات (Retention Policy). مثال:
- Hot Tier: احتفظ بالسجلات المفصلة والقابلة للبحث لمدة 7 أيام على أقراص SSD سريعة.
- Warm/Cold Tier: بعد 7 أيام، انقلها إلى أقراص أبطأ وأرخص لمدة 30 يومًا.
- Archive: بعد ذلك، قم بأرشفة السجلات في خدمة تخزين رخيصة جدًا (مثل AWS S3 Glacier) لمدة عام للامتثال للقوانين أو للتحليل المستقبلي.
4. لا تسجل البيانات الحساسة!
هذه نقطة لا يمكن التشديد عليها بما فيه الكفاية. إياك ثم إياك أن تسجل كلمات المرور، مفاتيح الـ API، أرقام البطاقات الائتمانية، أو أي معلومات شخصية حساسة كنص واضح. استخدم فلاتر في Logstash أو في تطبيقك نفسه لحذف أو إخفاء (Masking) هذه البيانات قبل إرسالها.
الخلاصة: لا تنتظر الكارثة لتبني شبكة أمانك 🛟
التسجيل المركزي ليس مجرد أداة تقنية جميلة، بل هو ضرورة أساسية وعقلية عمل (mindset) لأي فريق هندسي جاد. إنه ينقلك من حالة رد الفعل والفوضى عند حدوث المشاكل، إلى حالة من الاستباقية والتحكم والرؤية الواضحة. قد يبدو إعداده عملًا إضافيًا في البداية، لكن أؤكد لك، في أول ليلة ينهار فيها خادمك وتتمكن من تحديد المشكلة وحلها في 5 دقائق بدلًا من 5 ساعات، ستشكر كل دقيقة قضيتها في بناء هذا النظام.
يلا يا شباب، شدوا حيلكم وابدأوا اليوم، حتى لو بنظام بسيط. فالسلامة خير من الندامة. 💪