هندسة الـ Logging في Laravel: من ملف نصي إلى نظام مراقبة متكامل
كثير من المشاريع تبدأ بملف laravel.log وينتهي الموضوع هناك.
سطر خطأ هنا، تحذير هناك، وأحيانًا رسالة معلوماتية.
لكن مع نمو المشروع، يتحول هذا الملف إلى كتلة نصية غير مفهومة.
المشكلة ليست في Laravel، بل في طريقة التفكير حول الـ Logging نفسه.
1) اللوق ليس للقراءة… بل للتحليل
أول خطأ شائع هو كتابة رسائل موجهة للإنسان فقط:
Log::info("User created successfully");
هذه الرسالة لا تحتوي سياق. بعد أسبوع لن تعرف: من هو المستخدم؟ من أنشأه؟ من أي IP؟ في أي بيئة؟
الأفضل هو استخدام Structured Logging:
Log::info('User created', [
'user_id' => $user->id,
'created_by' => auth()->id(),
'ip' => request()->ip(),
]);
بهذا الشكل يصبح اللوق قابلًا للبحث والتحليل لاحقًا في أي نظام تجميع Logs.
2) فهم طبقة Monolog داخل Laravel
Laravel لا يخترع نظام تسجيل خاص به. هو يعتمد على Monolog. وهذا يعني أنك لا تتعامل مع ملف نصي فقط، بل مع نظام Channels وHandlers وProcessors.
في config/logging.php ستجد مفهوم القنوات:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
]
الـ stack يسمح لك بإرسال نفس الرسالة لأكثر من قناة. وهذا مهم في الأنظمة الكبيرة.
3) فصل القنوات حسب نوع الحدث
في المشاريع المتقدمة، لا تضع كل شيء في نفس الملف. افصل:
- أخطاء النظام
- أحداث الأمان
- عمليات الدفع
- أخطاء API
مثال قناة مخصصة:
'channels' => [
'security' => [
'driver' => 'single',
'path' => storage_path('logs/security.log'),
'level' => 'warning',
],
]
الاستخدام:
Log::channel('security')->warning('Unauthorized attempt', [
'user_id' => auth()->id(),
'ip' => request()->ip(),
]);
بهذا الشكل يصبح لديك ملف مستقل للأحداث الحساسة.
4) Log Levels ليست زينة
Laravel يدعم مستويات مختلفة:
- debug
- info
- notice
- warning
- error
- critical
- alert
- emergency
استخدام المستوى الصحيح يحدد أين تذهب الرسالة، وهل يتم إرسالها لنظام مراقبة خارجي أم لا.
مثال:
Log::error('Payment failed', [
'order_id' => $order->id,
'gateway' => 'stripe',
]);
لا تستخدم error لكل شيء. التصنيف الدقيق هو ما يجعل النظام قابلًا للإدارة.
5) إضافة Context تلقائي لكل رسالة
أحيانًا تريد أن تضيف بيانات ثابتة لكل Log، مثل:
- بيئة التشغيل
- اسم السيرفر
- رقم الإصدار
يمكنك ذلك عبر Processors في Monolog.
مثال داخل config/logging.php:
'tap' => [App\Logging\CustomizeFormatter::class],
وفي الكلاس:
namespace App\Logging;
use Monolog\Formatter\JsonFormatter;
class CustomizeFormatter
{
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new JsonFormatter());
}
}
}
بهذا تتحول الرسائل إلى JSON منظم، وهو أفضل بكثير في البيئات الإنتاجية.
6) Logging في بيئة الإنتاج ليس مثل التطوير
في local:
- مستوى debug مقبول
- تفاصيل كثيرة مفيدة
في production:
- تخفيف الضجيج
- تسجيل الأخطاء الحقيقية فقط
- عدم تسريب معلومات حساسة
تعديل المستوى:
LOG_LEVEL=error
7) لا تسجل بيانات حساسة
خطأ شائع:
Log::info('Login attempt', request()->all());
هذا قد يسجل كلمات المرور أو التوكنات.
دائمًا انتقِ الحقول يدويًا:
Log::info('Login attempt', [
'email' => request('email'),
'ip' => request()->ip(),
]);
8) اللوق ليس بديلًا عن Monitoring
تسجيل الرسالة لا يعني أن أحدًا رآها.
في الأنظمة الجدية يتم ربط Laravel مع:
- خادم تجميع Logs
- أداة تنبيه
- نظام تحليل مركزي
وهنا تظهر قيمة القنوات المتعددة والـ JSON formatting.
الخلاصة
الـ Logging في Laravel ليس مجرد استدعاء Log::info(). هو طبقة كاملة يمكن تصميمها بوعي:
- تحديد القنوات
- تصنيف المستويات بدقة
- إضافة سياق منظم
- حماية البيانات الحساسة
- تهيئة البيئة الإنتاجية بشكل مختلف
عندما يصبح اللوق جزءًا من هندسة النظام، تتحول الأخطاء من مفاجآت إلى بيانات يمكن تحليلها واتخاذ قرار بناءً عليها.