where('is_admin', false) ->where('is_active', true); $userFilter = $this->option('user'); if ($userFilter) { $users->where(function ($query) use ($userFilter) { $query->where('id', $userFilter) ->orWhere('username', $userFilter); }); } $users = $users->get(); if ($users->isEmpty()) { $this->info('No users found for usage collection.'); return 0; } $agent = new AgentClient; $capturedAt = now(); foreach ($users as $user) { $diskBytes = $user->getDiskUsageBytes(); $mailBytes = (int) Mailbox::where('user_id', $user->id)->sum('quota_used_bytes'); $dbBytes = $this->getDatabaseUsage($agent, $user); $bandwidthTotal = $this->getBandwidthTotal($agent, $user); $resourceStats = $this->getUserResourceStats($agent, $user); $cpuPercent = (int) round($resourceStats['cpu_percent'] ?? 0); $memoryBytes = (int) ($resourceStats['memory_bytes'] ?? 0); $diskIoTotal = (int) ($resourceStats['disk_io_total_bytes'] ?? 0); $lastBandwidthTotal = (int) UserSetting::getForUser($user->id, 'bandwidth_total_bytes', 0); $lastDiskIoTotal = (int) UserSetting::getForUser($user->id, 'disk_io_total_bytes', 0); $bandwidthDelta = $bandwidthTotal >= $lastBandwidthTotal ? $bandwidthTotal - $lastBandwidthTotal : $bandwidthTotal; $diskIoDelta = $diskIoTotal >= $lastDiskIoTotal ? $diskIoTotal - $lastDiskIoTotal : $diskIoTotal; $this->storeMetric($user->id, 'disk_bytes', $diskBytes, $capturedAt); $this->storeMetric($user->id, 'mail_bytes', $mailBytes, $capturedAt); $this->storeMetric($user->id, 'database_bytes', $dbBytes, $capturedAt); $this->storeMetric($user->id, 'bandwidth_bytes', $bandwidthDelta, $capturedAt); $this->storeMetric($user->id, 'cpu_percent', $cpuPercent, $capturedAt); $this->storeMetric($user->id, 'memory_bytes', $memoryBytes, $capturedAt); $this->storeMetric($user->id, 'disk_io_bytes', $diskIoDelta, $capturedAt); UserSetting::setForUser($user->id, 'bandwidth_total_bytes', $bandwidthTotal); UserSetting::setForUser($user->id, 'disk_io_total_bytes', $diskIoTotal); $this->line("Collected usage for {$user->username}"); } $retainDays = (int) $this->option('retain'); if ($retainDays > 0) { UserResourceUsage::where('captured_at', '<', now()->subDays($retainDays))->delete(); } return 0; } protected function getDatabaseUsage(AgentClient $agent, User $user): int { try { $result = $agent->mysqlListDatabases($user->username); $databases = $result['databases'] ?? []; $total = 0; foreach ($databases as $database) { $total += (int) ($database['size_bytes'] ?? 0); } return $total; } catch (Exception $e) { $this->warn("Failed to fetch database usage for {$user->username}: {$e->getMessage()}"); } return 0; } protected function getBandwidthTotal(AgentClient $agent, User $user): int { try { $result = $agent->send('usage.bandwidth_total', [ 'username' => $user->username, ]); if ($result['success'] ?? false) { return (int) ($result['total_bytes'] ?? 0); } } catch (Exception $e) { $this->warn("Failed to fetch bandwidth usage for {$user->username}: {$e->getMessage()}"); } return 0; } /** * @return array{cpu_percent: float, memory_bytes: int, disk_io_total_bytes: int} */ protected function getUserResourceStats(AgentClient $agent, User $user): array { try { $result = $agent->send('usage.user_resources', [ 'username' => $user->username, ]); if ($result['success'] ?? false) { return [ 'cpu_percent' => (float) ($result['cpu_percent'] ?? 0), 'memory_bytes' => (int) ($result['memory_bytes'] ?? 0), 'disk_io_total_bytes' => (int) ($result['disk_io_total_bytes'] ?? 0), ]; } } catch (Exception $e) { $this->warn("Failed to fetch CPU/memory/disk IO for {$user->username}: {$e->getMessage()}"); } return [ 'cpu_percent' => 0.0, 'memory_bytes' => 0, 'disk_io_total_bytes' => 0, ]; } protected function storeMetric(int $userId, string $metric, int $value, $capturedAt): void { UserResourceUsage::create([ 'user_id' => $userId, 'metric' => $metric, 'value' => max(0, $value), 'captured_at' => $capturedAt, ]); } }