Laravel المتقدم

Laravel Pulse والمراقبة

15 دقيقة الدرس 29 من 40

Laravel Pulse والمراقبة

Laravel Pulse هو لوحة تحكم لمراقبة أداء التطبيق في الوقت الفعلي توفر رؤى حول صحة تطبيقك وعقبات الأداء ونشاط المستخدم. يلتقط مقاييس مثل الاستعلامات البطيئة والاستثناءات وأداء قائمة الانتظار واستخدام موارد الخادم.

لماذا Pulse؟ على عكس أدوات المراقبة الخارجية، تم بناء Pulse مباشرة في Laravel، مما يوفر رؤى بدون تكوين مع لوحات تحكم جميلة في الوقت الفعلي يمكن الوصول إليها من داخل تطبيقك.

تثبيت وتكوين Pulse

<?php // تثبيت Pulse // composer require laravel/pulse // نشر التكوين و migrations // php artisan vendor:publish --provider="Laravel\Pulse\PulseServiceProvider" // php artisan migrate // config/pulse.php return [ 'domain' => env('PULSE_DOMAIN'), 'path' => env('PULSE_PATH', 'pulse'), 'enabled' => env('PULSE_ENABLED', true), 'storage' => [ 'driver' => env('PULSE_STORAGE_DRIVER', 'database'), 'database' => [ 'connection' => env('PULSE_DB_CONNECTION', null), 'chunk' => 1000, ], ], 'ingest' => [ 'driver' => env('PULSE_INGEST_DRIVER', 'storage'), 'buffer' => env('PULSE_INGEST_BUFFER', 5000), 'trim' => [ 'keep' => env('PULSE_INGEST_TRIM_KEEP', '7 days'), ], ], 'recorders' => [ Pulse\Recorders\CacheInteractions::class => [ 'enabled' => env('PULSE_CACHE_INTERACTIONS_ENABLED', true), 'sample_rate' => env('PULSE_CACHE_INTERACTIONS_SAMPLE_RATE', 1), ], Pulse\Recorders\Exceptions::class => [ 'enabled' => env('PULSE_EXCEPTIONS_ENABLED', true), 'sample_rate' => env('PULSE_EXCEPTIONS_SAMPLE_RATE', 1), 'ignore' => [ // الاستثناءات المراد تجاهلها ], ], Pulse\Recorders\Queues::class => [ 'enabled' => env('PULSE_QUEUES_ENABLED', true), 'sample_rate' => env('PULSE_QUEUES_SAMPLE_RATE', 1), ], Pulse\Recorders\SlowQueries::class => [ 'enabled' => env('PULSE_SLOW_QUERIES_ENABLED', true), 'sample_rate' => env('PULSE_SLOW_QUERIES_SAMPLE_RATE', 1), 'threshold' => env('PULSE_SLOW_QUERIES_THRESHOLD', 1000), ], Pulse\Recorders\Servers::class => [ 'enabled' => env('PULSE_SERVERS_ENABLED', true), ], Pulse\Recorders\UserRequests::class => [ 'enabled' => env('PULSE_USER_REQUESTS_ENABLED', true), 'sample_rate' => env('PULSE_USER_REQUESTS_SAMPLE_RATE', 1), ], Pulse\Recorders\UserJobs::class => [ 'enabled' => env('PULSE_USER_JOBS_ENABLED', true), 'sample_rate' => env('PULSE_USER_JOBS_SAMPLE_RATE', 1), ], ], ]; // الوصول إلى لوحة التحكم على /pulse // الحماية باستخدام middleware في routes Route::get('/pulse', function () { return redirect('/pulse'); })->middleware(['auth', 'admin']);

نظرة عامة على لوحة تحكم Pulse

تتضمن لوحة تحكم Pulse الافتراضية عدة بطاقات تعرض مقاييس في الوقت الفعلي:

<?php // بطاقات لوحة التحكم الافتراضية: // 1. موارد الخادم - استخدام CPU والذاكرة والقرص // 2. الاستعلامات البطيئة - استعلامات قاعدة البيانات التي تتجاوز الحد // 3. الاستثناءات - أخطاء التطبيق وتتبع المكدس // 4. إنتاجية قائمة الانتظار - الوظائف المعالجة في الدقيقة // 5. أداء التخزين المؤقت - نسب الإصابة/الفشل // 6. طلبات المستخدم - المستخدمون الأكثر نشاطًا // 7. المسارات البطيئة - طلبات HTTP حسب المدة // تخصيص لوحة التحكم في resources/views/vendor/pulse/dashboard.blade.php <x-pulse> <livewire:pulse.servers cols='4' /> <livewire:pulse.usage cols='4' rows='2' /> <livewire:pulse.queues cols='4' /> <livewire:pulse.cache cols='4' /> <livewire:pulse.slow-queries cols='8' /> <livewire:pulse.exceptions cols='8' /> <livewire:pulse.slow-requests cols='8' /> <livewire:pulse.slow-jobs cols='8' /> </x-pulse>
تأثير الأداء: تم تصميم Pulse ليكون له حد أدنى من التكلفة الإضافية. استخدم معدلات العينة لتقليل جمع البيانات إذا لزم الأمر. بالنسبة للمواقع ذات حركة المرور العالية، فكر في استخدام Redis لتخزين Pulse بدلاً من قاعدة البيانات.

إنشاء بطاقات Pulse مخصصة

<?php // إنشاء مسجل مخصص // app/Pulse/Recorders/ApiCallRecorder.php namespace App\Pulse\Recorders; use Laravel\Pulse\Facades\Pulse; use Illuminate\Http\Client\Events\ResponseReceived; class ApiCallRecorder { public function register() { Event::listen(ResponseReceived::class, function ($event) { $duration = $event->response->handlerStats()['total_time'] ?? 0; Pulse::record( type: 'api_call', key: $event->request->url(), value: $duration * 1000, // التحويل إلى ميلي ثانية )->count()->avg()->max(); }); } } // إنشاء مكون بطاقة Livewire مخصص // app/Livewire/Pulse/ApiCalls.php namespace App\Livewire\Pulse; use Laravel\Pulse\Livewire\Card; use Laravel\Pulse\Facades\Pulse; use Livewire\Attributes\Lazy; #[Lazy] class ApiCalls extends Card { public function render() { [$apiCalls, $time] = $this->remember( fn () => Pulse::values('api_call') ->map(function ($item) { return (object) [ 'url' => $item->key, 'count' => $item->count, 'avg_duration' => round($item->avg, 2), 'max_duration' => round($item->max, 2), ]; }), ); return view('livewire.pulse.api-calls', [ 'apiCalls' => $apiCalls, 'time' => $time, ]); } } // إنشاء عرض: resources/views/livewire/pulse/api-calls.blade.php <x-pulse::card :cols="$cols" :rows="$rows" :class="$class"> <x-pulse::card-header name="استدعاءات API"> <x-slot:icon> <x-pulse::icons.signal /> </x-slot:icon> </x-pulse::card-header> <x-pulse::scroll :expand="$expand"> @if ($apiCalls->isEmpty()) <x-pulse::no-results /> @else <div class="grid gap-3"> @foreach ($apiCalls as $call) <div class="flex items-center gap-3"> <div class="flex-1 truncate">{{ $call->url }}</div> <div class="text-gray-500"> {{ $call->count }} استدعاء </div> <div class="text-gray-500"> متوسط: {{ $call->avg_duration }}مللي ثانية </div> </div> @endforeach </div> @endif </x-pulse::scroll> </x-pulse::card> // تسجيل المسجل في config/pulse.php 'recorders' => [ App\Pulse\Recorders\ApiCallRecorder::class => [ 'enabled' => true, ], ],

تسجيل المقاييس المخصصة

<?php use Laravel\Pulse\Facades\Pulse; // تسجيل عداد بسيط Pulse::record( type: 'user_login', key: auth()->id(), )->count(); // التسجيل مع قيمة (للمتوسطات، الحد الأقصى، إلخ) Pulse::record( type: 'file_upload', key: $file->name, value: $file->size, )->count()->avg()->max(); // التسجيل مع الطابع الزمني Pulse::record( type: 'payment_processed', key: $payment->id, value: $payment->amount, timestamp: $payment->processed_at, )->sum(); // مثال: تتبع استخدام الميزة class FeatureUsageMiddleware { public function handle($request, Closure $next) { $response = $next($request); // تسجيل استخدام الميزة if (auth()->check()) { Pulse::record( type: 'feature_usage', key: $request->route()->getName(), )->count(); } return $response; } } // مثال: تتبع فعالية التخزين المؤقت Cache::macro('rememberWithPulse', function ($key, $ttl, $callback) { $hit = Cache::has($key); Pulse::record( type: 'cache_access', key: $hit ? 'hit' : 'miss', )->count(); return Cache::remember($key, $ttl, $callback); });
الاحتفاظ بالبيانات: يخزن Pulse المقاييس الأولية لمدة 7 أيام افتراضيًا. للتحليلات طويلة المدى، قم بتصدير البيانات إلى منصة تحليلات مخصصة. استخدم تكوين التقليم لموازنة احتياجات التخزين والاحتفاظ.

مراقبة الاستعلامات البطيئة والتحسين

<?php // تكوين حد الاستعلام البطيء في config/pulse.php Pulse\Recorders\SlowQueries::class => [ 'enabled' => true, 'threshold' => 1000, // مللي ثانية ], // عرض الاستعلامات البطيئة في لوحة التحكم // يلتقط Pulse تلقائيًا: // - استعلام SQL // - وقت التنفيذ // - الموقع (الملف والسطر) // - التكرار // مثال على سير عمل التحسين: // 1. تحديد الاستعلام البطيء في لوحة تحكم Pulse // 2. تحليل الاستعلام وخطة التنفيذ DB::enableQueryLog(); User::with('posts.comments')->get(); dd(DB::getQueryLog()); // 3. إضافة الفهارس المناسبة Schema::table('posts', function (Blueprint $table) { $table->index(['user_id', 'created_at']); }); // 4. استخدام التحميل المسبق لتقليل استعلامات N+1 // قبل (مشكلة N+1) $users = User::all(); foreach ($users as $user) { echo $user->posts->count(); // استعلام منفصل لكل مستخدم } // بعد (محسّن) $users = User::withCount('posts')->get(); foreach ($users as $user) { echo $user->posts_count; // استعلام واحد مع join } // 5. التحقق من التحسين في لوحة تحكم Pulse

تتبع الاستثناءات وتصحيح الأخطاء

<?php // يلتقط Pulse تلقائيًا جميع الاستثناءات // العرض في لوحة تحكم Pulse مع: // - نوع الاستثناء والرسالة // - تتبع المكدس // - تكرار الحدوث // - الطوابع الزمنية الأولى والأخيرة // تجاهل استثناءات معينة Pulse\Recorders\Exceptions::class => [ 'enabled' => true, 'ignore' => [ Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class, Illuminate\Auth\AuthenticationException::class, ], ], // إضافة سياق للاستثناءات try { $result = $this->processPayment($order); } catch (PaymentException $e) { Pulse::record( type: 'payment_failure', key: $order->id, )->count(); report($e); throw $e; } // مراقبة اتجاهات الاستثناءات // استخدام بطاقة مخصصة لتتبع معدلات الاستثناء بمرور الوقت
تمرين 1: قم بتثبيت Laravel Pulse وتكوينه لتطبيقك. أنشئ بطاقة مخصصة تتتبع معدلات تسجيل المستخدم في الساعة. اعرض إجمالي التسجيلات وساعات الذروة والاتجاهات.
تمرين 2: ابنِ مسجلاً مخصصًا يراقب أوقات استجابة API الخارجية. أنشئ بطاقة Pulse تعرض واجهات API الأبطأ ومتوسط أوقات الاستجابة ومعدلات الفشل. نفذ التنبيه عندما تتجاوز واجهات API الحدود.
تمرين 3: استخدم Pulse لتحديد وتحسين أبطأ 5 استعلامات في تطبيق موجود. وثق أوقات الاستعلام الأصلية واستراتيجيات التحسين المطبقة (الفهارس، التحميل المسبق، التخزين المؤقت) وتحسينات الأداء المحققة.