تخطي إلى المحتوى الرئيسي

المراقبة والـ Logging في الإنتاج: ختام السلسلة

المراقبة والـ Logging في الإنتاج: ختام السلسلة

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

المحتويات

أولاً: ليه “شغال عندي” مش كفاية بعد النشر

وانت بتطور، لو حصل خطأ، بتشوفه فورًا في الـ Terminal قدامك. بعد النشر، الوضع مختلف تمامًا: السيرفر شغال في مكان تاني، وانت مش قاعد قدامه. لو مستخدم حاول يسجل دخول وفشل بسبب غريب، أو طلب أخد وقت طويل جدًا، أو الاتصال بـ MongoDB اتقطع لحظة، مفيش حد هيشوف ده غير لو جهزت نظام يسجله ليك.

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

ثانياً: Logs وMetrics وTraces: أعمدة المراقبة التلاتة

عالم المراقبة بيتقسم لتلات أنواع بيانات مختلفة، وكل واحد بيجاوب سؤال مختلف.

  • Logs: سجل نصي لأحداث حصلت، زي “المستخدم X سجل دخول” أو “فشل الاتصال بقاعدة البيانات”. بيجاوب سؤال “إيه اللي حصل بالظبط؟”
  • Metrics: أرقام بتتجمع مع الوقت، زي عدد الطلبات في الدقيقة أو زمن الاستجابة المتوسط. بتجاوب سؤال “إيه اتجاه الأداء العام؟”
  • Traces: تتبع رحلة طلب واحد بالكامل عبر أكتر من خدمة (زي Nginx فـ Express فـ MongoDB). بتجاوب سؤال “فين بالظبط الطلب ده بطّأ؟”

لمشروع بحجم الميرن ستاك بتاعنا، الـ Logs هي نقطة البداية المنطقية، وأكتر حاجة هتحتاجها يوميًا. الـ Metrics وTraces بيبقوا أهم كل ما النظام يكبر ويبقى فيه خدمات كتير بتتكلم مع بعض. هنركز النهاردة على الـ Logs.

ثالثاً: Logging حقيقي بدل console.log العشوائي

على طول مشروعنا كنا بنستخدم console.log وconsole.error عادي، وده كان كافي وقت التطوير. المشكلة إن console.log مفهوش مستويات (كله نفس الأهمية)، ومفهوش تاريخ ووقت، ومفهوش شكل منظم تقدر تبحث فيه بعدين. هنستخدم مكتبة winston، من أشهر مكتبات الـ Logging في Node.js.

const winston = require("winston");

const logger = winston.createLogger({
  level: "info",
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [new winston.transports.Console()]
});

module.exports = logger;

فاكر فكرة الـ middleware المركزي للأخطاء اللي اقترحناها في مقال الـ REST API من غير ما نكتبها بالكامل وقتها؟ دي الفرصة نبنيها فعليًا، باستخدام الـ logger الجديد بدل console.error.

const logger = require("./logger");

app.use((err, req, res, next) => {
  logger.error({
    message: err.message,
    path: req.path,
    method: req.method
  });
  res.status(500).json({ error: "حصل خطأ غير متوقع" });
});

لاحظ إن الرسالة بقت كائن منظم (path، method، message) مش نص عشوائي، وده بيسهل جدًا البحث والفلترة بعدين. وملحوظة أمان مهمة: متسجلش كلمات سر ولا توكنات الـ JWT اللي شرحناها في مقال الـ JWT جوه الـ logs أبدًا، حتى لو كانت جزء من الطلب الفاشل. الـ logs بتتخزن وبيشوفها ناس تانية غير مستخدم التطبيق.

فيه فرق جوهري بين “المعلومة موجودة” و”المعلومة وصلتك”. الـ logs لوحدها بتخزن المعلومة، بس محدش هيقراها لحد ما يحصل مشكلة ويفكر يدور فيها، يعني بعد ما تكون حصلت فعلًا. ده نفس فكرة الـ Fail Fast اللي اتكلمنا عنها في مقال الـ CI/CD، بس في بيئة الإنتاج بدل بيئة التطوير: مش كفاية إن الخطأ يتسجل في مكان ما، لازم حد يعرف بيه بأسرع وقت ممكن. عشان كده الـ logs والتنبيهات الفورية (زي اللي هنشوفها دلوقتي) بيكملوا بعض، مش بيستبدلوا بعض.

حاجة تانية تفرق كتير: استخدم مستوى الـ log المناسب، مش error لكل حاجة. winston بيدعم عدة مستويات زي info (حاجة عادية بتحصل، زي “مستخدم جديد اتسجل”)، warn (حاجة غريبة بس مش خطيرة، زي محاولة تسجيل دخول فاشلة)، وerror (حاجة اتكسرت فعليًا وتستاهل انتباه فوري). لو كل حاجة اتسجلت بمستوى error، هتلاقي نفسك بتتجاهل التنبيهات بعد فترة لأن معظمها مش فعليًا أخطاء.

رابعاً: متابعة الـ Logs على Railway فعليًا

الخبر الحلو إنك مش محتاج إعداد إضافي عشان تشوف الـ logs دي. أي حاجة بتتكتب بـ winston للـ Console بتظهر تلقائيًا في تبويب Deployments ثم Logs في لوحة تحكم Railway اللي استخدمناها في مقال النشر. تقدر تفلتر بالوقت أو تدور بكلمة معينة، وتشوف كل الأخطاء اللي حصلت وانت مش شايف السيرفر.

عادة الـ logs دي بتتمسح بعد فترة معينة حسب الباقة المجانية، فمش مكان دائم للأرشفة، لكنه كافي جدًا لاكتشاف وتصحيح مشكلة حصلت في الأيام الأخيرة.

خامساً: تتبع الأخطاء تلقائيًا

الـ Logs كويسة، لكن عندها مشكلة: إنت لازم تروح تقراها بنفسك عشان تعرف إن فيه مشكلة. أدوات تتبع الأخطاء زي Sentry بتعمل العكس: بتمسك أي خطأ لحظة ما يحصل، وتبعتلك تنبيه فورًا، من غير ما تحتاج تفتح لوحة الـ Logs كل شوية.

const Sentry = require("@sentry/node");

Sentry.init({ dsn: process.env.SENTRY_DSN });

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

سادساً: إيه اللي تراقبه فعلاً، مش كل حاجة

فخ شائع: تحاول تراقب كل رقم ممكن تقيسه، وتنتهي بلوحة تحكم مليانة أرقام محدش بيبصلها فعليًا. ركز على 3 حاجات بس في البداية.

  • معدل الأخطاء: نسبة الطلبات اللي بترجع خطأ (زي 500). لو فجأة ارتفعت، فيه حاجة اتكسرت.
  • زمن الاستجابة: قد إيه السيرفر بياخد وقت يرد. لو بدأ يبطّأ تدريجيًا، ده مؤشر مبكر قبل ما يقع تمامًا.
  • التوفر (Uptime): هل السيرفر أصلاً شغال وبيرد؟ أبسط مقياس وأهمه.

التلاتة دول بيغطوا 90% من المواقف اللي هتحتاج تتصرف فيها فعليًا. أي حاجة زيادة في البداية هتبقى تشتيت أكتر منها فايدة.

لاحظ حاجة مهمة في مقياس التوفر بالذات: لو السيرفر وقع تمامًا، winston مش هيقدر يسجل حاجة، وSentry مش هيستقبل أي تنبيه، لأن الاتنين بيشتغلوا من جوه التطبيق نفسه، ولو التطبيق مش شغال خالص مفيش حد يبعت التنبيه. عشان كده محتاج أداة بتفحص موقعك من برّه بشكل دوري، زي UptimeRobot، اللي بتدخل عندها الدومين بتاعك مرة واحدة، وهي بتبعتلك طلب كل كذا دقيقة وتنبهك فورًا لو مفيش رد. الباقة المجانية كافية جدًا لمشروع شخصي، وده الفرق بين إنك تعرف إن موقعك واقع من أداة خارجية، أو تعرف من مستخدم زعلان بعد ساعات.

سابعاً: أخطاء شائعة هتقابلك

  • تسجيل كل حاجة بمستوى info أو error واحد، فمينفعش تفرق بين حاجة عادية وحاجة خطيرة فعلًا وقت البحث.
  • تسجيل بيانات حساسة (كلمات سر، توكنات، أرقام بطاقات) في الـ logs، زي ما اتكلمنا فوق بالظبط.
  • الاعتماد على الذاكرة إنك هتفتكر تفتح لوحة الـ Logs كل يوم، من غير أي تنبيه تلقائي لما حاجة تعطل.
  • بناء نظام مراقبة معقد لمشروع لسه صغير، قبل ما يكون عندك حتى مستخدمين حقيقيين يستاهلوا المجهود ده.

ثامناً: خاتمة السلسلة

لو وصلت للمقال ده، يبقى عدّيت رحلة كاملة: بنيت قاعدة بيانات وربطتها بسيرفر، بنيت REST API حقيقي بعمليات CRUD، وصلت واجهة React بيه، حميته بتسجيل دخول حقيقي، عزلته في حاويات، فهمت إيه اللي بيحصل ورا الكواليس بـ Nginx، نشرته فعليًا على الإنترنت، أتمتت فحصه ونشره، ودلوقتي بتراقبه وهو شغال. ده مش مشروع تعليمي بس، ده دورة حياة تطبيق حقيقي من أول سطر كود لحد ما يبقى بين إيدين مستخدمين فعليين.

لو فاتك مقال في السلسلة أو عايز تراجع حاجة معينة، كل المقالات مربوطة ببعض على طول السلسلة. ولو عندك اقتراح لموضوع جديد تحب تشوفه، قولّي في التعليقات، دايمًا بسمع اقتراحاتكم.


اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

saeed aly

كاتب ومطور تقني في منصة كود التطور، يشارك المعرفة البرمجية لإثراء المحتوى العربي.

اترك رد