twig = $twig; } public function show(Request $request, Response $response, $args) { $id = $args['id']; // Получаем информацию о сервере $stmt = $this->pdo->prepare(" SELECT s.*, sg.name as group_name, sg.icon as group_icon, sg.color as group_color FROM servers s LEFT JOIN server_groups sg ON s.group_id = sg.id WHERE s.id = :id "); $stmt->execute([':id' => $id]); $server = $stmt->fetch(); if (!$server) { return $response->withHeader('Location', '/servers')->withStatus(302); } // Получаем период для выборки метрик $period = $request->getQueryParams()['period'] ?? '24h'; // Определяем интервал времени в зависимости от периода $interval = match($period) { '7d' => 'INTERVAL 7 DAY', '30d' => 'INTERVAL 30 DAY', default => 'INTERVAL 24 HOUR' }; // Получаем последние метрики для этого сервера $stmt = $this->pdo->prepare(" SELECT sm.value, mn.name, mn.unit, sm.created_at FROM server_metrics sm JOIN metric_names mn ON sm.metric_name_id = mn.id WHERE sm.server_id = :id AND sm.created_at >= DATE_SUB(NOW(), {$interval}) ORDER BY sm.created_at DESC "); $stmt->execute([':id' => $id]); $metrics = $stmt->fetchAll(); // Группируем метрики по типу (CPU, RAM, Disk) $groupedMetrics = []; foreach ($metrics as $metric) { $metricName = $metric['name']; if (!isset($groupedMetrics[$metricName])) { $groupedMetrics[$metricName] = []; } $groupedMetrics[$metricName][] = $metric; } // Получаем текущие пороговые значения для сервера $stmt = $this->pdo->prepare(" SELECT mt.warning_threshold, mt.critical_threshold, mt.duration, mn.name FROM metric_thresholds mt JOIN metric_names mn ON mt.metric_name_id = mn.id WHERE mt.server_id = :id "); $stmt->execute([':id' => $id]); $existingThresholds = []; foreach ($stmt->fetchAll() as $threshold) { $existingThresholds[$threshold['name']] = [ 'warning' => $threshold['warning_threshold'], 'critical' => $threshold['critical_threshold'], 'duration' => $threshold['duration'] ]; } // Получаем все типы метрик $stmt = $this->pdo->query("SELECT id, name, unit FROM metric_names WHERE name NOT LIKE '%\_proc' ORDER BY name"); $allMetricTypes = $stmt->fetchAll(); // Получаем список сервисов $stmt = $this->pdo->prepare(" SELECT service_name, status, load_state, active_state, sub_state FROM service_status WHERE server_id = :server_id ORDER BY service_name "); $stmt->execute([':server_id' => $id]); $allServices = $stmt->fetchAll(); // Получаем список сервисов для мониторинга из конфигурации агента $stmt = $this->pdo->prepare(" SELECT monitor_services FROM agent_configs WHERE server_id = :server_id "); $stmt->execute([':server_id' => $id]); $agentConfig = $stmt->fetch(); $monitorServices = []; if ($agentConfig && !empty($agentConfig['monitor_services'])) { $monitorServices = json_decode($agentConfig['monitor_services'], true) ?? []; } $templateData = [ 'title' => 'Сервер: ' . $server['name'], 'server' => $server, 'metrics' => $groupedMetrics, 'allMetricTypes' => $allMetricTypes, 'existingThresholds' => $existingThresholds, 'allServices' => $allServices, 'monitorServices' => $monitorServices, 'period' => $period, 'request' => $request->getQueryParams() ]; return $this->twig->render($response, 'servers/detail.twig', $templateData); } public function saveThresholds(Request $request, Response $response, $args) { $id = $args['id']; $params = $request->getParsedBody(); // Получаем все типы метрик $stmt = $this->pdo->query("SELECT id, name FROM metric_names WHERE name NOT LIKE '%\_proc' ORDER BY name"); $metricTypes = $stmt->fetchAll(); // Удаляем старые пороги для этого сервера $stmt = $this->pdo->prepare("DELETE FROM metric_thresholds WHERE server_id = :server_id"); $stmt->execute([':server_id' => $id]); // Добавляем новые пороги $insertStmt = $this->pdo->prepare(" INSERT INTO metric_thresholds (server_id, metric_name_id, warning_threshold, critical_threshold, duration) VALUES (:server_id, :metric_name_id, :warning_threshold, :critical_threshold, :duration) "); foreach ($metricTypes as $metricType) { $warning = $params[$metricType['name'] . '_warning'] ?? ''; $critical = $params[$metricType['name'] . '_critical'] ?? ''; $duration = $params[$metricType['name'] . '_duration'] ?? 0; if ($warning !== '' && $critical !== '') { $insertStmt->execute([ ':server_id' => $id, ':metric_name_id' => $metricType['id'], ':warning_threshold' => $warning, ':critical_threshold' => $critical, ':duration' => $duration ]); } } // Возвращаемся на страницу сервера return $response->withHeader('Location', "/servers/{$id}")->withStatus(302); } public function saveServices(Request $request, Response $response, $args) { $id = $args['id']; $params = $request->getParsedBody(); // Получаем список сервисов для мониторинга $services = $params['services'] ?? []; if (is_string($services)) { $services = json_decode($services, true) ?? []; } // Обновляем конфигурацию агента $stmt = $this->pdo->prepare(" INSERT INTO agent_configs (server_id, interval_seconds, monitor_services, enabled) VALUES (:server_id, 60, :services, TRUE) ON DUPLICATE KEY UPDATE monitor_services = VALUES(monitor_services), updated_at = CURRENT_TIMESTAMP "); $stmt->execute([ ':server_id' => $id, ':services' => json_encode($services) ]); // Возвращаемся на страницу сервера return $response->withHeader('Location', "/servers/{$id}?tab=services")->withStatus(302); } }