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; $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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $db->prepare($query); $stmt->execute([ $remote_server_id, $home_id, isset($data['cpu_usage']) ? floatval($data['cpu_usage']) : null, isset($data['memory_usage']) ? floatval($data['memory_usage']) : null, isset($data['memory_used_mb']) ? intval($data['memory_used_mb']) : null, isset($data['memory_total_mb']) ? intval($data['memory_total_mb']) : null, isset($data['disk_usage']) ? floatval($data['disk_usage']) : null, isset($data['disk_used_mb']) ? intval($data['disk_used_mb']) : null, isset($data['disk_total_mb']) ? intval($data['disk_total_mb']) : null, isset($data['process_count']) ? intval($data['process_count']) : null, isset($data['network_rx_mb']) ? intval($data['network_rx_mb']) : null, isset($data['network_tx_mb']) ? intval($data['network_tx_mb']) : null ]); } /** * 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 = ? AND home_id IS NULL AND is_active = 1"; $stmt = $db->prepare($query); $stmt->execute([$server['remote_server_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': $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 "

Resource Monitoring Dashboard

"; // Get recent resource data for all servers $query = "SELECT r.*, s.agent_name, s.agent_ip FROM ogp_resource_monitoring r LEFT JOIN ogp_remote_servers s ON r.remote_server_id = s.remote_server_id WHERE r.timestamp >= DATE_SUB(NOW(), INTERVAL 1 HOUR) AND r.home_id IS NULL ORDER BY r.timestamp DESC"; $result = $db->query($query); $servers_data = $result->fetchAll(); if (empty($servers_data)) { echo "

No recent resource data available. Make sure the monitoring system is configured and running.

"; echo "Configure Monitoring"; return; } echo "
"; // Group by server $servers = []; foreach ($servers_data as $data) { $server_id = $data['remote_server_id']; if (!isset($servers[$server_id])) { $servers[$server_id] = [ 'info' => $data, 'latest' => null ]; } if (!$servers[$server_id]['latest'] || $data['timestamp'] > $servers[$server_id]['latest']['timestamp']) { $servers[$server_id]['latest'] = $data; } } foreach ($servers as $server_id => $server) { $data = $server['latest']; $server_name = $data['agent_name'] ?: $data['agent_ip']; echo "
"; echo "
"; echo "
{$server_name}
"; echo "
"; // CPU Usage $cpu_class = $data['cpu_usage'] >= 80 ? 'danger' : ($data['cpu_usage'] >= 60 ? 'warning' : 'success'); 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 "
"; } echo "
"; echo "
"; echo "View History "; echo "Manage Alerts "; echo "Configuration"; echo "
"; } /** * Show configuration page */ function show_configuration() { echo "

Resource Monitoring Configuration

"; echo "
"; echo "
Setup Instructions:
"; echo "
    "; echo "
  1. Add this to your server's crontab to collect data every 5 minutes:
    "; echo "*/5 * * * * curl -s " . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . "?m=resource_monitor&type=api_collect
  2. "; echo "
  3. Configure Discord webhook URLs in the alerts section
  4. "; echo "
  5. Set up alert thresholds for your servers and game instances
  6. "; echo "
"; echo "
"; echo "

Monitoring Status

"; // Check if we have recent data global $db; $recent_data = $db->query("SELECT COUNT(*) as count FROM ogp_resource_monitoring WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 10 MINUTE)")->fetch(); if ($recent_data['count'] > 0) { echo "
✅ Monitoring is active - " . $recent_data['count'] . " records in the last 10 minutes
"; } else { echo "
⚠️ No recent monitoring data found. Please set up the cron job.
"; } } /** * Show resource history with charts */ function show_history() { global $db; echo "

Resource History

"; // Simple table view for now - could be enhanced with charts later $query = "SELECT r.*, s.agent_name, s.agent_ip, h.home_name FROM ogp_resource_monitoring r LEFT JOIN ogp_remote_servers s ON r.remote_server_id = s.remote_server_id LEFT JOIN ogp_server_homes h ON r.home_id = h.home_id WHERE r.timestamp >= DATE_SUB(NOW(), INTERVAL 24 HOUR) ORDER BY r.timestamp DESC LIMIT 100"; $result = $db->query($query); $history_data = $result->fetchAll(); echo ""; echo ""; echo ""; foreach ($history_data as $data) { $server_name = $data['agent_name'] ?: $data['agent_ip']; $target = $data['home_id'] ? "Game Server ({$data['home_name']})" : "System"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo "
TimeServerTargetCPU %Memory %Disk %
" . date('m-d H:i', strtotime($data['timestamp'])) . "{$server_name}{$target}" . ($data['cpu_usage'] ? number_format($data['cpu_usage'], 1) . "%" : "-") . "" . ($data['memory_usage'] ? number_format($data['memory_usage'], 1) . "%" : "-") . "" . ($data['disk_usage'] ? number_format($data['disk_usage'], 1) . "%" : "-") . "
"; } /** * Manage alerts configuration */ function manage_alerts() { global $db; if (isset($_POST['add_alert'])) { add_alert(); } if (isset($_POST['update_discord_settings'])) { update_discord_settings(); } echo "

Alert Management

"; // Discord settings form echo "

Discord Settings

"; echo "
"; $discord_settings = get_discord_settings(); echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo ""; echo "
"; echo "
"; // Show existing alerts echo "

Current Alerts

"; $alerts = $db->query("SELECT a.*, s.agent_name, s.agent_ip FROM ogp_resource_alerts a LEFT JOIN ogp_remote_servers s ON a.remote_server_id = s.remote_server_id ORDER BY a.created_at DESC")->fetchAll(); if (empty($alerts)) { echo "

No alerts configured yet.

"; } else { echo ""; echo ""; echo ""; foreach ($alerts as $alert) { $server_name = $alert['agent_name'] ?: $alert['agent_ip']; $target = $alert['home_id'] ? "Game Server (ID: {$alert['home_id']})" : "System"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo "
ServerTypeThresholdDurationActiveLast Triggered
{$server_name}
{$target}
" . strtoupper($alert['alert_type']) . "{$alert['threshold_percentage']}%{$alert['duration_minutes']} min" . ($alert['is_active'] ? "✅" : "❌") . "" . ($alert['last_triggered'] ? date('Y-m-d H:i', strtotime($alert['last_triggered'])) : "Never") . "
"; } echo "
"; // Add new alert form echo "

Add New Alert

"; echo "
"; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo ""; echo ""; echo "
"; echo "
"; echo "
"; echo ""; echo "
"; echo "
"; } function get_discord_settings() { global $db; $settings = []; $result = $db->query("SELECT setting_name, setting_value FROM ogp_discord_settings"); while ($row = $result->fetch()) { $settings[$row['setting_name']] = $row['setting_value']; } return $settings; } function update_discord_settings() { global $db; $settings = [ 'default_webhook_url' => $_POST['webhook_url'], 'bot_username' => $_POST['bot_username'] ]; foreach ($settings as $name => $value) { $stmt = $db->prepare("UPDATE ogp_discord_settings SET setting_value = ? WHERE setting_name = ?"); $stmt->execute([$value, $name]); } echo "
Discord settings updated successfully!
"; } function add_alert() { global $db; $stmt = $db->prepare("INSERT INTO ogp_resource_alerts (remote_server_id, alert_type, threshold_percentage, duration_minutes, discord_webhook_url) VALUES (?, ?, ?, ?, ?)"); $webhook_url = !empty($_POST['webhook_url']) ? $_POST['webhook_url'] : null; $stmt->execute([ $_POST['remote_server_id'], $_POST['alert_type'], $_POST['threshold'], $_POST['duration'], $webhook_url ]); echo "
Alert added successfully!
"; } ?>