getRemoteServers(); foreach ($remote_servers as $server) { collect_server_resources($server); } } /** * Collect resources from a specific server */ function collect_server_resources($server) { global $db; try { $remote = new OGPRemoteLibrary( $server['agent_ip'], $server['agent_port'], $server['encryption_key'], $server['timeout'] ); // Collect system-wide resources $system_stats = $remote->get_system_resource_usage(); if ($system_stats && strpos($system_stats, '1;') === 0) { $data = parse_resource_string(substr($system_stats, 2)); store_resource_data($server['remote_server_id'], null, $data); check_system_alerts($server, $data); } // Get all game servers on this remote server $game_servers = $db->getHomesFor("remote_server_id", $server['remote_server_id']); foreach ($game_servers as $game_server) { $game_stats = $remote->get_gameserver_resource_usage($game_server['home_id']); if ($game_stats && strpos($game_stats, '1;') === 0) { $data = parse_resource_string(substr($game_stats, 2)); store_resource_data($server['remote_server_id'], $game_server['home_id'], $data); check_gameserver_alerts($server, $game_server, $data); } } } catch (Exception $e) { error_log("Resource monitoring error for server {$server['remote_server_id']}: " . $e->getMessage()); } } /** * Parse resource data string from agent */ function parse_resource_string($resource_string) { $data = array(); $pairs = explode(';', $resource_string); foreach ($pairs as $pair) { if (strpos($pair, '=') !== false) { list($key, $value) = explode('=', $pair, 2); $data[trim($key)] = trim($value); } } return $data; } /** * Store resource data in database */ function store_resource_data($remote_server_id, $home_id, $data) { global $db; // Sanitize values $cpu_usage = isset($data['cpu_usage']) ? floatval($data['cpu_usage']) : 'NULL'; $memory_usage = isset($data['memory_usage']) ? floatval($data['memory_usage']) : 'NULL'; $memory_used_mb = isset($data['memory_used_mb']) ? intval($data['memory_used_mb']) : 'NULL'; $memory_total_mb = isset($data['memory_total_mb']) ? intval($data['memory_total_mb']) : 'NULL'; $disk_usage = isset($data['disk_usage']) ? floatval($data['disk_usage']) : 'NULL'; $disk_used_mb = isset($data['disk_used_mb']) ? intval($data['disk_used_mb']) : 'NULL'; $disk_total_mb = isset($data['disk_total_mb']) ? intval($data['disk_total_mb']) : 'NULL'; $process_count = isset($data['process_count']) ? intval($data['process_count']) : 'NULL'; $network_rx_mb = isset($data['network_rx_mb']) ? intval($data['network_rx_mb']) : 'NULL'; $network_tx_mb = isset($data['network_tx_mb']) ? intval($data['network_tx_mb']) : 'NULL'; $home_id_val = $home_id ? intval($home_id) : 'NULL'; $query = "INSERT INTO ogp_resource_monitoring (remote_server_id, home_id, cpu_usage, memory_usage, memory_used_mb, memory_total_mb, disk_usage, disk_used_mb, disk_total_mb, process_count, network_rx_mb, network_tx_mb) VALUES ( " . intval($remote_server_id) . ", $home_id_val, $cpu_usage, $memory_usage, $memory_used_mb, $memory_total_mb, $disk_usage, $disk_used_mb, $disk_total_mb, $process_count, $network_rx_mb, $network_tx_mb )"; return $db->query($query); } /** * Check for system alerts */ function check_system_alerts($server, $data) { global $db; // Get active alerts for this server (system-wide) $query = "SELECT * FROM ogp_resource_alerts WHERE remote_server_id = " . intval($server['remote_server_id']) . " AND home_id IS NULL AND is_active = 1"; $alerts = $db->resultQuery($query); foreach ($alerts as $alert) { $resource_value = null; switch ($alert['alert_type']) { case 'cpu': $resource_value = isset($data['cpu_usage']) ? floatval($data['cpu_usage']) : null; break; case 'memory': $resource_value = isset($data['memory_usage']) ? floatval($data['memory_usage']) : null; break; case 'disk': $resource_value = isset($data['disk_usage']) ? floatval($data['disk_usage']) : null; break; } if ($resource_value !== null && $resource_value >= $alert['threshold_percentage']) { check_alert_duration($alert, $server, null, $resource_value); } } } /** * Check for game server alerts */ function check_gameserver_alerts($server, $game_server, $data) { global $db; // Get active alerts for this game server $query = "SELECT * FROM ogp_resource_alerts WHERE remote_server_id = ? AND home_id = ? AND is_active = 1"; $stmt = $db->prepare($query); $stmt->execute([$server['remote_server_id'], $game_server['home_id']]); $alerts = $stmt->fetchAll(); foreach ($alerts as $alert) { $resource_value = null; switch ($alert['alert_type']) { case 'cpu': $resource_value = isset($data['cpu_usage']) ? floatval($data['cpu_usage']) : null; break; case 'memory': // For game servers, we calculate percentage based on system total memory if (isset($data['memory_used_mb'])) { // Get system total memory for percentage calculation $system_query = "SELECT memory_total_mb FROM ogp_resource_monitoring WHERE remote_server_id = ? AND home_id IS NULL ORDER BY timestamp DESC LIMIT 1"; $system_stmt = $db->prepare($system_query); $system_stmt->execute([$server['remote_server_id']]); $system_memory = $system_stmt->fetch(); if ($system_memory && $system_memory['memory_total_mb'] > 0) { $resource_value = (floatval($data['memory_used_mb']) / floatval($system_memory['memory_total_mb'])) * 100; } } break; } if ($resource_value !== null && $resource_value >= $alert['threshold_percentage']) { check_alert_duration($alert, $server, $game_server, $resource_value); } } } /** * Check if alert should be triggered based on duration */ function check_alert_duration($alert, $server, $game_server, $resource_value) { global $db; // Get recent resource data to check if threshold has been exceeded for the required duration $home_condition = $game_server ? "AND home_id = ?" : "AND home_id IS NULL"; $params = [$server['remote_server_id']]; if ($game_server) { $params[] = $game_server['home_id']; } $resource_field = ''; switch ($alert['alert_type']) { case 'cpu': $resource_field = 'cpu_usage'; break; case 'memory': $resource_field = 'memory_usage'; break; case 'disk': $resource_field = 'disk_usage'; break; } $query = "SELECT timestamp, $resource_field FROM ogp_resource_monitoring WHERE remote_server_id = ? $home_condition AND timestamp >= DATE_SUB(NOW(), INTERVAL ? MINUTE) AND $resource_field >= ? ORDER BY timestamp DESC"; $params[] = $alert['duration_minutes']; $params[] = $alert['threshold_percentage']; $stmt = $db->prepare($query); $stmt->execute($params); $exceeded_records = $stmt->fetchAll(); // Check if we have enough consecutive records over the threshold $duration_exceeded = count($exceeded_records) * 5; // 5-minute intervals if ($duration_exceeded >= $alert['duration_minutes']) { trigger_discord_alert($alert, $server, $game_server, $resource_value, $duration_exceeded); } } /** * Trigger Discord alert */ function trigger_discord_alert($alert, $server, $game_server, $resource_value, $duration_exceeded) { global $db; // Check cooldown to prevent spam $cooldown_query = "SELECT setting_value FROM ogp_discord_settings WHERE setting_name = 'alert_cooldown_minutes'"; $cooldown_result = $db->query($cooldown_query)->fetch(); $cooldown_minutes = $cooldown_result ? intval($cooldown_result['setting_value']) : 60; if ($alert['last_triggered']) { $last_triggered_time = strtotime($alert['last_triggered']); $cooldown_time = $last_triggered_time + ($cooldown_minutes * 60); if (time() < $cooldown_time) { return; // Still in cooldown } } // Get Discord settings $webhook_url = $alert['discord_webhook_url']; if (!$webhook_url) { $default_webhook = $db->query("SELECT setting_value FROM ogp_discord_settings WHERE setting_name = 'default_webhook_url'")->fetch(); $webhook_url = $default_webhook ? $default_webhook['setting_value'] : ''; } if (!$webhook_url) { error_log("No Discord webhook URL configured for alert ID {$alert['id']}"); return; } // Create alert message $server_name = $server['agent_name'] ?: $server['agent_ip']; $target = $game_server ? "Game Server (Home ID: {$game_server['home_id']})" : "System"; $message = [ 'username' => 'OGP Resource Monitor', 'embeds' => [ [ 'title' => '🚨 Resource Alert Triggered', 'color' => 15158332, // Red color 'fields' => [ [ 'name' => 'Server', 'value' => $server_name, 'inline' => true ], [ 'name' => 'Target', 'value' => $target, 'inline' => true ], [ 'name' => 'Resource Type', 'value' => strtoupper($alert['alert_type']), 'inline' => true ], [ 'name' => 'Current Usage', 'value' => sprintf('%.2f%%', $resource_value), 'inline' => true ], [ 'name' => 'Threshold', 'value' => sprintf('%.2f%%', $alert['threshold_percentage']), 'inline' => true ], [ 'name' => 'Duration Exceeded', 'value' => sprintf('%d minutes', $duration_exceeded), 'inline' => true ] ], 'timestamp' => date('c'), 'footer' => [ 'text' => 'OGP Resource Monitoring System' ] ] ] ]; // Send Discord message $discord_response = send_discord_webhook($webhook_url, $message); // Update alert last_triggered time $update_query = "UPDATE ogp_resource_alerts SET last_triggered = NOW() WHERE id = ?"; $db->prepare($update_query)->execute([$alert['id']]); // Log alert in history $history_query = "INSERT INTO ogp_resource_alert_history (alert_id, remote_server_id, home_id, alert_type, triggered_value, threshold_value, duration_exceeded, message_sent, discord_response) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; $db->prepare($history_query)->execute([ $alert['id'], $server['remote_server_id'], $game_server ? $game_server['home_id'] : null, $alert['alert_type'], $resource_value, $alert['threshold_percentage'], $duration_exceeded, $discord_response ? 1 : 0, $discord_response ]); } /** * Send Discord webhook message */ function send_discord_webhook($webhook_url, $message) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $webhook_url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code >= 200 && $http_code < 300) { return "Success: HTTP $http_code"; } else { error_log("Discord webhook failed: HTTP $http_code, Response: $response"); return "Error: HTTP $http_code"; } } /** * Clean up old monitoring data */ function cleanup_old_data() { global $db; // Delete monitoring data older than 30 days $monitoring_query = "DELETE FROM ogp_resource_monitoring WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)"; $db->query($monitoring_query); // Delete alert history older than 90 days $history_query = "DELETE FROM ogp_resource_alert_history WHERE triggered_at < DATE_SUB(NOW(), INTERVAL 90 DAY)"; $db->query($history_query); } /** * API endpoint for collecting resources (called by cron) */ function collect_resources_api() { // Verify this is being called appropriately (could add API key check here) collect_all_resources(); cleanup_old_data(); header('Content-Type: application/json'); echo json_encode(['status' => 'success', 'message' => 'Resource collection completed']); exit; } /** * Show dashboard with current resource status */ function show_dashboard() { global $db, $view; echo "
No recent resource data available. Make sure the monitoring system is configured and running.
"; echo "Configure Monitoring"; return; } echo "CPU: " . number_format($data['cpu_usage'], 1) . "%
"; // Memory Usage $mem_class = $data['memory_usage'] >= 80 ? 'danger' : ($data['memory_usage'] >= 60 ? 'warning' : 'success'); echo "Memory: " . number_format($data['memory_usage'], 1) . "%"; echo " (" . number_format($data['memory_used_mb']/1024, 1) . "GB / " . number_format($data['memory_total_mb']/1024, 1) . "GB)
"; // Disk Usage $disk_class = $data['disk_usage'] >= 80 ? 'danger' : ($data['disk_usage'] >= 60 ? 'warning' : 'success'); echo "Disk: " . number_format($data['disk_usage'], 1) . "%"; echo " (" . number_format($data['disk_used_mb']/1024, 1) . "GB / " . number_format($data['disk_total_mb']/1024, 1) . "GB)
"; echo "Last Updated: " . date('Y-m-d H:i:s', strtotime($data['timestamp'])) . "
"; echo "*/5 * * * * curl -s " . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . "?m=resource_monitor&type=api_collect| Time | Server | Target | CPU % | Memory % | Disk % |
|---|---|---|---|---|---|
| " . date('m-d H:i', strtotime($data['timestamp'])) . " | "; echo "{$server_name} | "; echo "{$target} | "; echo "" . ($data['cpu_usage'] ? number_format($data['cpu_usage'], 1) . "%" : "-") . " | "; echo "" . ($data['memory_usage'] ? number_format($data['memory_usage'], 1) . "%" : "-") . " | "; echo "" . ($data['disk_usage'] ? number_format($data['disk_usage'], 1) . "%" : "-") . " | "; echo "
No alerts configured yet.
"; } else { echo "| Server | Type | Threshold | Duration | Active | Last Triggered |
|---|---|---|---|---|---|
| {$server_name} {$target} | ";
echo "" . strtoupper($alert['alert_type']) . " | "; echo "{$alert['threshold_percentage']}% | "; echo "{$alert['duration_minutes']} min | "; echo "" . ($alert['is_active'] ? "✅" : "❌") . " | "; echo "" . ($alert['last_triggered'] ? date('Y-m-d H:i', strtotime($alert['last_triggered'])) : "Never") . " | "; echo "