246 lines
8.0 KiB
PHP
Executable File
246 lines
8.0 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ServerManager\Services;
|
|
|
|
use ServerManager\Core\Database;
|
|
use ServerManager\Core\Logger;
|
|
use ServerManager\Core\App;
|
|
use ServerManager\Services\SSHService;
|
|
|
|
class MonitoringService
|
|
{
|
|
private Database $db;
|
|
private Logger $logger;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->db = Database::getInstance();
|
|
$this->logger = Logger::getInstance();
|
|
}
|
|
|
|
public function collectMetrics(int $serverId): ?array
|
|
{
|
|
$server = $this->db->fetch('SELECT * FROM servers WHERE id = ? AND status = \'active\'', [$serverId]);
|
|
|
|
if (!$server || !$server['is_active']) {
|
|
return null;
|
|
}
|
|
|
|
$server = App::getEncryption()->decryptArray($server, ['ssh_password', 'ssh_key']);
|
|
|
|
try {
|
|
$ssh = new SSHService();
|
|
|
|
if (!$ssh->connect($server, true)) {
|
|
return ['status' => 'offline'];
|
|
}
|
|
|
|
$metrics = [
|
|
'server_id' => $serverId,
|
|
'status' => 'online',
|
|
'cpu_usage' => $this->getCPUUsage($ssh),
|
|
'ram_usage' => $this->getRAMUsage($ssh),
|
|
'disk_usage' => $this->getDiskUsage($ssh),
|
|
'load_average' => $this->getLoadAverage($ssh),
|
|
'uptime' => $this->getUptime($ssh),
|
|
];
|
|
|
|
$this->saveMetrics($metrics);
|
|
|
|
$ssh->disconnect();
|
|
|
|
return $metrics;
|
|
} catch (\Throwable $e) {
|
|
$this->logger->warning("Failed to collect metrics for server {$serverId}: " . $e->getMessage());
|
|
|
|
$this->saveMetrics([
|
|
'server_id' => $serverId,
|
|
'status' => 'offline',
|
|
'cpu_usage' => 0,
|
|
'ram_usage' => 0,
|
|
'disk_usage' => 0,
|
|
'load_average' => 0,
|
|
'uptime' => '',
|
|
]);
|
|
|
|
return ['status' => 'offline'];
|
|
}
|
|
}
|
|
|
|
public function collectAllMetrics(): array
|
|
{
|
|
$servers = $this->db->fetchAll('SELECT * FROM servers WHERE status = \'active\' AND is_active = 1');
|
|
$results = [];
|
|
|
|
foreach ($servers as $server) {
|
|
$results[$server['id']] = $this->collectMetrics($server['id']);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
private function getCPUUsage(SSHService $ssh): float
|
|
{
|
|
$result = $ssh->exec("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1");
|
|
return (float) trim($result['output']);
|
|
}
|
|
|
|
private function getRAMUsage(SSHService $ssh): float
|
|
{
|
|
$result = $ssh->exec("free | grep Mem | awk '{printf \"%.2f\", $3/$2 * 100}'");
|
|
return (float) trim($result['output']);
|
|
}
|
|
|
|
private function getDiskUsage(SSHService $ssh): float
|
|
{
|
|
$result = $ssh->exec("df / | tail -1 | awk '{print $5}' | sed 's/%//'");
|
|
return (float) trim($result['output']);
|
|
}
|
|
|
|
private function getLoadAverage(SSHService $ssh): float
|
|
{
|
|
$result = $ssh->exec("cat /proc/loadavg | awk '{print $1}'");
|
|
return (float) trim($result['output']);
|
|
}
|
|
|
|
private function getUptime(SSHService $ssh): string
|
|
{
|
|
$result = $ssh->exec("uptime -p");
|
|
return trim(str_replace('up ', '', $result['output']));
|
|
}
|
|
|
|
public function saveMetrics(array $metrics): void
|
|
{
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
$this->db->insert('monitoring_history', [
|
|
'server_id' => $metrics['server_id'],
|
|
'status' => $metrics['status'],
|
|
'cpu_usage' => $metrics['cpu_usage'],
|
|
'ram_usage' => $metrics['ram_usage'],
|
|
'disk_usage' => $metrics['disk_usage'],
|
|
'load_average' => $metrics['load_average'],
|
|
'uptime' => $metrics['uptime'] ?? '',
|
|
'created_at' => $now,
|
|
]);
|
|
|
|
$this->db->query(
|
|
"UPDATE servers SET
|
|
last_check_at = ?,
|
|
current_status = ?,
|
|
cpu_usage = ?,
|
|
ram_usage = ?,
|
|
disk_usage = ?,
|
|
load_average = ?,
|
|
uptime = ?
|
|
WHERE id = ?",
|
|
[
|
|
$now,
|
|
$metrics['status'],
|
|
$metrics['cpu_usage'],
|
|
$metrics['ram_usage'],
|
|
$metrics['disk_usage'],
|
|
$metrics['load_average'],
|
|
$metrics['uptime'] ?? '',
|
|
$metrics['server_id'],
|
|
]
|
|
);
|
|
|
|
$retention = App::getConfig()['monitoring']['retention_days'] ?? 30;
|
|
$this->db->query(
|
|
"DELETE FROM monitoring_history WHERE created_at < DATE_SUB(NOW(), INTERVAL ? DAY)",
|
|
[$retention]
|
|
);
|
|
}
|
|
|
|
public function getLatestMetrics(int $serverId): ?array
|
|
{
|
|
return $this->db->fetch(
|
|
'SELECT * FROM monitoring_history WHERE server_id = ? ORDER BY created_at DESC LIMIT 1',
|
|
[$serverId]
|
|
);
|
|
}
|
|
|
|
public function getHistoricalMetrics(int $serverId, int $hours = 24): array
|
|
{
|
|
return $this->db->fetchAll(
|
|
'SELECT * FROM monitoring_history
|
|
WHERE server_id = ? AND created_at >= DATE_SUB(NOW(), INTERVAL ? HOUR)
|
|
ORDER BY created_at ASC',
|
|
[$serverId, $hours]
|
|
);
|
|
}
|
|
|
|
public function getAggregatedHistoricalMetrics(array $serverIds, int $hours = 24): array
|
|
{
|
|
if (empty($serverIds)) {
|
|
return [];
|
|
}
|
|
$placeholders = implode(',', array_fill(0, count($serverIds), '?'));
|
|
$params = $serverIds;
|
|
$params[] = $hours;
|
|
return $this->db->fetchAll(
|
|
"SELECT
|
|
DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:00') as time_bucket,
|
|
AVG(cpu_usage) as avg_cpu,
|
|
AVG(ram_usage) as avg_ram,
|
|
AVG(disk_usage) as avg_disk
|
|
FROM monitoring_history
|
|
WHERE server_id IN ({$placeholders})
|
|
AND created_at >= DATE_SUB(NOW(), INTERVAL ? HOUR)
|
|
GROUP BY time_bucket
|
|
ORDER BY time_bucket ASC",
|
|
$params
|
|
);
|
|
}
|
|
|
|
public function getDashboardStats(?array $serverIds = null): array
|
|
{
|
|
$where = '';
|
|
$params = [];
|
|
|
|
if ($serverIds !== null) {
|
|
if (empty($serverIds)) {
|
|
$serverIds = [-1];
|
|
}
|
|
$placeholders = implode(',', array_fill(0, count($serverIds), '?'));
|
|
$where = " AND s.id IN ({$placeholders})";
|
|
$params = $serverIds;
|
|
}
|
|
|
|
$totalServers = $this->db->fetch("SELECT COUNT(*) as total FROM servers s WHERE s.status = 'active'{$where}", $params);
|
|
$onlineServers = $this->db->fetch(
|
|
"SELECT COUNT(*) as total FROM servers s WHERE s.current_status = 'online' AND s.status = 'active' AND s.is_active = 1{$where}",
|
|
$params
|
|
);
|
|
$offlineServers = $this->db->fetch(
|
|
"SELECT COUNT(*) as total FROM servers s WHERE s.current_status = 'offline' AND s.status = 'active' AND s.is_active = 1{$where}",
|
|
$params
|
|
);
|
|
|
|
$avgCpu = $this->db->fetch(
|
|
"SELECT AVG(s.cpu_usage) as avg FROM servers s WHERE s.status = 'active' AND s.is_active = 1 AND s.current_status = 'online'{$where}",
|
|
$params
|
|
);
|
|
$avgRam = $this->db->fetch(
|
|
"SELECT AVG(s.ram_usage) as avg FROM servers s WHERE s.status = 'active' AND s.is_active = 1 AND s.current_status = 'online'{$where}",
|
|
$params
|
|
);
|
|
$avgDisk = $this->db->fetch(
|
|
"SELECT AVG(s.disk_usage) as avg FROM servers s WHERE s.status = 'active' AND s.is_active = 1 AND s.current_status = 'online'{$where}",
|
|
$params
|
|
);
|
|
|
|
return [
|
|
'total_servers' => (int) ($totalServers['total'] ?? 0),
|
|
'online_servers' => (int) ($onlineServers['total'] ?? 0),
|
|
'offline_servers' => (int) ($offlineServers['total'] ?? 0),
|
|
'avg_cpu' => round((float) ($avgCpu['avg'] ?? 0), 1),
|
|
'avg_ram' => round((float) ($avgRam['avg'] ?? 0), 1),
|
|
'avg_disk' => round((float) ($avgDisk['avg'] ?? 0), 1),
|
|
];
|
|
}
|
|
}
|