يا جماعة الخير، السلام عليكم. اسمي أبو عمر، وهذا الموقف صار معي قبل كم سنة، بس والله للآن بتذكره كأنه مبارح.
كنا في نص الليل، الساعة بتدق 2 الفجر، وفريقنا كله “فاتح بالحيط”. كان عنا تطبيق مهم جداً لعميل كبير، وفجأة بلش التطبيق يتصرف بغرابة. طلبات بتفشل بشكل عشوائي، المستخدمين بشتكوا من بطء وأخطاء غريبة، وما في أي نمط واضح للمشكلة. الوضع كان كارثي، والضغط علينا من كل حدب وصوب.
شو الحل؟ قلنا “خلينا نشوف السجلات (Logs)”. وهون بلشت المأساة الحقيقية. تطبيقنا كان عبارة عن خدمات مصغرة (Microservices)، يعني عندنا 10 سيرفرات مختلفة، وكل سيرفر عليه كومة ملفات سجل. صرت أنا وزميلي “نطنط” من سيرفر لسيرفر باستخدام SSH، ونستخدم أمر grep و tail و less في محاولة يائسة نلاقي أي إشي يدلنا على المشكلة.
كان الوضع أشبه بالبحث عن إبرة سوادء في كومة قش في ليلة ظلماء. ملفات بتنسيقات مختلفة، توقيتات زمنية مش متزامنة بين السيرفرات، وأحجام ملفات بالجيجابايت. بعد ساعتين من التخبيط والبحث العقيم، صرخت فيهم: “خلص! بكفي! هاي شغلانة بتجلط ومش رح توصلنا لنتيجة. من بكرة الصبح، أول إشي رح نعمله هو بناء نظام تسجيل مركزي. ما رح أسمح لهالمهزلة تتكرر”.
وهكذا كانت البداية… بداية رحلتنا مع مكدس ELK الذي أنقذنا من هذا الجحيم.
ما هي مشكلة ملفات السجل المبعثرة؟
القصة اللي حكيتها مش مجرد فضفضة يا جماعة. هي بتلخص معاناة حقيقية بتواجهها أغلب الفرق البرمجية اللي ما عندها نظام تسجيل مركزي. المشكلة أعمق من مجرد إزعاج، الها أبعاد خطيرة:
- إضاعة وقت كارثية: الوقت اللي بتقضيه في الدخول لكل سيرفر والبحث اليدوي هو وقت ثمين كان ممكن تستغله في حل المشكلة نفسها.
- صعوبة ربط الأحداث: لما يكون عندك طلب بمر عبر 3 خدمات مختلفة، كيف بدك تتبع رحلته بالكامل إذا كانت سجلات كل خدمة في مكان منعزل؟ شبه مستحيل.
- فقدان الرؤية الشاملة: أنت لا ترى الصورة الكبيرة. ما بتقدر تعرف الأنماط، مثل “هل كل أخطاء 500 بتيجي من الخدمة الفلانية؟” أو “هل في زيادة مفاجئة في عدد الطلبات على النظام؟”.
- مشاكل أذونات وأمان: هل من المنطقي تعطي كل مطور في الفريق صلاحية الدخول (SSH) على سيرفرات الإنتاج؟ طبعاً لا. هذا بيخلق عنق زجاجة، بحيث بس شخص أو شخصين عندهم القدرة على البحث.
ببساطة، بدون نظام تسجيل مركزي، أنت تقود طائرة في الضباب وأنت أعمى.
الحل السحري: مكدس ELK Stack
ELK هو اختصار لثلاثة مشاريع مفتوحة المصدر بتشتغل مع بعضها بشكل متناغم لحل مشكلة السجلات هاي. مؤخراً صاروا يسموه Elastic Stack لأنه انضافت عليه مكونات جديدة مثل الـ Beats، بس الاسم القديم لسا دارج.
خلينا نفصصهم حبة حبة:
- E – Elasticsearch: هذا هو القلب النابض للمنظومة. هو محرك بحث وتحليل قوي جداً. فكر فيه كقاعدة بيانات ضخمة ومفهرسة مصممة خصيصاً لتخزين كميات هائلة من البيانات النصية (زي سجلاتنا) والبحث فيها بسرعة خيالية.
- L – Logstash: هذا هو “السبّاك” أو خط الأنابيب. وظيفته يجمع السجلات من مصادر مختلفة (ملفات، قواعد بيانات، رسائل…)، وبعدها يقوم بمعالجتها وتصفيتها وتحويلها لصيغة موحدة ومرتبة، وأخيراً يرسلها لوجهتها النهائية (اللي هي Elasticsearch).
- K – Kibana: هذه هي الواجهة الجميلة اللي بنتعامل معها. هي أداة تصور (Visualization) بتخليك تبحث في البيانات المخزنة في Elasticsearch وتعمل رسوم بيانية ولوحات معلومات (Dashboards) تفاعلية ورهيبة. هي اللي بتحول كومة البيانات لرسومات وقصص مفهومة.
رحلة خط السجل (Log Entry) من التطبيق إلى لوحة المعلومات
عشان نفهم الموضوع عملياً، تخيل معي رحلة سجل خطأ واحد من لحظة حدوثه:
- التطبيق يكتب السجل: تطبيقك (مثلاً تطبيق ويب) بواجه خطأ وبيكتب سطر في ملف
error.logعلى السيرفر. - Filebeat يلتقط السطر: على نفس السيرفر، بيكون في وكيل (agent) خفيف اسمه Filebeat (جزء من عائلة Beats). وظيفته يراقب ملف
error.logوأي سطر جديد بينضاف، بياخده فوراً وببعته لـ Logstash. - Logstash يعالج وينظف: بيستقبل Logstash السطر الخام. هنا بتبلش عملية “الطبخ”. ممكن يستخدم فلاتر مثل “grok” عشان يفصص السطر ويفهم أجزاءه (مثل التاريخ، مستوى الخطأ، الرسالة، عنوان IP…). بعدها بحوله لصيغة JSON مرتبة.
- Elasticsearch يخزن ويفهرس: بيستلم Elasticsearch كائن الـ JSON المرتب من Logstash، وبخزنه وبفهرسه فوراً. الآن صار السجل جاهز للبحث.
- Kibana يعرض ويحلل: أنت، يا “أبو عمر” المطور، بتفتح متصفحك على واجهة Kibana. بتكتب في شريط البحث “level:error AND status:500″، وفي أقل من ثانية، بيعرضلك Kibana كل الأخطاء من نوع 500 اللي صارت في كل النظام، مع رسوم بيانية بتوضحلك من أي خدمة اجت ومتى صارت.
شفت الفرق؟ بدل ما تبحث عن إبرة في كومة قش، صار عندك مغناطيس ضخم بيجذبلك كل الإبر اللي بدك إياها فوراً.
مثال عملي: كيف نجهز Logstash لمعالجة سجلات Nginx؟
الكلام النظري حلو، بس خلينا نشوف شوية كود. لنفترض عندك سجلات خادم الويب Nginx بالصيغة الافتراضية. السطر الواحد بيكون شكله هيك:
127.0.0.1 - - [10/Oct/2023:13:55:36 +0000] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0"
بدون معالجة، هذا السطر رح يدخل على Elasticsearch ككتلة نصية واحدة، والبحث فيه صعب. هنا يأتي دور Logstash. بنعمل ملف إعدادات بسيط nginx.conf لـ Logstash:
# /etc/logstash/conf.d/nginx.conf
input {
# Logstash يستمع للبيانات القادمة من Filebeat على هذا المنفذ
beats {
port => 5044
}
}
filter {
# إذا كان السجل قادم من ملف سجلات Nginx
if [fileset][module] == "nginx" and [fileset][name] == "access" {
# استخدم فلتر grok لتفصيص السجل
grok {
match => { "message" => "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} [%{HTTPDATE:timestamp}] "%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) %{QS:referrer} %{QS:agent}" }
}
# حول حقل التاريخ إلى صيغة يفهمها Elasticsearch
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp"
}
# استخرج معلومات الموقع الجغرافي من IP العميل
geoip {
source => "clientip"
}
}
}
output {
# أرسل النتيجة النهائية إلى Elasticsearch
elasticsearch {
hosts => ["http://localhost:9200"]
index => "nginx-logs-%{+YYYY.MM.dd}"
}
}
شرح الكود السابق:
- Input: نخبر Logstash أن يستمع للبيانات القادمة من Filebeat على المنفذ 5044.
- Filter: هذا هو الجزء الأهم.
- نستخدم
grokمع نمط معين لتحليل سطر سجل Nginx. كل جزء مثل%{IPORHOST:clientip}يعني “ابحث عن شيء يشبه الـ IP أو اسم المضيف، وخزن قيمته في حقل جديد اسمهclientip“. - نستخدم فلتر
dateلتحويل صيغة التاريخ في السجل إلى الصيغة القياسية@timestampالتي يعتمدها ELK. - نستخدم فلتر
geoip(وهذا سحر بحد ذاته) ليقوم Logstash تلقائياً بأخذ حقلclientipوالبحث في قاعدة بيانات داخلية لتحديد البلد والمدينة والإحداثيات الجغرافية لهذا الـ IP!
- نستخدم
- Output: نرسل الوثيقة (Document) المعالجة والمنظمة إلى خادم Elasticsearch، ونطلب منه أن يضعها في فهرس (index) يومي (مثلاً
nginx-logs-2023.10.26). هذا يسهل إدارة البيانات وحذف القديم منها.
نصائح من خبرة أبو عمر
بعد سنوات من التعامل مع ELK، تعلمت كم شغلة بالطريقة الصعبة. خذوا هالنصائح العملية اللي رح توفر عليكم وقت وجهد:
نصيحة 1: ابدأ بالأساسيات ثم توسع
لا تحاول من أول يوم تجمع سجلات من كل الأنظمة في الشركة. ابدأ بتطبيق واحد مهم تعاني من مشاكله. جهز الـ Stack، اجمع سجلاته، تعلم كيف تبحث في Kibana وتعمل لوحة معلومات بسيطة. لما تتقن العملية وتشوف الفائدة، وقتها توسع لباقي الأنظمة. “شوي شوي بتوصل”.
نصيحة 2: السجلات المنظمة (Structured Logging) هي المستقبل
فلتر grok قوي، ولكنه مثل “الترقيع”. الحل الأمثل هو أن تجعل تطبيقاتك تكتب السجلات بصيغة منظمة من الأصل، وأفضل صيغة هي JSON. بدلاً من أن يكتب تطبيقك سطراً كهذا:
ERROR: Failed to process payment for user 123. Reason: Insufficient funds.
اجعله يكتب كائن JSON:
{
"timestamp": "2023-10-26T10:30:00Z",
"level": "ERROR",
"message": "Failed to process payment",
"context": {
"userId": 123,
"reason": "Insufficient funds",
"transactionId": "txn_abcdef12345"
}
}
هذا يغنيك عن الحاجة لـ grok تماماً. Logstash و Elasticsearch يفهمون JSON بشكل أصلي، وستحصل على حقول مفصلة وجاهزة للبحث والفلترة بدون أي مجهود إضافي.
نصيحة 3: انتبه للموارد
مكدس ELK، خصوصاً Elasticsearch، يمكن أن يكون شرهاً للموارد (CPU, RAM, Disk). خطط جيداً لحجم البيانات التي ستجمعها ومدة الاحتفاظ بها. استخدم أدوات مثل Curator لحذف الفهارس القديمة تلقائياً. لا تجمع كل شيء، اجمع فقط ما تحتاجه.
نصيحة 4: لا تنسَ البدائل
ELK هو الخيار الأشهر والأقوى في العالم مفتوح المصدر، ولكنه ليس الوحيد. من الجيد أن تعرف عن البدائل مثل Graylog (أسهل في الإعداد المبدئي) أو مكدس Grafana Loki (مصمم ليتكامل بشكل رائع مع Prometheus ومناسب جداً لبيئة Kubernetes).
الخلاصة: من كومة قش إلى مكتبة منظمة
في النهاية يا جماعة، الاستثمار في نظام تسجيل مركزي مثل ELK ليس رفاهية، بل هو ضرورة قصوى لأي مشروع برمجي جاد. هو الفرق بين أن تقضي ليلتك في تخبيط عشوائي ويأس، وبين أن تجد سبب المشكلة في 30 ثانية وأنت تشرب فنجان قهوتك. ☕
نعم، الإعداد الأولي يحتاج بعض الجهد والتعلم، لكن العائد على هذا الاستثمار هائل. أنت لا تبني مجرد أداة، بل تبني ثقافة جديدة في فريقك: ثقافة الاعتماد على البيانات، سرعة الاستجابة للمشاكل، والرؤية الواضحة لما يحدث داخل أنظمتك.
فيا خوي المبرمج، ما تخلوا السجلات تهزمكم. سيطروا عليها، حولوها من عبء إلى أقوى سلاح في ترسانتكم. 👍