تسجيل الدخول في تطبيقات TypeScript: أفضل الممارسات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تحتاج إلى التسجيل (Logging) في TypeScript؟

التسجيل (Logging) ليس مجرد تسجيل رسائل في وحدة التحكم. في تطبيقات TypeScript الحديثة (تطبيقات الخادم على Node.js، تطبيقات العميل على React/Angular أو مشاريع full-stack) يصبح التسجيل أداة حاسمة لتصحيح الأخطاء والمراقبة وتحليل الأداء. بدون تسجيل عالي الجودة، يضيع المطورون ساعات في إعادة إنتاج الأخطاء، ولا يستطيع مهندسو DevOps تحديد سبب العطل في بيئة الإنتاج بسرعة.

TypeScript، كطبقة فوقية على JavaScript، يضيف كتابة صارمة (strict typing)، مما يسمح بإنشاء أنظمة تسجيل أكثر موثوقية وقابلية للتنبؤ. في هذه المقالة، سنستعرض أفضل الممارسات التي ستساعدك على تنظيم تسجيل فعال في مشاريع TypeScript.



المبادئ الأساسية للتسجيل (Logging)

مستويات التسجيل (Logging Levels)

الاستخدام الصحيح لمستويات التسجيل هو أساس أي نظام مراقبة. في TypeScript، من المعتاد استخدام المستويات التالية (حسب الأهمية المتزايدة):

  • debug — معلومات تصحيح أخطاء مفصلة (للتطوير فقط);
  • info — رسائل معلوماتية قياسية (بدء تشغيل الخادم، الطلبات);
  • warn — تحذيرات (مشاكل غير حرجة);
  • error — أخطاء تتطلب الانتباه;
  • fatal — أخطاء حرجة تؤدي إلى إيقاف التطبيق.

مثال على إعداد المستويات باستخدام مكتبة Winston:

import winston from 'winston';

const logger = winston.createLogger({ level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', format: winston.format.json(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'error.log', level: 'error' }), ],});

logger.info('الخادم يعمل على المنفذ 3000');logger.warn('الذاكرة قريبة من الحد الأقصى');logger.error('خطأ في الاتصال بقاعدة البيانات');


السجلات المنظمة (Structured Logs)

تجنب رسائل السلسلة النصية البسيطة. استخدم السجلات المنظمة مع معلومات السياق (تنسيق JSON). هذا يبسط البحث والتحليل في أنظمة مثل ELK أو Grafana.

// سيءlogger.info(`المستخدم ${userId} قام بالإجراء ${action}`);

// جيدlogger.info('إجراء المستخدم', { userId: userId, action: action, timestamp: new Date().toISOString(), ip: request.ip,});

هذا النهج يسمح بتصفية السجلات حسب الحقول وإنشاء الرسوم البيانية.



أفضل الممارسات لـ TypeScript

استخدام TypeScript لكتابة (Typing) السجلات

يتيح TypeScript تعريف واجهات (interfaces) لسياق السجلات، مما يمنع الأخطاء العشوائية في أسماء الحقول:

interface LogContext {  userId: string;  action: string;  durationMs: number;  success: boolean;}

function logUserAction(context: LogContext): void { logger.info('إجراء المستخدم', context);}

// سيتحقق المترجم من أن جميع الحقول قد تم تمريرها بشكل صحيحlogUserAction({ userId: '123', action: 'login', durationMs: 150, success: true,});


تجنب تسجيل البيانات الحساسة

لا تقم أبدًا بتسجيل كلمات المرور أو الرموز المميزة (tokens) أو أرقام بطاقات الائتمان أو البيانات الشخصية (GDPR). استخدم أدوات مساعدة للإخفاء (masking):

function sanitizeLogData(data: Record<string, unknown>): Record<string, unknown> {  const sensitiveFields = ['password', 'token', 'ssn'];  const sanitized = { ...data };  for (const field of sensitiveFields) {    if (sanitized[field]) {      sanitized[field] = '***';    }  }  return sanitized;}

logger.info('تسجيل مستخدم جديد', sanitizeLogData(userData));


التسجيل غير المتزامن (Async Logging) والأداء

في التطبيقات عالية التحميل، يمكن أن يؤدي التسجيل المتزامن إلى إبطاء العمل. استخدم وسائل النقل غير المتزامنة (على سبيل المثال، winston يدعم التخزين المؤقت (buffering)).

المدونات

توصيات الكتب