fix: métriques monitoring via host-metrics.json (RAM/CPU réels hôte LXC)
This commit is contained in:
parent
ea7deec23c
commit
17d86b5000
|
|
@ -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+/);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue