All files / src/utils parsers.js

0% Statements 0/24
0% Branches 0/14
0% Functions 0/7
0% Lines 0/19

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 };