Complete resource monitoring system implementation with dashboard, Discord alerts, and documentation

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-09-10 20:21:06 +00:00
parent 57a34d3a2b
commit 9682416b81
5 changed files with 321 additions and 54 deletions

View file

@ -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;
}
}
?>

View file

@ -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)

View file

@ -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 "<h2>Resource Monitoring Dashboard</h2>";
// 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 "<p>No recent resource data available. Make sure the monitoring system is configured and running.</p>";
echo "<a href='?m=resource_monitor&type=configure' class='btn btn-primary'>Configure Monitoring</a>";
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 "<div class='col-md-4'>";
echo "<div class='card'>";
@ -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 "<div class='alert alert-success'>✅ Monitoring is active - " . $recent_data['count'] . " records in the last 10 minutes</div>";
if ($recent_data && isset($recent_data[0]['count']) && $recent_data[0]['count'] > 0) {
echo "<div class='alert alert-success'>✅ Monitoring is active - " . $recent_data[0]['count'] . " records in the last 10 minutes</div>";
} else {
echo "<div class='alert alert-warning'>⚠️ No recent monitoring data found. Please set up the cron job.</div>";
}
@ -517,7 +528,7 @@ function show_history()
echo "<h2>Resource History</h2>";
// 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 "<table class='table table-striped'>";
echo "<thead><tr><th>Time</th><th>Server</th><th>Target</th><th>CPU %</th><th>Memory %</th><th>Disk %</th></tr></thead>";
echo "<tbody>";
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 "<tr>";
@ -589,9 +603,9 @@ function manage_alerts()
// Show existing alerts
echo "<h4>Current Alerts</h4>";
$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 "<p>No alerts configured yet.</p>";
} else {
echo "<table class='table'>";
@ -599,7 +613,7 @@ function manage_alerts()
echo "<tbody>";
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 "<tr>";
@ -625,10 +639,12 @@ function manage_alerts()
echo "<div class='col-md-4'>";
echo "<label>Server:</label>";
echo "<select name='remote_server_id' class='form-control' required>";
$servers = $db->query("SELECT remote_server_id, agent_name, agent_ip FROM ogp_remote_servers ORDER BY agent_name, agent_ip")->fetchAll();
foreach ($servers as $server) {
$name = $server['agent_name'] ?: $server['agent_ip'];
echo "<option value='{$server['remote_server_id']}'>{$name}</option>";
$servers = $db->resultQuery("SELECT remote_server_id, remote_server_name, agent_ip FROM ogp_remote_servers ORDER BY remote_server_name, agent_ip");
if ($servers) {
foreach ($servers as $server) {
$name = $server['remote_server_name'] ?: $server['agent_ip'];
echo "<option value='{$server['remote_server_id']}'>{$name}</option>";
}
}
echo "</select>";
echo "</div>";
@ -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 "<div class='alert alert-success'>Discord settings updated successfully!</div>";
@ -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 "<div class='alert alert-success'>Alert added successfully!</div>";
if ($db->query($query)) {
echo "<div class='alert alert-success'>Alert added successfully!</div>";
} else {
echo "<div class='alert alert-danger'>Error adding alert!</div>";
}
}
?>

View file

@ -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

View file

@ -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"