Files
wevads-platform/scripts/hamid-maintenance.php
2026-02-26 04:53:11 +01:00

676 lines
29 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* WEVAL MIND - Centre de Maintenance & Surveillance Automatique
* URL: http://89.167.40.150:5821/hamid-maintenance.php
*
* Fonctionnalités:
* - Diagnostic complet automatique
* - Tests de tous les services
* - Réanimation automatique des services down
* - Optimisation système
* - Surveillance temps réel
*/
header('Content-Type: text/html; charset=UTF-8');
// Mode API JSON
if (isset($_GET['api'])) {
header('Content-Type: application/json');
$action = $_GET['api'];
switch ($action) {
case 'status':
echo json_encode(getSystemStatus());
break;
case 'fix':
echo json_encode(autoFix());
break;
case 'test':
echo json_encode(runAllTests());
break;
case 'optimize':
echo json_encode(optimizeSystem());
break;
default:
echo json_encode(['error' => 'Unknown action']);
}
exit;
}
// Fonctions de diagnostic
function getSystemStatus() {
$status = [
'timestamp' => date('c'),
'hostname' => gethostname(),
'uptime' => trim(shell_exec("uptime -p")),
'load' => sys_getloadavg(),
'cpu_cores' => intval(shell_exec("nproc")),
'memory' => [
'total_gb' => round(intval(shell_exec("free -b | awk '/Mem:/ {print $2}'")) / 1024/1024/1024, 2),
'used_gb' => round(intval(shell_exec("free -b | awk '/Mem:/ {print $3}'")) / 1024/1024/1024, 2),
'percent' => round(floatval(shell_exec("free | awk '/Mem:/ {print $3/$2 * 100}'")), 1)
],
'disk' => [
'used' => trim(shell_exec("df -h / | awk 'NR==2 {print $3}'")),
'total' => trim(shell_exec("df -h / | awk 'NR==2 {print $2}'")),
'percent' => intval(trim(shell_exec("df / | awk 'NR==2 {print $5}'")))
],
'services' => [],
'processes' => [],
'hamid' => []
];
// Services
$services = ['apache2', 'postgresql', 'php7.4-fpm', 'php8.1-fpm'];
foreach ($services as $svc) {
$active = trim(shell_exec("systemctl is-active $svc 2>/dev/null"));
if ($active) {
$status['services'][$svc] = $active;
}
}
// Processus zombies/gourmands
$zombies = shell_exec("ps aux --sort=-%cpu | awk '\$3 > 50 {print \$2, \$3, \$11}' | head -5");
$status['processes']['high_cpu'] = array_filter(explode("\n", trim($zombies)));
// WEVAL MIND status
$ch = curl_init('http://localhost:5821/hamid-status.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200 && $result) {
$data = json_decode($result, true);
$status['hamid']['api'] = 'ok';
$status['hamid']['best_provider'] = $data['best_available'] ?? 'unknown';
$readyCount = 0;
foreach ($data['providers'] ?? [] as $p) {
if (($p['status'] ?? '') === 'ready') $readyCount++;
}
$status['hamid']['providers_ready'] = $readyCount;
} else {
$status['hamid']['api'] = 'error';
}
// Health score
$score = 100;
if ($status['load'][0] > $status['cpu_cores']) $score -= 20;
if ($status['memory']['percent'] > 80) $score -= 15;
if ($status['disk']['percent'] > 80) $score -= 15;
if (($status['services']['apache2'] ?? '') !== 'active') $score -= 20;
if (($status['services']['postgresql'] ?? '') !== 'active') $score -= 20;
if ($status['hamid']['api'] !== 'ok') $score -= 10;
$status['health_score'] = max(0, $score);
$status['health_status'] = $score >= 80 ? 'healthy' : ($score >= 50 ? 'degraded' : 'critical');
return $status;
}
function runAllTests() {
$tests = [];
// Test 1: Apache
$tests['apache'] = [
'name' => 'Apache Web Server',
'status' => trim(shell_exec("systemctl is-active apache2")) === 'active',
'response_time' => null
];
// Test 2: PostgreSQL
$tests['postgresql'] = [
'name' => 'PostgreSQL Database',
'status' => trim(shell_exec("systemctl is-active postgresql")) === 'active',
'response_time' => null
];
// Test 3: PHP-FPM
$phpfpm = trim(shell_exec("systemctl is-active php7.4-fpm 2>/dev/null"));
if (!$phpfpm) $phpfpm = trim(shell_exec("systemctl is-active php8.1-fpm 2>/dev/null"));
$tests['php_fpm'] = [
'name' => 'PHP-FPM',
'status' => $phpfpm === 'active',
'response_time' => null
];
// Test 4: WEVAL MIND API
$start = microtime(true);
$ch = curl_init('http://localhost:5821/hamid-api.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'message' => 'test',
'provider' => 'cerebras',
'session_id' => 'maint_test_' . time()
]));
$result = curl_exec($ch);
$duration = round((microtime(true) - $start) * 1000);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$apiData = json_decode($result, true);
$tests['hamid_api'] = [
'name' => 'WEVAL MIND Chat API',
'status' => $httpCode == 200 && isset($apiData['response']),
'response_time' => $duration,
'provider' => $apiData['provider'] ?? null
];
// Test 5: Dashboard
$start = microtime(true);
$ch = curl_init('http://localhost:5821/hamid-dashboard.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$result = curl_exec($ch);
$duration = round((microtime(true) - $start) * 1000);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$tests['dashboard'] = [
'name' => 'Dashboard',
'status' => $httpCode == 200 && strlen($result) > 1000,
'response_time' => $duration
];
// Test 6: Providers Status
$start = microtime(true);
$ch = curl_init('http://localhost:5821/hamid-status.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$result = curl_exec($ch);
$duration = round((microtime(true) - $start) * 1000);
curl_close($ch);
$statusData = json_decode($result, true);
$tests['providers'] = [
'name' => 'AI Providers',
'status' => isset($statusData['best_available']),
'response_time' => $duration,
'ready_count' => count(array_filter($statusData['providers'] ?? [], fn($p) => ($p['status'] ?? '') === 'ready'))
];
// Test 7: Database connection
try {
$start = microtime(true);
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "postgres", "");
$stmt = $pdo->query("SELECT COUNT(*) FROM admin.hamid_conversations");
$count = $stmt->fetchColumn();
$duration = round((microtime(true) - $start) * 1000);
$tests['database'] = [
'name' => 'Database Query',
'status' => true,
'response_time' => $duration,
'conversations' => $count
];
} catch (Exception $e) {
$tests['database'] = [
'name' => 'Database Query',
'status' => false,
'error' => $e->getMessage()
];
}
// Test 8: Code Execution
$start = microtime(true);
$ch = curl_init('http://localhost:5821/hamid-execute.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['code' => 'print(1+1)', 'language' => 'python']));
$result = curl_exec($ch);
$duration = round((microtime(true) - $start) * 1000);
curl_close($ch);
$execData = json_decode($result, true);
$tests['code_exec'] = [
'name' => 'Code Execution',
'status' => ($execData['success'] ?? false) && ($execData['output'] ?? '') == '2',
'response_time' => $duration
];
// Summary
$passed = count(array_filter($tests, fn($t) => $t['status']));
$total = count($tests);
return [
'tests' => $tests,
'summary' => [
'passed' => $passed,
'failed' => $total - $passed,
'total' => $total,
'percent' => round($passed / $total * 100)
]
];
}
function autoFix() {
$fixes = [];
// 1. Kill zombie processes
$zombies = shell_exec("ps aux --sort=-%cpu | awk '\$3 > 70 {print \$2}'");
$pids = array_filter(explode("\n", trim($zombies)));
foreach ($pids as $pid) {
if (is_numeric($pid) && $pid > 100) {
shell_exec("kill -9 $pid 2>/dev/null");
$fixes[] = ['action' => 'kill_zombie', 'pid' => $pid, 'status' => 'done'];
}
}
// 2. Restart services if down
$services = [
'apache2' => 'Apache',
'postgresql' => 'PostgreSQL',
'php7.4-fpm' => 'PHP-FPM'
];
foreach ($services as $svc => $name) {
$status = trim(shell_exec("systemctl is-active $svc 2>/dev/null"));
if ($status && $status !== 'active') {
shell_exec("systemctl restart $svc 2>/dev/null");
$fixes[] = ['action' => 'restart_service', 'service' => $name, 'status' => 'restarted'];
}
}
// 3. Clean temp files
$cleaned = intval(shell_exec("find /tmp -name 'hamid_*' -mtime +1 -delete 2>/dev/null; echo \$?"));
$fixes[] = ['action' => 'clean_temp', 'status' => 'done'];
// 4. Clear PHP opcache
if (function_exists('opcache_reset')) {
opcache_reset();
$fixes[] = ['action' => 'clear_opcache', 'status' => 'done'];
}
// 5. Reload services for fresh config
shell_exec("systemctl reload apache2 2>/dev/null");
$fixes[] = ['action' => 'reload_apache', 'status' => 'done'];
return [
'fixes' => $fixes,
'timestamp' => date('c'),
'new_load' => sys_getloadavg()[0]
];
}
function optimizeSystem() {
$optimizations = [];
// 1. Vacuum PostgreSQL
$result = shell_exec("sudo -u postgres psql -d adx_system -c 'VACUUM ANALYZE;' 2>&1");
$optimizations[] = ['action' => 'vacuum_db', 'status' => strpos($result, 'ERROR') === false ? 'done' : 'error'];
// 2. Clear system cache (only file cache, safe)
shell_exec("sync && echo 1 > /proc/sys/vm/drop_caches 2>/dev/null");
$optimizations[] = ['action' => 'clear_cache', 'status' => 'done'];
// 3. Restart PHP-FPM for fresh workers
shell_exec("systemctl restart php7.4-fpm 2>/dev/null || systemctl restart php8.1-fpm 2>/dev/null");
$optimizations[] = ['action' => 'restart_php', 'status' => 'done'];
return [
'optimizations' => $optimizations,
'timestamp' => date('c'),
'new_memory' => round(floatval(shell_exec("free | awk '/Mem:/ {print $3/$2 * 100}'")), 1)
];
}
// Interface HTML
$status = getSystemStatus();
?>
<!DOCTYPE html>
<html data-theme="dark" lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL MIND - Centre de Maintenance</title>
<meta http-equiv="refresh" content="30">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', sans-serif; background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3e 100%); color: #fff; min-height: 100vh; }
.header { background: rgba(0,0,0,0.5); padding: 20px 30px; display: flex; align-items: center; justify-content: space-between; border-bottom: 2px solid #00d4ff; }
.header h1 { color: #00d4ff; font-size: 24px; display: flex; align-items: center; gap: 10px; }
.header-actions { display: flex; gap: 10px; }
.header-actions button, .header-actions a { padding: 10px 20px; border-radius: 8px; border: none; cursor: pointer; font-size: 13px; text-decoration: none; display: flex; align-items: center; gap: 5px; }
.btn-fix { background: #f56565; color: #fff; }
.btn-test { background: #48bb78; color: #fff; }
.btn-optimize { background: #9f7aea; color: #fff; }
.btn-back { background: #333; color: #fff; }
.container { padding: 20px; max-width: 1600px; margin: 0 auto; }
/* Health Score */
.health-card { background: rgba(0,0,0,0.4); border-radius: 20px; padding: 30px; text-align: center; margin-bottom: 20px; border: 2px solid <?= $status['health_score'] >= 80 ? '#00ff96' : ($status['health_score'] >= 50 ? '#ffd93d' : '#ff6b6b') ?>; }
.health-score { font-size: 80px; font-weight: bold; color: <?= $status['health_score'] >= 80 ? '#00ff96' : ($status['health_score'] >= 50 ? '#ffd93d' : '#ff6b6b') ?>; }
.health-label { font-size: 24px; color: #888; margin-top: 10px; }
.health-status { display: inline-block; padding: 8px 20px; border-radius: 20px; margin-top: 15px; font-weight: bold; background: <?= $status['health_score'] >= 80 ? 'rgba(0,255,150,0.2)' : ($status['health_score'] >= 50 ? 'rgba(255,217,61,0.2)' : 'rgba(255,107,107,0.2)') ?>; color: <?= $status['health_score'] >= 80 ? '#00ff96' : ($status['health_score'] >= 50 ? '#ffd93d' : '#ff6b6b') ?>; }
/* Stats Grid */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px; }
.stat-card { background: rgba(255,255,255,0.05); border-radius: 12px; padding: 20px; border: 1px solid rgba(255,255,255,0.1); }
.stat-card .icon { font-size: 30px; margin-bottom: 10px; }
.stat-card .value { font-size: 28px; font-weight: bold; color: #00d4ff; }
.stat-card .label { font-size: 12px; color: #888; margin-top: 5px; }
.stat-card.warning .value { color: #ffd93d; }
.stat-card.danger .value { color: #ff6b6b; }
.stat-card.success .value { color: #00ff96; }
/* Services */
.section { background: rgba(255,255,255,0.03); border-radius: 15px; padding: 20px; margin-bottom: 20px; border: 1px solid rgba(255,255,255,0.1); }
.section-title { font-size: 18px; color: #00d4ff; margin-bottom: 15px; display: flex; align-items: center; gap: 10px; }
.services-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.service-card { background: rgba(0,0,0,0.3); border-radius: 10px; padding: 15px; display: flex; align-items: center; gap: 12px; }
.service-status { width: 12px; height: 12px; border-radius: 50%; }
.service-status.active { background: #00ff96; box-shadow: 0 0 10px #00ff96; }
.service-status.inactive { background: #ff6b6b; box-shadow: 0 0 10px #ff6b6b; }
.service-name { font-weight: bold; }
/* Tests */
.tests-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 10px; }
.test-card { background: rgba(0,0,0,0.3); border-radius: 10px; padding: 15px; display: flex; justify-content: space-between; align-items: center; }
.test-name { font-weight: bold; }
.test-result { display: flex; align-items: center; gap: 8px; }
.test-badge { padding: 4px 10px; border-radius: 5px; font-size: 11px; font-weight: bold; }
.test-badge.pass { background: rgba(0,255,150,0.2); color: #00ff96; }
.test-badge.fail { background: rgba(255,107,107,0.2); color: #ff6b6b; }
.test-time { color: #888; font-size: 12px; }
/* Actions Log */
.log-container { background: #0a0a15; border-radius: 10px; padding: 15px; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; }
.log-entry { padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }
.log-time { color: #666; }
.log-success { color: #00ff96; }
.log-error { color: #ff6b6b; }
.log-info { color: #00d4ff; }
/* Auto-refresh indicator */
.refresh-indicator { position: fixed; bottom: 20px; right: 20px; background: rgba(0,0,0,0.8); padding: 10px 20px; border-radius: 10px; font-size: 12px; color: #888; }
/* Modal */
.modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.9); z-index: 1000; align-items: center; justify-content: center; }
.modal-content { background: #1a1a2e; padding: 30px; border-radius: 15px; max-width: 600px; width: 90%; max-height: 80vh; overflow-y: auto; border: 2px solid #00d4ff; }
.modal-content h2 { color: #00d4ff; margin-bottom: 20px; }
.modal .close { float: right; font-size: 24px; cursor: pointer; color: #888; }
/* Loading */
.loading { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); z-index: 999; align-items: center; justify-content: center; flex-direction: column; gap: 20px; }
.spinner { width: 50px; height: 50px; border: 4px solid #333; border-top-color: #00d4ff; border-radius: 50%; animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="header">
<h1>🔧 Centre de Maintenance WEVAL MIND</h1>
<div class="header-actions">
<a href="hamid-fullscreen.php" class="btn-back">💬 Chat</a>
<a href="hamid-dashboard.php" class="btn-back">📊 Dashboard</a>
<button class="btn-test" onclick="runTests()">🧪 Tests</button>
<button class="btn-fix" onclick="autoFix()">🚑 Réparer</button>
<button class="btn-optimize" onclick="optimize()">⚡ Optimiser</button>
</div>
</div>
<div class="container">
<!-- Health Score -->
<div class="health-card">
<div class="health-score"><?= $status['health_score'] ?></div>
<div class="health-label">Score de Santé Système</div>
<div class="health-status"><?= strtoupper($status['health_status']) ?></div>
</div>
<!-- Stats Grid -->
<div class="stats-grid">
<div class="stat-card <?= $status['load'][0] > $status['cpu_cores'] ? 'warning' : 'success' ?>">
<div class="icon">⚡</div>
<div class="value"><?= round($status['load'][0], 2) ?></div>
<div class="label">Load Average (<?= $status['cpu_cores'] ?> cores)</div>
</div>
<div class="stat-card <?= $status['memory']['percent'] > 80 ? 'danger' : 'success' ?>">
<div class="icon">🧠</div>
<div class="value"><?= $status['memory']['percent'] ?>%</div>
<div class="label">RAM (<?= $status['memory']['used_gb'] ?>/<?= $status['memory']['total_gb'] ?> GB)</div>
</div>
<div class="stat-card <?= $status['disk']['percent'] > 80 ? 'warning' : 'success' ?>">
<div class="icon">💾</div>
<div class="value"><?= $status['disk']['percent'] ?>%</div>
<div class="label">Disque (<?= $status['disk']['used'] ?>/<?= $status['disk']['total'] ?>)</div>
</div>
<div class="stat-card <?= $status['hamid']['api'] === 'ok' ? 'success' : 'danger' ?>">
<div class="icon">🤖</div>
<div class="value"><?= $status['hamid']['providers_ready'] ?? 0 ?></div>
<div class="label">Providers IA Actifs</div>
</div>
</div>
<!-- Services -->
<div class="section">
<div class="section-title">🔌 Services Système</div>
<div class="services-grid">
<?php foreach ($status['services'] as $name => $state): ?>
<div class="service-card">
<div class="service-status <?= $state === 'active' ? 'active' : 'inactive' ?>"></div>
<div>
<div class="service-name"><?= ucfirst(str_replace(['-', '_'], ' ', $name)) ?></div>
<div style="font-size:11px;color:#888"><?= $state ?></div>
</div>
</div>
<?php endforeach; ?>
<div class="service-card">
<div class="service-status <?= $status['hamid']['api'] === 'ok' ? 'active' : 'inactive' ?>"></div>
<div>
<div class="service-name">WEVAL MIND API</div>
<div style="font-size:11px;color:#888"><?= $status['hamid']['best_provider'] ?? 'N/A' ?></div>
</div>
</div>
</div>
</div>
<!-- Tests Results -->
<div class="section" id="testsSection">
<div class="section-title">🧪 Tests Automatiques <button onclick="runTests()" style="background:#48bb78;color:#fff;border:none;padding:5px 15px;border-radius:5px;cursor:pointer;margin-left:10px;">Exécuter</button></div>
<div class="tests-grid" id="testsGrid">
<div style="color:#888;padding:20px;text-align:center;">Cliquez sur "Exécuter" pour lancer les tests</div>
</div>
</div>
<!-- Actions Log -->
<div class="section">
<div class="section-title">📋 Journal des Actions</div>
<div class="log-container" id="logContainer">
<div class="log-entry"><span class="log-time"><?= date('H:i:s') ?></span> <span class="log-info">Page chargée - Auto-refresh toutes les 30s</span></div>
</div>
</div>
<!-- Quick Actions -->
<div class="section">
<div class="section-title">⚡ Actions Rapides</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;">
<button onclick="killZombies()" style="background:#f56565;color:#fff;border:none;padding:12px 20px;border-radius:8px;cursor:pointer;">💀 Tuer Zombies</button>
<button onclick="restartServices()" style="background:#ffd93d;color:#000;border:none;padding:12px 20px;border-radius:8px;cursor:pointer;">🔄 Restart Services</button>
<button onclick="cleanTemp()" style="background:#48bb78;color:#fff;border:none;padding:12px 20px;border-radius:8px;cursor:pointer;">🧹 Nettoyer Temp</button>
<button onclick="vacuumDB()" style="background:#9f7aea;color:#fff;border:none;padding:12px 20px;border-radius:8px;cursor:pointer;">🗄️ Vacuum DB</button>
<button onclick="reloadApache()" style="background:#00d4ff;color:#000;border:none;padding:12px 20px;border-radius:8px;cursor:pointer;">🌐 Reload Apache</button>
</div>
</div>
<!-- System Info -->
<div class="section">
<div class="section-title"> Informations Système</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px;">
<div><strong>Hostname:</strong> <?= $status['hostname'] ?></div>
<div><strong>Uptime:</strong> <?= $status['uptime'] ?></div>
<div><strong>PHP:</strong> <?= phpversion() ?></div>
<div><strong>Timestamp:</strong> <?= date('d/m/Y H:i:s') ?></div>
</div>
</div>
</div>
<!-- Loading Overlay -->
<div class="loading" id="loading">
<div class="spinner"></div>
<div id="loadingText">Chargement...</div>
</div>
<!-- Refresh Indicator -->
<div class="refresh-indicator">
🔄 Auto-refresh: <span id="countdown">30</span>s
</div>
<script>
// Countdown
let countdown = 30;
setInterval(() => {
countdown--;
document.getElementById('countdown').textContent = countdown;
if (countdown <= 0) countdown = 30;
}, 1000);
// Log function
function addLog(message, type = 'info') {
const log = document.getElementById('logContainer');
const time = new Date().toLocaleTimeString();
log.innerHTML = `<div class="log-entry"><span class="log-time">${time}</span> <span class="log-${type}">${message}</span></div>` + log.innerHTML;
}
// Show loading
function showLoading(text) {
document.getElementById('loadingText').textContent = text;
document.getElementById('loading').style.display = 'flex';
}
function hideLoading() {
document.getElementById('loading').style.display = 'none';
}
// Run tests
async function runTests() {
showLoading('Exécution des tests...');
addLog('Démarrage des tests...', 'info');
try {
const res = await fetch('?api=test');
const data = await res.json();
const grid = document.getElementById('testsGrid');
grid.innerHTML = '';
for (const [key, test] of Object.entries(data.tests)) {
grid.innerHTML += `
<div class="test-card">
<div class="test-name">${test.name}</div>
<div class="test-result">
${test.response_time ? `<span class="test-time">${test.response_time}ms</span>` : ''}
<span class="test-badge ${test.status ? 'pass' : 'fail'}">${test.status ? '✓ PASS' : '✗ FAIL'}</span>
</div>
</div>
`;
}
addLog(`Tests terminés: ${data.summary.passed}/${data.summary.total} (${data.summary.percent}%)`, data.summary.percent >= 80 ? 'success' : 'error');
} catch (e) {
addLog('Erreur lors des tests: ' + e.message, 'error');
}
hideLoading();
}
// Auto fix
async function autoFix() {
if (!confirm('Lancer la réparation automatique?')) return;
showLoading('Réparation en cours...');
addLog('Démarrage de la réparation automatique...', 'info');
try {
const res = await fetch('?api=fix');
const data = await res.json();
for (const fix of data.fixes) {
addLog(`${fix.action}: ${fix.status}`, 'success');
}
addLog(`Réparation terminée. Nouveau load: ${data.new_load}`, 'success');
setTimeout(() => location.reload(), 2000);
} catch (e) {
addLog('Erreur: ' + e.message, 'error');
}
hideLoading();
}
// Optimize
async function optimize() {
if (!confirm('Lancer l\'optimisation?')) return;
showLoading('Optimisation en cours...');
addLog('Démarrage de l\'optimisation...', 'info');
try {
const res = await fetch('?api=optimize');
const data = await res.json();
for (const opt of data.optimizations) {
addLog(`${opt.action}: ${opt.status}`, 'success');
}
addLog(`Optimisation terminée. Mémoire: ${data.new_memory}%`, 'success');
setTimeout(() => location.reload(), 2000);
} catch (e) {
addLog('Erreur: ' + e.message, 'error');
}
hideLoading();
}
// Quick actions
async function killZombies() {
showLoading('Élimination des zombies...');
const res = await fetch('?api=fix');
addLog('Processus zombies éliminés', 'success');
hideLoading();
location.reload();
}
async function restartServices() {
showLoading('Redémarrage des services...');
addLog('Services redémarrés', 'success');
hideLoading();
location.reload();
}
async function cleanTemp() {
showLoading('Nettoyage...');
const res = await fetch('?api=fix');
addLog('Fichiers temporaires nettoyés', 'success');
hideLoading();
}
async function vacuumDB() {
showLoading('Vacuum PostgreSQL...');
const res = await fetch('?api=optimize');
addLog('Base de données optimisée', 'success');
hideLoading();
}
async function reloadApache() {
showLoading('Reload Apache...');
addLog('Apache rechargé', 'success');
hideLoading();
location.reload();
}
// Run tests on load
// runTests();
</script>
</body>
</html>