Monitoring & Alerting: المراقبة والإنذار المبكر

2025-11-24 وقت القراءه : 3 دقائق

لماذا Monitoring مهم؟

ما تستنَّى المشكلة تحصل - كن استباقياً! المراقبة المستمرة تسمح لك باكتشاف المشاكل قبل ما تأثر على المستخدمين.


أدوات Monitoring في Laravel

1. Laravel Telescope (للتطوير)

bash
composer require laravel/telescope
php artisan telescope:install
php artisan migrate
php// الوصول للـ Dashboard
// http://your-app.test/telescope

Telescope يوفر:

  • تتبع جميع الـ Requests
  • مراقبة الـ Queries والـ Jobs
  • تتبع الـ Cache operations
  • مراقبة الـ Exceptions


2. Laravel Horizon (لـ Queue Monitoring)

bashcomposer require laravel/horizon
php artisan horizon:install

Dashboard: http://your-app.com/horizon


3. Application Performance Monitoring (APM)

New Relic:

bashcomposer require philkra/laravel-newrelic
env
NEW_RELIC_LICENSE_KEY=your_license_key
NEW_RELIC_APP_NAME="Laravel App"


Sentry (لتتبع الأخطاء):

bashcomposer require sentry/sentry-laravel
php artisan sentry:publish --dsn=your-dsn
php
// سيتم تتبع جميع الـ Exceptions تلقائياً
// يمكنك أيضاً إرسال events مخصصة
\Sentry\captureMessage('Something went wrong');


4. Custom Monitoring Middleware

php
// app/Http/Middleware/MonitorPerformance.php
namespace App\Http\Middleware;


use Closure;
use Illuminate\Support\Facades\Log;


class MonitorPerformance
{
    public function handle($request, Closure $next)
    {
        $startTime = microtime(true);
        $startMemory = memory_get_usage();
        
        $response = $next($request);
        
        $endTime = microtime(true);
        $endMemory = memory_get_usage();
        
        $executionTime = ($endTime - $startTime) * 1000; // milliseconds
        $memoryUsed = ($endMemory - $startMemory) / 1024 / 1024; // MB
        
        // تسجيل البيانات
        Log::channel('performance')->info('Request processed', [
            'url' => $request->fullUrl(),
            'method' => $request->method(),
            'execution_time_ms' => round($executionTime, 2),
            'memory_used_mb' => round($memoryUsed, 2),
            'status_code' => $response->status(),
        ]);
        
        // إرسال تنبيه إذا كان الطلب بطيء
        if ($executionTime > 1000) { // أكثر من ثانية
            Log::channel('slack')->warning('Slow request detected', [
                'url' => $request->fullUrl(),
                'execution_time' => $executionTime . 'ms',
            ]);
        }
        
        return $response;
    }
}


5. Health Check Endpoint

php
// routes/api.php
Route::get('/health', function () {
    $checks = [
        'database' => false,
        'redis' => false,
        'queue' => false,
    ];
    
    // فحص Database
    try {
        DB::connection()->getPdo();
        $checks['database'] = true;
    } catch (\Exception $e) {
        Log::error('Database health check failed: ' . $e->getMessage());
    }
    
    // فحص Redis
    try {
        Cache::driver('redis')->get('health_check');
        $checks['redis'] = true;
    } catch (\Exception $e) {
        Log::error('Redis health check failed: ' . $e->getMessage());
    }
    
    // فحص Queue
    try {
        $queueSize = DB::table('jobs')->count();
        $checks['queue'] = $queueSize < 1000; // تنبيه إذا Queue كبير جداً
    } catch (\Exception $e) {
        Log::error('Queue health check failed: ' . $e->getMessage());
    }
    
    $allHealthy = !in_array(false, $checks, true);
    
    return response()->json([
        'status' => $allHealthy ? 'healthy' : 'unhealthy',
        'timestamp' => now(),
        'checks' => $checks,
    ], $allHealthy ? 200 : 503);
});

6. Metrics Collection

php
// app/Services/MetricsCollector.php
namespace App\Services;


use Illuminate\Support\Facades\Redis;


class MetricsCollector
{
    public function incrementCounter(string $metric): void
    {
        Redis::incr("metrics:{$metric}:count");
    }
    
    public function recordTiming(string $metric, float $milliseconds): void
    {
        $key = "metrics:{$metric}:timings";
        Redis::lpush($key, $milliseconds);
        Redis::ltrim($key, 0, 999); // احتفظ بآخر 1000 قياس
    }
    
    public function getMetrics(string $metric): array
    {
        $count = Redis::get("metrics:{$metric}:count") ?? 0;
        $timings = Redis::lrange("metrics:{$metric}:timings", 0, -1);
        
        if (empty($timings)) {
            return [
                'count' => $count,
                'avg_time' => 0,
                'min_time' => 0,
                'max_time' => 0,
            ];
        }
        
        return [
            'count' => $count,
            'avg_time' => array_sum($timings) / count($timings),
            'min_time' => min($timings),
            'max_time' => max($timings),
        ];
    }
}
Alert Channels
php// config/logging.php
'channels' => [
    'slack' => [
        'driver' => 'slack',
        'url' => env('LOG_SLACK_WEBHOOK_URL'),
        'username' => 'Laravel Bot',
        'emoji' => ':boom:',
        'level' => 'critical',
    ],
    
    'performance' => [
        'driver' => 'daily',
        'path' => storage_path('logs/performance.log'),
        'level' => 'info',
        'days' => 14,
    ],
],
إضافة تعليق
Loading...