logContent = shell_exec("tail -n {$logLines} " . escapeshellarg($logPath)); // Use tail output to check for warnings/errors (avoid file() which loads entire file into memory) $recentLines = explode("\n", $this->logContent ?? ''); $messages = []; if (collect($recentLines)->contains(fn ($line) => stripos($line, 'WARNING') !== false)) { $messages[] = 'Warning detected in the recent log output'; } if (collect($recentLines)->contains(fn ($line) => stripos($line, 'ERROR') !== false)) { $messages[] = 'Error detected in the recent log output'; } if (collect($recentLines)->contains(fn ($line) => stripos($line, 'CRITICAL') !== false)) { $messages[] = 'Critical issue detected in the recent log output'; } if (collect($recentLines)->contains(fn ($line) => stripos($line, 'ALERT') !== false)) { $messages[] = 'Alert detected in the recent log output - IMMEDIATE ACTION REQUIRED'; } $this->message = implode('
', $messages); } // Get disk usage $free = disk_free_space("/"); $total = disk_total_space("/"); $used = $total - $free; $percent = $total > 0 ? round(($used / $total) * 100, 1) : 0; // Determine disk usage color class if ($percent > 90) { $this->diskUsageClass = 'text-red-500'; } elseif ($percent > 75) { $this->diskUsageClass = 'text-orange-500'; } else { $this->diskUsageClass = 'text-green-500'; } $this->diskUsage = sprintf( '%s used of %s (%.1f%%)', $this->formatBytes($used), $this->formatBytes($total), $percent ); // Get RAM memory information $meminfo = file_get_contents('/proc/meminfo'); preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matchesTotal); preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $matchesAvailable); $totalKb = $matchesTotal[1] ?? 0; $availableKb = $matchesAvailable[1] ?? 0; $usedKb = $totalKb - $availableKb; $percentRam = $totalKb > 0 ? round(($usedKb / $totalKb) * 100, 1) : 0; $this->availableRam = sprintf( '%s used of %s (%.1f%%)', $this->formatBytes($usedKb * 1024), $this->formatBytes($totalKb * 1024), $percentRam ); if ($percentRam > 90) { $this->availableRamClass = 'text-red-500'; } elseif ($percentRam > 75) { $this->availableRamClass = 'text-orange-500'; } else { $this->availableRamClass = 'text-green-500'; } // Check running queue workers $queueWorkers = []; exec("ps aux | grep 'artisan queue:work' | grep -v grep", $output); foreach ($output as $line) { // Parse $line for more details $queueWorkers[] = $line; } $this->queueWorkers = $queueWorkers; $this->queueWorkersCount = count($queueWorkers); // Check Reverb server connection (example: check if port is open) $reverbPort = env('REVERB_PORT', 6001); // Check Reverb server connection $reverbConnected = false; $connection = @fsockopen('127.0.0.1', $reverbPort, $errno, $errstr, 1); if ($connection) { $reverbConnected = true; fclose($connection); } $this->reverbConnected = $reverbConnected; } // Helper to format bytes public function formatBytes($bytes, $precision = 2) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $bytes = max($bytes, 0); $pow = $bytes > 0 ? floor(log($bytes) / log(1024)) : 0; $pow = min($pow, count($units) - 1); $bytes /= (1 << (10 * $pow)); return round($bytes, $precision) . ' ' . $units[$pow]; } public function downloadLog() { $logPath = storage_path('logs/laravel-' . date('Y-m-d') . '.log'); if (!file_exists($logPath)) { $logPath = storage_path('logs/laravel.log'); } if (file_exists($logPath)) { return response()->download($logPath, 'laravel-' . date('Y-m-d') . '.log'); } session()->flash('error', 'Log file not found'); } public function render() { $layout = Auth::check() ? 'app-layout' : 'guest-layout'; return view('livewire.admin.log', [ 'layout' => $layout, 'logContent' => $this->logContent, 'message' => $this->message, 'diskUsage' => $this->diskUsage, 'diskUsageClass' => $this->diskUsageClass, 'availableRam' => $this->availableRam, 'availableRamClass' => $this->availableRamClass, 'queueWorkers' => $this->queueWorkers, 'queueWorkersCount' => $this->queueWorkersCount, 'reverbConnected' => $this->reverbConnected, ]); } }