لماذا 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 يوفر:
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,
],
],