Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | /**
* Parsers de métriques système — CPU, RAM, disque.
*
* Interprètent les sorties des commandes top, free et df
* exécutées via SSH sur les serveurs distants.
*
* Utilisés par : dashboard, overview, metricsCollector.
*
* @module utils/parsers
*/
/**
* Parse la sortie de `top -bn1` pour extraire le pourcentage CPU.
* Cherche la ligne "%Cpu(s):" et extrait la valeur "id" (idle).
* CPU usage = 100 - idle.
*
* @param {string} raw — Sortie brute de top
* @returns {{ use_percent: number }|null}
*/
function parseCpu(raw) {
const cpuLine = raw.split('\n').find((l) => l.includes('%Cpu(s)'));
if (!cpuLine) return null;
// ReDoS-safe : \d+ et \.\d+ sont disjoints (le point separe), backtracking lineaire O(n).
// De plus, l'entree provient de `top -bn1` (sortie bornee d'une commande systeme).
const idleMatch = cpuLine.match(/(\d+(?:\.\d+)?)\s+id/); // NOSONAR — regex safe (classes disjointes, entree bornee)
const idle = idleMatch ? Number.parseFloat(idleMatch[1]) : null;
return idle == null ? null : { use_percent: Math.round(100 - idle) };
}
/**
* Parse la sortie de `free -m` pour l'utilisation mémoire.
*
* @param {string} raw — Sortie brute de free -m
* @returns {{ total_mb: number, used_mb: number, available_mb: number, use_percent: number }|null}
*/
function parseFree(raw) {
const lines = raw.trim().split('\n');
const memLine = lines.find((l) => l.startsWith('Mem:'));
if (!memLine) return null;
const parts = memLine.split(/\s+/);
const total = Number.parseInt(parts[1]);
const used = Number.parseInt(parts[2]);
return {
total_mb: total,
used_mb: used,
available_mb: Number.parseInt(parts[6]) || total - used,
use_percent: Math.round((used / total) * 100),
};
}
/**
* Parse la sortie de `df -h` et retourne les partitions principales.
* Filtre pour ne garder que les vrais systèmes de fichiers (/, /dev, overlay).
*
* @param {string} raw — Sortie brute de df -h
* @returns {Array<{ filesystem: string, size: string, used: string, available: string, use_percent: number, mount: string }>}
*/
function parseDf(raw) {
const lines = raw.trim().split('\n').slice(1);
return lines
.map((line) => {
const parts = line.split(/\s+/);
if (parts.length < 6) return null;
return {
filesystem: parts[0],
size: parts[1],
used: parts[2],
available: parts[3],
use_percent: Number.parseInt(parts[4]),
mount: parts[5],
};
})
.filter(Boolean)
.filter((d) => d.filesystem.startsWith('/') || d.filesystem.startsWith('overlay'));
}
module.exports = { parseCpu, parseFree, parseDf };
|