metrics: fix root device detection

the existing logic does not work for device like /dev/md1 (on the dedis)
This commit is contained in:
Girish Ramakrishnan
2025-10-15 11:24:07 +02:00
parent 155af33b0c
commit 41c00eda74

View File

@@ -15,9 +15,9 @@ const apps = require('./apps.js'),
fs = require('node:fs'), fs = require('node:fs'),
net = require('node:net'), net = require('node:net'),
os = require('node:os'), os = require('node:os'),
path = require('node:path'),
{ Readable } = require('node:stream'), { Readable } = require('node:stream'),
safe = require('safetydance'), safe = require('safetydance'),
shell = require('./shell.js')('metrics'),
superagent = require('@cloudron/superagent'), superagent = require('@cloudron/superagent'),
_ = require('./underscore.js'); _ = require('./underscore.js');
@@ -99,23 +99,29 @@ async function readCpuMetrics() {
return { userMsecs, sysMsecs }; // these values are the times spent since system start return { userMsecs, sysMsecs }; // these values are the times spent since system start
} }
async function readDiskMetrics() { let gRootDiskName = null;
async function getRootDiskName() {
if (gRootDiskName) return gRootDiskName;
const mounts = await fs.promises.readFile('/proc/mounts', { encoding: 'utf8' }); const mounts = await fs.promises.readFile('/proc/mounts', { encoding: 'utf8' });
const rootLine = mounts.split('\n').find(line => line.split(' ')[1] === '/'); const rootfsLine = mounts.split('\n').find(line => line.split(' ')[1] === '/');
if (!rootLine) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Root mount not found'); if (!rootfsLine) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Root mount not found');
const devicePath = rootfsLine.split(' ')[0]; // eg. /dev/foo . This can be a partition or a disk path
const devicePath = rootLine.split(' ')[0]; // e.g., "/dev/sda1" // -n is no headings , -d is no holder devices or slaves , -o is output format . PKNAME is parent kernel name
const base = path.basename(devicePath); // remove /dev/ const output = await shell.spawn('lsblk', [ '-ndo', 'PKNAME', devicePath ], { encoding: 'utf8' });
const match = base.match(/^(.*?)(p?[0-9]+)?$/); gRootDiskName = output.trim() || devicePath.replace('/dev/', '');
const blockDevice = match ? match[1] : base; return gRootDiskName;
if (!blockDevice) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Could not find root block device name'); }
async function readDiskMetrics() {
const rootDiskName = await getRootDiskName();
const diskstats = await fs.promises.readFile('/proc/diskstats', { encoding: 'utf8' }); const diskstats = await fs.promises.readFile('/proc/diskstats', { encoding: 'utf8' });
const statsLine = diskstats.split('\n').find(l => l.includes(` ${blockDevice} `)); const statsLine = diskstats.split('\n').find(l => l.includes(` ${rootDiskName} `));
if (!statsLine) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Could not get disk stats'); if (!statsLine) throw new BoxError(BoxError.EXTERNAL_ERROR, `Could not get disk stats of ${rootDiskName}`);
const parts = statsLine.trim().split(/\s+/); const parts = statsLine.trim().split(/\s+/);
const sectorsRead = parseInt(parts[5], 10); // field 6 . one sectiro is 512 bytes const sectorsRead = parseInt(parts[5], 10); // field 6 . one sector is 512 bytes
const sectorsWrite = parseInt(parts[9], 10); // field 10 const sectorsWrite = parseInt(parts[9], 10); // field 10
const blockRead = sectorsRead * 512; const blockRead = sectorsRead * 512;
const blockWrite = sectorsWrite * 512; const blockWrite = sectorsWrite * 512;