fix: métriques monitoring via host-metrics.json (RAM/CPU réels hôte LXC)

This commit is contained in:
manus-admin 2026-06-01 02:02:08 +02:00
parent ea7deec23c
commit 17d86b5000
1 changed files with 33 additions and 10 deletions

View File

@ -183,9 +183,26 @@ function getServerMetrics() {
const { execSync } = require("child_process"); const { execSync } = require("child_process");
const fs = require("fs"); const fs = require("fs");
try { try {
// Lecture directe de /proc (monté depuis l'hôte via le namespace PID du conteneur) // ===== Méthode 1 : Lire host-metrics.json généré par le script système de l'hôte =====
// Pas besoin de nsenter : /proc dans le conteneur reflète l'hôte // Ce fichier est mis à jour toutes les 30s par /opt/manus-deploy/host-metrics.sh
// Il contient les vraies métriques de l'hôte LXC (pas du nœud physique)
const hostMetricsPath = '/opt/manus-deploy/host-metrics.json';
if (fs.existsSync(hostMetricsPath)) {
try {
const raw = fs.readFileSync(hostMetricsPath, 'utf8');
const hostMetrics = JSON.parse(raw);
// Vérifier que le fichier est récent (moins de 2 minutes)
const fileAge = Date.now() - new Date(hostMetrics.timestamp).getTime();
if (fileAge < 120000 && hostMetrics.memory && hostMetrics.memory.total > 0) {
return resolve({
...hostMetrics,
timestamp: new Date().toISOString()
});
}
} catch(e) {}
}
// ===== Méthode 2 : Lecture directe de /proc (fallback) =====
// CPU : mesure via cgroup v2 usage_usec (méthode précise pour conteneur LXC) // CPU : mesure via cgroup v2 usage_usec (méthode précise pour conteneur LXC)
// Fallback sur /proc/stat normalisé par nproc si cgroup v2 non disponible // Fallback sur /proc/stat normalisé par nproc si cgroup v2 non disponible
let cpuUsage = 0; let cpuUsage = 0;
@ -303,8 +320,10 @@ function getServerMetrics() {
const sReclaimable = memMap['SReclaimable'] || 0; const sReclaimable = memMap['SReclaimable'] || 0;
const shmem = memMap['Shmem'] || 0; const shmem = memMap['Shmem'] || 0;
memCached = (memMap['Cached'] || 0) + (sReclaimable > shmem ? sReclaimable - shmem : 0); memCached = (memMap['Cached'] || 0) + (sReclaimable > shmem ? sReclaimable - shmem : 0);
memUsed = memTotal - memFree - memBuffers - memCached; // Utiliser MemAvailable comme référence car elle inclut les caches libérables
if (memUsed < 0) memUsed = memTotal - memAvailable; // Identique à ce que `free` affiche dans la colonne 'disponible'
memUsed = memTotal - memAvailable;
if (memUsed < 0) memUsed = 0;
} }
} catch(e) { } catch(e) {
// Fallback ultime // Fallback ultime
@ -317,19 +336,22 @@ function getServerMetrics() {
} catch(e2) {} } catch(e2) {}
} }
// Disque : df sur la racine du conteneur (= hôte car pas de volume overlay) // Disque : df sur /opt/manus-deploy (point de montage de l'hôte LXC)
// Utiliser /opt/manus-deploy car c'est un volume monté depuis l'hôte
let diskTotal = 0, diskUsed = 0, diskFree = 0; let diskTotal = 0, diskUsed = 0, diskFree = 0;
try { try {
const diskRaw = execSync('df -B1 / | tail -1').toString().trim().split(/\s+/); const diskPath = fs.existsSync('/opt/manus-deploy') ? '/opt/manus-deploy' : '/';
const diskRaw = execSync('df -B1 ' + diskPath + ' | tail -1').toString().trim().split(/\s+/);
diskTotal = parseInt(diskRaw[1]); diskTotal = parseInt(diskRaw[1]);
diskUsed = parseInt(diskRaw[2]); diskUsed = parseInt(diskRaw[2]);
diskFree = parseInt(diskRaw[3]); diskFree = parseInt(diskRaw[3]);
} catch(e) {} } catch(e) {}
// Uptime et load // Uptime et load : utiliser /host/proc si disponible (hôte LXC réel)
const uptimeRaw = fs.readFileSync('/proc/uptime', 'utf8').trim().split(' '); const procBase = fs.existsSync('/host/proc/uptime') ? '/host/proc' : '/proc';
const uptimeRaw = fs.readFileSync(procBase + '/uptime', 'utf8').trim().split(' ');
const uptimeSeconds = parseFloat(uptimeRaw[0]); const uptimeSeconds = parseFloat(uptimeRaw[0]);
const loadRaw = fs.readFileSync('/proc/loadavg', 'utf8').trim().split(' '); const loadRaw = fs.readFileSync(procBase + '/loadavg', 'utf8').trim().split(' ');
const load1 = parseFloat(loadRaw[0]); const load1 = parseFloat(loadRaw[0]);
const load5 = parseFloat(loadRaw[1]); const load5 = parseFloat(loadRaw[1]);
const load15 = parseFloat(loadRaw[2]); const load15 = parseFloat(loadRaw[2]);
@ -337,7 +359,8 @@ function getServerMetrics() {
// Réseau // Réseau
let netRx = 0, netTx = 0; let netRx = 0, netTx = 0;
try { try {
const netDev = fs.readFileSync('/proc/net/dev', 'utf8'); const netDevPath = fs.existsSync('/host/proc/net/dev') ? '/host/proc/net/dev' : '/proc/net/dev';
const netDev = fs.readFileSync(netDevPath, 'utf8');
const netLine = netDev.split('\n').find(l => /eth0|ens|enp/.test(l)); const netLine = netDev.split('\n').find(l => /eth0|ens|enp/.test(l));
if (netLine) { if (netLine) {
const parts = netLine.trim().split(/\s+/); const parts = netLine.trim().split(/\s+/);