التسجيل (Logging) في Laravel

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

مقدمة

يوفر Laravel خدمات تسجيل صلبة (robust) تسمح لك بتسجيل الرسائل في ملفّات، و سجّل أخطاء النظام، وحتى بتطبيق Slack لإعلام فريقك بأكمله وذلك لمساعدتك على معرفة المزيد حول ما يحدث داخل تطبيقك. يستخدم Laravel وراء الكواليس مكتبة Monolog التي توفر الدعم لمجموعة متنوعة من معالجات السجل القوية. يجعل Laravel إعداد هذه المُعالجات سهلة للغاية، ممّا يسمح لك بالتنسيق بينهم لتخصيص معالجة سجل تطبيقك.

الضبط

توجد كل إعدادات نظام تسجيل تطبيقك في ملف الإعدادات config/logging.php. يتيح لك هذا الملف إعداد قنوات سجّل التطبيق، لذا تأكد من مراجعة كل قناة من القنوات المتاحة وخياراتها. سنراجع بعض الخيارات الشائعة أدناه.

سيستخدم Laravel قناة المكدّس (stack channel) عند تسجيل الرسائل افتراضيًّا. تُستخدم قناة المكدّس (stack channel) لتجميع عدة قنوات سجلّات في قناة واحدة. لمزيد من المعلومات حول بناء المكدّسات راجع الوثائق أدناه.

ضبط اسم القناة

يُنشأ Monolog افتراضيًّا مع "اسم قناة" يطابق البيئة الحالية، مثل production أو local. لتغيير هذه القيمة، أضف الخيار name لإعدادات قناتك:
'stack' => [
    'driver' => 'stack',
    'name' => 'channel-name',
    'channels' => ['single', 'slack'],
],

برامج تشغيل القنوات المتاحة (Available Channel Drivers)

الاسم الوصف
stack مُغلّف لتيسير إنشاء قنوات "متعددة القنوات"
single قناة تسجيل واحدة قائمة على ملف أو مسار (StreamHandler)
daily برنامج تشغيل RotatingFileHandler قائم على Monolog يدور يوميًّا
slack برنامج تشغيل SlackWebhookHandler قائم على Monolog
syslog برنامج تشغيل SyslogHandler قائم على Monolog
errorlog برنامج تشغيل ErrorLogHandler قائم على Monolog
monolog برنامج تشغيل معملي (factory driver) يستطيع استخدام أي مُعالج Monolog مدعوم
custom برنامج تشغيل ينادي معملا محدّدا لإنشاء قناة

إعداد قناة Slack

تتطلب القناة slack خيار إعداد عنوان url. يجب أن يطابق هذا العنوان URL عنوان URL من webhook وارد أعددته مع فريقك Slack.

بناء مكدّسات سجلّات

يسمح لك برنامج التشغيل stack بدمج عدة قنوات في قناة سجل واحدة. فلنلقي نظرة على مثال إعداد قد تراه في تطبيق إنتاج لتوضيح كيفيّة استخدام مكدّسات السجل:
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['syslog', 'slack'],
    ],

    'syslog' => [
        'driver' => 'syslog',
        'level' => 'debug',
    ],

    'slack' => [
        'driver' => 'slack',
        'url' => env('LOG_SLACK_WEBHOOK_URL'),
        'username' => 'Laravel Log',
        'emoji' => ':boom:',
        'level' => 'critical',
    ],
],
فلنحلّل هذا الإعداد. أولًا، لاحظ أنّ قناة مُكدّسنا تجمع عبر خيارها channels قناتين أخريتين: syslog وslack. لذلك ستتاح فرصة تسجيل الرسالة لكلا القناتين عند تسجيل الرسائل.

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

لاحظ خيار الإعداد level الموجود بإعدادات القناتين syslog و slack بالمثال أعلاه. يحدد هذا الخيار "مستوى" السالة الأدنى المطلوب كي تُسجّلها القناة. يُقدّم Monolog، الذي يدعم خدمات تسجيل Laravel، جميع مستويات السجل المحددة في المواصفات RFC 5424: الطوارئ، والتنبيه، والحرجة (critical)، والخطأ (error)، والتحذير، والإشعار (notice)، والمعلومات، وتصحيح الأخطاء (debug).

فلنفترض أنّنا نسجّل الرسالة باستخدام التابع debug:
Log::debug('An informational message.');
ستكتب القناة syslog الرسالة بسجلّ النظام نظرًا لإعداداتنا؛ ولكنها لن تُرسل إلى Slack بما أنّ رسالة الخطأ ليست critical (حرجة) أو أعلى منها مستوى،. لكن إن سجّلنا رسالة emergency  (طوارئ)، ستُرسل إلى كل من سجل النظام و Slack بما أنّ مستوى الطوارئ emergency فوق عتبة المستوى الأدنى لكلا القناتين:
Log::emergency('The system is down!');
وكما ذُكر سابقا، يوفّر المُسجّل مستويات التسجيل الثمانية المحددة في المواصفات RFC 5424: الطوارئ، والتنبيه، والحرجة (critical)، والخطأ (error)، والتحذير، والإشعار (notice)، والمعلومات، وتصحيح الأخطاء (debug):
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
لذلك يمكنك مناداة أي من هذه التوابع لتسجيل الرسالة بالمستوى المناسب. ستُكتب الرسالة بقناة السجل الافتراضيّة حسب ضبطك بملف إعداداتك config/logging.php:
<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * عرض ملف المستخدم المحدّد الشخصي.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        Log::info('Showing user profile for user: '.$id);

        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

المعلومات السياقيّة

تستطيع أيضًا أن تمرّر مصفوفة من البيانات السياقية لتوابع السجل. ستُنسّق وتُعرض هذه البيانات السياقية مع رسالة السجل:
Log::info('User failed to login.', ['id' => $user->id]);

الكتابة لقنوات محددة

قد ترغب أحيانًا في تسجيل رسالة لقناة غير قناة التطبيق الافتراضية. تستطيع استخدام التابع channel على  الواجهة الساكنة Log للاسترداد والتسجيل بأي قناة محددّة في ملف إعداداتك:
Log::channel('slack')->info('Something happened!');
إذا رغبت في إنشاء مكدّس تسجيل مُؤلّف من عدّة قنوات حسب الطلب، تستطيع استخدام التابع stack:
Log::stack(['single', 'slack'])->info('Something happened!');

تخصيص قنوات Monolog متقدمة

تخصيص Monolog للقنوات

قد تحتاج في بعض الأحيان للتحكّم الكامل في كيفية إعداد Monolog لقناة موجودة. قد ترغب مثلًا في إعداد تعريف استخدام Monolog FormatterInterface مخصّص لمعالجات قناة معيّنة.

للبدء، عرّف مصفوفة tap بإعدادات القناة. يجب أن تحتوي المصفوفة tap على قائمة من الأصناف التي يجب أن تقدر على تخصيص النسخة Monolog بعد إنشائها:
'single' => [
    'driver' => 'single',
    'tap' => [App\Logging\CustomizeFormatter::class],
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
],
تكون بمجرد إعدادك للخيار tap بقناتك مستعدًا لتعريف الصنف الذي سيخصّص نسختك Monolog. يحتاج هذا الصنف لتابع واحد فقط invoke__ ، الذي يتلقى نسخة Illuminate\Log\Logger. تُوكّل النسخة Illuminate\Log\Logger جميع نداءات التابع للنسخة Monolog الأساسيّة:
<?php

namespace App\Logging;

class CustomizeFormatter
{
    /**
     * تخصيص نُسخة المُسجّل المعيّنة.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(...);
        }
    }
}
تُستبين كل أصناف "النقر" (tap) لديك من طرف حاوي الخدمات، وبالتالي ستُضاف تلقائيًا أي اعتماديّات إنشاء (constructor dependencies) تتطلبها.

إنشاء قنوات معالجة Monolog

لدى Monolog مجموعة متنوعة من المُعالجات المتاحة. في بعض الحالات، يكون نوع المُسجّل الذي تريد إنشائه مجرد برنامج تشغيل Monolog (أي Monolog driver) بنسخة من معالِج معيّن. يمكن إنشاء هذه القنوات باستخدام برنامج التشغيل monolog.

عند استخدام برنامج التشغيل monolog، يُستخدم خيار الإعداد handler لتحديد المُعالج الذي ستنشأ نسخة منه. يمكن تحديد معاملات الإنشاء التي يحتاجها المُعالج باستخدام خيار الإعداد handler_with:
'logentries' => [
    'driver'  => 'monolog',
    'handler' => Monolog\Handler\SyslogUdpHandler::class,
    'handler_with' => [
        'host' => 'my.logentries.internal.datahubhost.company.com',
        'port' => '10000',
    ],
],

منسّقو Monolog (أي Monolog Formatters)

عند استخدام برنامج التشغيل monolog ، سيُستخدم Monolog LineFormatter كمنسّق افتراضي. ولكن، تستطيع تخصيص نوع المنسّق الذي يُمرّر إلى المعالج باستخدام خيارات الإعداد formatter و formatter_with:
'browser' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\BrowserConsoleHandler::class,
    'formatter' => Monolog\Formatter\HtmlFormatter::class,
    'formatter_with' => [
        'dateFormat' => 'Y-m-d',
    ],
],
إذا كنت تستخدم مُعالج Monolog قادر على توفير منسّقه الخاص، تستطيع وضع قيمة خيار إعداد formatter على قيمته الافتراضيّة default:
'newrelic' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\NewRelicHandler::class,
    'formatter' => 'default',
],

إنشاء القنوات عبر المعامل

إن رغبت في تعريف قناة مخصّصة تمتلك فيها التحكّم الكامل في عملية إنشاء وإعداد Monolog، تستطيع تحديد نوع مُشغّل مخصّص custom في ملف إعداداتك config/logging.php. يجب على إعداداتك أن تتضمّن خيارًا via للإشارة إلى صنف المعمل التي سيُستدعى لإنشاء نسخة Monolog:
'channels' => [
    'custom' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],
أنت مستعد لتعريف الصنف التي سينشئ نسختك Monolog بمجرد تكوين القناة المخصّصة custom . يحتاج هذا الصنف إلى تابع واحد فقط: invoke__ ، والذي يجب أن يعرض النسخة Monolog:
<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * إنشاء نسخة Monolog مخصّصة.
     *
     * @param  array  $config
     * @return \Monolog\Logger
     */
    public function __invoke(array $config)
    {
        return new Logger(...);
    }
}

مصادر