From 9682416b8164176d7d592dd2a8a26e7d01c1d830 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Sep 2025 20:21:06 +0000 Subject: [PATCH] Complete resource monitoring system implementation with dashboard, Discord alerts, and documentation Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com> --- includes/lib_remote.php | 22 +++ modules/resource_monitor/README.md | 184 ++++++++++++++++++ .../resource_monitor/resource_functions.php | 130 ++++++++----- scripts/resource_collector.php | 1 + scripts/setup_monitoring_cron.sh | 38 ++++ 5 files changed, 321 insertions(+), 54 deletions(-) create mode 100644 modules/resource_monitor/README.md create mode 100755 scripts/setup_monitoring_cron.sh diff --git a/includes/lib_remote.php b/includes/lib_remote.php index aafb450e..9fda8640 100755 --- a/includes/lib_remote.php +++ b/includes/lib_remote.php @@ -1198,5 +1198,27 @@ class OGPRemoteLibrary //Unknown response return -4; } + + /// Get system-wide resource usage from agent + public function get_system_resource_usage() + { + $args = $this->encrypt_params("system_resources"); + $this->add_enc_chk($args); + $request = xmlrpc_encode_request("get_system_resource_usage", $args); + $response = $this->sendRequest($request); + + return $response; + } + + /// Get resource usage for a specific game server from agent + public function get_gameserver_resource_usage($home_id) + { + $args = $this->encrypt_params($home_id); + $this->add_enc_chk($args); + $request = xmlrpc_encode_request("get_gameserver_resource_usage", $args); + $response = $this->sendRequest($request); + + return $response; + } } ?> diff --git a/modules/resource_monitor/README.md b/modules/resource_monitor/README.md new file mode 100644 index 00000000..f5657829 --- /dev/null +++ b/modules/resource_monitor/README.md @@ -0,0 +1,184 @@ +# OGP Resource Monitoring System + +This module provides comprehensive resource monitoring for Open Game Panel (OGP) installations, including real-time monitoring, alerting, and historical data visualization. + +## Features + +- **System-wide Monitoring**: CPU, RAM, and disk usage for entire servers +- **Per-Game-Server Monitoring**: Individual resource usage for each game instance +- **Discord Alerts**: Configurable threshold-based alerts sent to Discord channels +- **Historical Data**: 30-day retention with trend visualization +- **Automated Collection**: 5-minute interval data collection via cron jobs +- **Web Dashboard**: Real-time status with color-coded indicators + +## Installation + +1. **Database Setup**: The resource monitoring tables are automatically created when applying the main database schema, or you can apply them individually: + ```bash + mysql -u username -p database_name < db/resource_monitoring_schema.sql + ``` + +2. **Agent Enhancement**: The monitoring functions are added to the OGP agent (`_agent-linux/ogp_agent.pl`). The agent must be restarted for the new functions to be available. + +3. **Cron Job Setup**: Set up automated data collection: + ```bash + # Run the setup script + ./scripts/setup_monitoring_cron.sh + + # Or manually add to crontab: + */5 * * * * /usr/bin/php /path/to/GSP/scripts/resource_collector.php >> /var/log/ogp_monitoring.log 2>&1 + ``` + +4. **PHP Requirements**: Ensure the following PHP extensions are installed: + - mysqli (for database access) + - curl (for Discord webhooks) + - xmlrpc (for agent communication) + +## Usage + +### Dashboard Access + +Navigate to the Resource Monitor module in your OGP panel: +- **Dashboard**: Real-time resource status for all servers +- **History**: Historical data and trend analysis +- **Alerts**: Configure Discord alerts and thresholds +- **Configuration**: Setup instructions and system status + +### Setting Up Alerts + +1. **Create Discord Webhook**: + - In your Discord server, go to Server Settings → Integrations → Webhooks + - Create a new webhook and copy the webhook URL + +2. **Configure Alert Thresholds**: + - Access the "Alert Configuration" page + - Set the default Discord webhook URL + - Add alerts for specific servers and resource types + - Configure threshold percentages and duration requirements + +3. **Alert Parameters**: + - **Threshold**: Percentage at which to trigger alerts (default: 80%) + - **Duration**: Minutes the threshold must be exceeded (default: 30) + - **Cooldown**: Minimum time between identical alerts (default: 60 minutes) + +### Data Collection + +The system collects the following metrics: + +**System-wide (per server)**: +- CPU usage percentage +- Memory usage percentage and absolute values +- Disk usage percentage and absolute values +- Network traffic (cumulative) + +**Per-game-server**: +- CPU usage by game processes +- Memory usage by game processes +- Process count + +### API Endpoints + +The system provides API endpoints for data collection: +- `?m=resource_monitor&type=api_collect` - Trigger manual collection + +## Technical Details + +### Database Schema + +- `ogp_resource_monitoring`: Timestamped resource data +- `ogp_resource_alerts`: Alert configurations +- `ogp_resource_alert_history`: Alert trigger history +- `ogp_discord_settings`: Discord integration settings + +### Agent Functions + +New XML-RPC functions added to the agent: +- `get_system_resource_usage()`: System-wide metrics +- `get_gameserver_resource_usage(home_id)`: Game-specific metrics + +### Data Retention + +- Resource monitoring data: 30 days +- Alert history: 90 days +- Automatic cleanup via scheduled database operations + +## Configuration Examples + +### Basic Alert Setup +``` +Server: My Game Server +Resource Type: CPU +Threshold: 80% +Duration: 30 minutes +``` + +### Discord Webhook Format +```json +{ + "username": "OGP Resource Monitor", + "embeds": [{ + "title": "🚨 Resource Alert Triggered", + "color": 15158332, + "fields": [ + {"name": "Server", "value": "My Server", "inline": true}, + {"name": "Resource", "value": "CPU", "inline": true}, + {"name": "Usage", "value": "85.2%", "inline": true} + ] + }] +} +``` + +## Troubleshooting + +### Common Issues + +1. **No Data Appearing**: + - Verify cron job is running: `crontab -l` + - Check agent connectivity and authentication + - Review log files: `tail -f /var/log/ogp_monitoring.log` + +2. **Agent Connection Errors**: + - Ensure agent is running and accessible + - Verify encryption keys match between panel and agent + - Check firewall settings for agent port + +3. **Discord Alerts Not Sending**: + - Verify webhook URL is correct and active + - Check Discord server permissions + - Review PHP curl extension availability + +### Log Files + +- Monitoring collection: `/var/log/ogp_monitoring.log` +- PHP errors: Check your web server's error log +- Agent logs: `_agent-linux/ogp_agent.log` + +## Performance Considerations + +- Data collection occurs every 5 minutes per server +- Database queries are optimized with proper indexing +- Historical data is automatically pruned after 30 days +- Dashboard queries are limited to recent data for performance + +## Security + +- All agent communication uses XXTEA encryption +- Discord webhooks use HTTPS +- Database queries use proper escaping to prevent injection +- Alert cooldowns prevent webhook spam + +## Future Enhancements + +- Advanced charting and graphing +- Email alert options +- Mobile-responsive dashboard improvements +- Custom alert conditions and thresholds +- Integration with external monitoring systems + +## Support + +For issues and questions: +1. Check the OGP documentation +2. Review log files for error messages +3. Verify all dependencies are installed +4. Test individual components (database, agent, webhooks) \ No newline at end of file diff --git a/modules/resource_monitor/resource_functions.php b/modules/resource_monitor/resource_functions.php index 013e9a30..745e2ec0 100644 --- a/modules/resource_monitor/resource_functions.php +++ b/modules/resource_monitor/resource_functions.php @@ -86,26 +86,39 @@ 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + 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 + )"; - $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 - ]); + return $db->query($query); } /** @@ -117,10 +130,9 @@ function check_system_alerts($server, $data) // 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(); + 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; @@ -407,17 +419,16 @@ function show_dashboard() echo "

Resource Monitoring Dashboard

"; // Get recent resource data for all servers - $query = "SELECT r.*, s.agent_name, s.agent_ip + $query = "SELECT r.*, s.remote_server_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(); + $servers_data = $db->resultQuery($query); - if (empty($servers_data)) { + if (!$servers_data || empty($servers_data)) { echo "

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

"; echo "Configure Monitoring"; return; @@ -442,7 +453,7 @@ function show_dashboard() foreach ($servers as $server_id => $server) { $data = $server['latest']; - $server_name = $data['agent_name'] ?: $data['agent_ip']; + $server_name = $data['remote_server_name'] ?: $data['agent_ip']; echo "
"; echo "
"; @@ -498,10 +509,10 @@ function show_configuration() // 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(); + $recent_data = $db->resultQuery("SELECT COUNT(*) as count FROM ogp_resource_monitoring WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 10 MINUTE)"); - if ($recent_data['count'] > 0) { - echo "
✅ Monitoring is active - " . $recent_data['count'] . " records in the last 10 minutes
"; + if ($recent_data && isset($recent_data[0]['count']) && $recent_data[0]['count'] > 0) { + echo "
✅ Monitoring is active - " . $recent_data[0]['count'] . " records in the last 10 minutes
"; } else { echo "
⚠️ No recent monitoring data found. Please set up the cron job.
"; } @@ -517,7 +528,7 @@ function show_history() 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 + $query = "SELECT r.*, s.remote_server_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 @@ -525,15 +536,18 @@ function show_history() ORDER BY r.timestamp DESC LIMIT 100"; - $result = $db->query($query); - $history_data = $result->fetchAll(); + $history_data = $db->resultQuery($query); + + if (!$history_data) { + $history_data = []; + } echo ""; echo ""; echo ""; foreach ($history_data as $data) { - $server_name = $data['agent_name'] ?: $data['agent_ip']; + $server_name = $data['remote_server_name'] ?: $data['agent_ip']; $target = $data['home_id'] ? "Game Server ({$data['home_name']})" : "System"; echo ""; @@ -589,9 +603,9 @@ function manage_alerts() // 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(); + $alerts = $db->resultQuery("SELECT a.*, s.remote_server_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"); - if (empty($alerts)) { + if (!$alerts || empty($alerts)) { echo "

No alerts configured yet.

"; } else { echo "
TimeServerTargetCPU %Memory %Disk %
"; @@ -599,7 +613,7 @@ function manage_alerts() echo ""; foreach ($alerts as $alert) { - $server_name = $alert['agent_name'] ?: $alert['agent_ip']; + $server_name = $alert['remote_server_name'] ?: $alert['agent_ip']; $target = $alert['home_id'] ? "Game Server (ID: {$alert['home_id']})" : "System"; echo ""; @@ -625,10 +639,12 @@ function manage_alerts() echo "
"; echo ""; echo ""; echo "
"; @@ -672,10 +688,12 @@ function get_discord_settings() global $db; $settings = []; - $result = $db->query("SELECT setting_name, setting_value FROM ogp_discord_settings"); + $result = $db->resultQuery("SELECT setting_name, setting_value FROM ogp_discord_settings"); - while ($row = $result->fetch()) { - $settings[$row['setting_name']] = $row['setting_value']; + if ($result) { + foreach ($result as $row) { + $settings[$row['setting_name']] = $row['setting_value']; + } } return $settings; @@ -691,8 +709,9 @@ function update_discord_settings() ]; foreach ($settings as $name => $value) { - $stmt = $db->prepare("UPDATE ogp_discord_settings SET setting_value = ? WHERE setting_name = ?"); - $stmt->execute([$value, $name]); + $escaped_value = $db->realEscapeSingle($value); + $escaped_name = $db->realEscapeSingle($name); + $db->query("UPDATE ogp_discord_settings SET setting_value = '$escaped_value' WHERE setting_name = '$escaped_name'"); } echo "
Discord settings updated successfully!
"; @@ -702,19 +721,22 @@ 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 (?, ?, ?, ?, ?)"); + $remote_server_id = intval($_POST['remote_server_id']); + $alert_type = $db->realEscapeSingle($_POST['alert_type']); + $threshold = floatval($_POST['threshold']); + $duration = intval($_POST['duration']); + $webhook_url = !empty($_POST['webhook_url']) ? $db->realEscapeSingle($_POST['webhook_url']) : 'NULL'; - $webhook_url = !empty($_POST['webhook_url']) ? $_POST['webhook_url'] : null; + $webhook_value = ($webhook_url === 'NULL') ? 'NULL' : "'$webhook_url'"; - $stmt->execute([ - $_POST['remote_server_id'], - $_POST['alert_type'], - $_POST['threshold'], - $_POST['duration'], - $webhook_url - ]); + $query = "INSERT INTO ogp_resource_alerts (remote_server_id, alert_type, threshold_percentage, duration_minutes, discord_webhook_url) + VALUES ($remote_server_id, '$alert_type', $threshold, $duration, $webhook_value)"; - echo "
Alert added successfully!
"; + if ($db->query($query)) { + echo "
Alert added successfully!
"; + } else { + echo "
Error adding alert!
"; + } } ?> \ No newline at end of file diff --git a/scripts/resource_collector.php b/scripts/resource_collector.php index 689077ed..1c738df6 100755 --- a/scripts/resource_collector.php +++ b/scripts/resource_collector.php @@ -12,6 +12,7 @@ chdir(dirname(__DIR__)); require_once('includes/config.inc.php'); require_once('includes/functions.php'); +require_once('includes/helpers.php'); require_once('includes/database.php'); // Connect to database diff --git a/scripts/setup_monitoring_cron.sh b/scripts/setup_monitoring_cron.sh new file mode 100755 index 00000000..bfffd5c1 --- /dev/null +++ b/scripts/setup_monitoring_cron.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Setup script for OGP Resource Monitoring Cron Job +# This script sets up the cron job to collect resource data every 5 minutes + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +OGP_DIR="$(dirname "$SCRIPT_DIR")" +COLLECTOR_SCRIPT="$OGP_DIR/scripts/resource_collector.php" + +echo "Setting up OGP Resource Monitoring..." + +# Check if the resource collector script exists +if [ ! -f "$COLLECTOR_SCRIPT" ]; then + echo "Error: Resource collector script not found at $COLLECTOR_SCRIPT" + exit 1 +fi + +# Make the script executable +chmod +x "$COLLECTOR_SCRIPT" + +# Create the cron job entry +CRON_ENTRY="*/5 * * * * /usr/bin/php $COLLECTOR_SCRIPT >> /var/log/ogp_monitoring.log 2>&1" + +# Add to crontab if not already present +if ! crontab -l 2>/dev/null | grep -q "resource_collector.php"; then + (crontab -l 2>/dev/null; echo "$CRON_ENTRY") | crontab - + echo "Cron job added successfully!" + echo "Resource monitoring will run every 5 minutes." +else + echo "Cron job already exists." +fi + +echo "" +echo "To verify the cron job was added, run: crontab -l" +echo "To view monitoring logs, run: tail -f /var/log/ogp_monitoring.log" +echo "" +echo "You can also trigger manual collection by running:" +echo " php $COLLECTOR_SCRIPT" \ No newline at end of file