diff --git a/modules/resource_stats/stats_aggregate.php b/modules/resource_stats/stats_aggregate.php index eb93ac02..78252559 100644 --- a/modules/resource_stats/stats_aggregate.php +++ b/modules/resource_stats/stats_aggregate.php @@ -1,32 +1,30 @@ '127.0.0.1', - 'user' => 'gs_metrics', + 'user' => 'panel_user', 'pass' => 'REPLACE_ME', - 'name' => 'gs_metrics' + 'name' => 'panel_database' ]; - +$TABLE_PREFIX = 'gsp_'; $DISCORD_WEBHOOK = 'https://discord.com/api/webhooks/REPLACE_ME'; -$ALERT_THRESHOLD = 80.0; // percent -/****************************/ +$ALERT_THRESHOLD = 80.0; +/***************************************/ -header('Content-Type: application/json'); +$format = $_GET['format'] ?? 'json'; +$machine = $_GET['machine'] ?? null; -$machine = isset($_GET['machine']) ? $_GET['machine'] : null; -$format = isset($_GET['format']) ? $_GET['format'] : 'json'; +if ($format === 'html') header('Content-Type: text/html'); else header('Content-Type: application/json'); $mysqli = new mysqli($db['host'], $db['user'], $db['pass'], $db['name']); if ($mysqli->connect_errno) { http_response_code(500); - echo json_encode(['error' => 'DB connect failed', 'detail' => $mysqli->connect_error]); - exit; + echo json_encode(['error' => 'DB connect failed', 'detail' => $mysqli->connect_error]); exit; } $mysqli->set_charset("utf8mb4"); -// helper function q($mysqli, $sql, $params=[]) { $stmt = $mysqli->prepare($sql); if(!$stmt){ throw new Exception($mysqli->error); } @@ -46,9 +44,7 @@ function send_discord($url, $content) { curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['content' => $content])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - $resp = curl_exec($ch); - $err = curl_error($ch); - curl_close($ch); + $resp = curl_exec($ch); $err = curl_error($ch); curl_close($ch); return [$resp, $err]; } function window_clause($hours) { @@ -56,18 +52,17 @@ function window_clause($hours) { } try { - // If no machine specified, list available: if(!$machine){ - $rows = q($mysqli, "SELECT DISTINCT machine_id, hostname, created_at FROM machines ORDER BY created_at DESC"); - echo json_encode(['machines' => $rows], JSON_PRETTY_PRINT); + $rows = q($mysqli, "SELECT machine_id, hostname, created_at FROM {$TABLE_PREFIX}machines ORDER BY created_at DESC"); + $payload = ['machines' => $rows]; + echo $format==='html' ? "
".htmlspecialchars(json_encode($payload, JSON_PRETTY_PRINT))."
" : json_encode($payload, JSON_PRETTY_PRINT); exit; } $out = ['machine' => $machine, 'windows' => []]; - // ---- LAST SAMPLE ---- $lastM = q($mysqli, - "SELECT * FROM machine_samples WHERE machine_id=? ORDER BY ts DESC LIMIT 1", + "SELECT * FROM {$TABLE_PREFIX}machine_samples WHERE machine_id=? ORDER BY ts DESC LIMIT 1", [$machine] ); $lastTs = $lastM ? $lastM[0]['ts'] : null; @@ -78,8 +73,8 @@ try { AVG(mem_pct) AS mem_pct_avg, MAX(folder_size_bytes) AS folder_size_bytes, GROUP_CONCAT(DISTINCT pid ORDER BY pid) AS pids - FROM process_samples - WHERE machine_id=? AND ts=(SELECT MAX(ts) FROM process_samples WHERE machine_id=?) + FROM {$TABLE_PREFIX}process_samples + WHERE machine_id=? AND ts=(SELECT MAX(ts) FROM {$TABLE_PREFIX}process_samples WHERE machine_id=?) GROUP BY server_name ORDER BY server_name ASC ", [$machine, $machine]); @@ -101,45 +96,31 @@ try { 'servers' => $lastServers ]; - // ---- WINDOWS ---- - $windows = [ - '1h' => 1, - '24h' => 24, - '7d' => 24*7 - ]; - + $windows = [ '1h'=>1, '24h'=>24, '7d'=>24*7 ]; foreach($windows as $label=>$hours){ - // Machine aggregates $aggM = q($mysqli, " - SELECT - COUNT(*) AS n, - AVG(cpu_pct) AS cpu_avg, - AVG(mem_used_pct) AS mem_avg, - AVG(disk_used_pct)AS disk_avg, - MIN(ts) AS ts_first, - MAX(ts) AS ts_last - FROM machine_samples + SELECT COUNT(*) AS n, + AVG(cpu_pct) AS cpu_avg, + AVG(mem_used_pct) AS mem_avg, + AVG(disk_used_pct)AS disk_avg + FROM {$TABLE_PREFIX}machine_samples WHERE machine_id=? AND ".window_clause($hours), [$machine] ); $netRows = q($mysqli, " SELECT ts, rx_bytes, tx_bytes, iface_speed_mbps - FROM machine_samples + FROM {$TABLE_PREFIX}machine_samples WHERE machine_id=? AND ".window_clause($hours)." ORDER BY ts ASC ", [$machine]); $net = null; if(count($netRows) >= 2){ - $first = $netRows[0]; - $last = $netRows[count($netRows)-1]; - $t1 = strtotime($first['ts']); $t2 = strtotime($last['ts']); - $secs = max(1, $t2-$t1); - $rx_bytes = (int)$last['rx_bytes'] - (int)$first['rx_bytes']; - $tx_bytes = (int)$last['tx_bytes'] - (int)$first['tx_bytes']; - $rx_bps = $rx_bytes / $secs; - $tx_bps = $tx_bytes / $secs; + $first = $netRows[0]; $last = $netRows[count($netRows)-1]; + $secs = max(1, strtotime($last['ts']) - strtotime($first['ts'])); + $rx_bps = ((int)$last['rx_bytes'] - (int)$first['rx_bytes']) / $secs; + $tx_bps = ((int)$last['tx_bytes'] - (int)$first['tx_bytes']) / $secs; $speed_mbps = $last['iface_speed_mbps'] ? (int)$last['iface_speed_mbps'] : null; $util_pct = null; if($speed_mbps && $speed_mbps > 0){ @@ -154,13 +135,12 @@ try { ]; } - // Per-server aggregates $aggS = q($mysqli, " SELECT server_name, AVG(cpu_pct) AS cpu_avg, AVG(mem_pct) AS mem_avg, MAX(folder_size_bytes) AS folder_size_bytes - FROM process_samples + FROM {$TABLE_PREFIX}process_samples WHERE machine_id=? AND ".window_clause($hours)." GROUP BY server_name ORDER BY server_name ASC @@ -177,25 +157,20 @@ try { ]; } - // ---- ALERTS (>=80% for 1h or 24h) ---- $alerts = []; foreach (['1h','24h'] as $w) { $mw = $out['windows'][$w]['machine']; - // machine: cpu, mem, disk, net util% if ($mw['cpu_avg'] !== null && $mw['cpu_avg'] >= $ALERT_THRESHOLD) $alerts[] = "Machine CPU avg {$w}: ".round($mw['cpu_avg'],1)."%"; if ($mw['mem_avg'] !== null && $mw['mem_avg'] >= $ALERT_THRESHOLD) $alerts[] = "Machine MEM avg {$w}: ".round($mw['mem_avg'],1)."%"; if ($mw['disk_avg'] !== null && $mw['disk_avg'] >= $ALERT_THRESHOLD) $alerts[] = "Machine DISK avg {$w}: ".round($mw['disk_avg'],1)."%"; if (isset($mw['net']['avg_util_pct']) && $mw['net']['avg_util_pct'] !== null && $mw['net']['avg_util_pct'] >= $ALERT_THRESHOLD) { $alerts[] = "Machine NET util avg {$w}: ".round($mw['net']['avg_util_pct'],1)."%"; } - // servers: cpu or mem foreach ($out['windows'][$w]['servers'] as $s) { - if ($s['cpu_avg'] !== null && (float)$s['cpu_avg'] >= $ALERT_THRESHOLD) { + if ($s['cpu_avg'] !== null && (float)$s['cpu_avg'] >= $ALERT_THRESHOLD) $alerts[] = "Server '{$s['server_name']}' CPU avg {$w}: ".round($s['cpu_avg'],1)."%"; - } - if ($s['mem_avg'] !== null && (float)$s['mem_avg'] >= $ALERT_THRESHOLD) { + if ($s['mem_avg'] !== null && (float)$s['mem_avg'] >= $ALERT_THRESHOLD) $alerts[] = "Server '{$s['server_name']}' MEM avg {$w}: ".round($s['mem_avg'],1)."%"; - } } } if (!empty($alerts) && !empty($DISCORD_WEBHOOK) && strpos($DISCORD_WEBHOOK, 'REPLACE_ME') === false) { @@ -206,12 +181,8 @@ try { $out['alerts_sent'] = []; } - if ($format === 'html') { - header('Content-Type: text/html'); - echo "
".htmlspecialchars(json_encode($out, JSON_PRETTY_PRINT))."
"; - } else { - echo json_encode($out, JSON_PRETTY_PRINT); - } + $json = json_encode($out, JSON_PRETTY_PRINT); + echo $format==='html' ? "
".htmlspecialchars($json)."
" : $json; } catch (Throwable $e) { http_response_code(500);