@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
130 lines • 5.44 kB
JavaScript
// We want to keep `system` export to be used as namespace
import os from "node:os";
import path from "node:path";
// We want to keep `system` export as it's more readable and easier to understand
import system from "systeminformation";
/**
* Singleton class to collect and provide system information
*/
class System {
constructor() {
// static data only needs to be collected once
this.staticDataCollected = false;
// disk I/O is not measurable in some environments
this.diskIOMeasurable = true;
this.cpuCores = 0;
this.cpuThreads = 0;
this.cpuNodeSystemSecondsTotal = 0;
this.cpuNodeUserSecondsTotal = 0;
// Note: CPU I/O wait is not measured by os.cpus()
this.cpuNodeIOWaitSecondsTotal = 0;
this.cpuNodeIdleSecondsTotal = 0;
this.memoryNodeBytesTotal = 0;
this.memoryNodeBytesFree = 0;
this.memoryNodeBytesCached = 0;
this.memoryNodeBytesBuffers = 0;
this.diskNodeBytesTotal = 0;
this.diskNodeBytesFree = 0;
// Note: disk I/O seconds is currently unused by beaconcha.in
this.diskNodeIOSeconds = 0;
this.diskNodeReadsTotal = 0;
this.diskNodeWritesTotal = 0;
this.networkNodeBytesTotalReceive = 0;
this.networkNodeBytesTotalTransmit = 0;
this.miscNodeBootTsSeconds = 0;
this.miscOs = "unk";
}
/**
* Collect system data and update cached values
*/
async collectData(logger) {
const debug = (dataType, e) => logger.debug(`Failed to collect ${dataType} data`, {}, e);
await Promise.all([
this.collectStaticData().catch((e) => debug("static system", e)),
this.collectCpuData().catch((e) => debug("CPU", e)),
this.collectMemoryData().catch((e) => debug("memory", e)),
this.collectDiskData().catch((e) => debug("disk", e)),
this.collectNetworkData().catch((e) => debug("network", e)),
]);
this.miscNodeBootTsSeconds = this.getSystemBootTime();
}
async collectStaticData() {
if (this.staticDataCollected)
return;
const cpu = await system.cpu();
// Note: inside container this might be inaccurate as
// physicalCores in some cases is the count of logical CPU cores
this.cpuCores = cpu.physicalCores;
this.cpuThreads = cpu.cores;
this.miscOs = this.getNormalizedOsVersion();
this.staticDataCollected = true;
}
async collectCpuData() {
const cpuTimes = {};
for (const cpu of os.cpus()) {
// sum up CPU times per mode and convert to seconds
for (const [mode, time] of Object.entries(cpu.times)) {
if (cpuTimes[mode] == null)
cpuTimes[mode] = 0;
cpuTimes[mode] += Math.floor(time / 1000);
}
}
// Note: currently beaconcha.in expects system CPU seconds to be everything
this.cpuNodeSystemSecondsTotal = Object.values(cpuTimes).reduce((total, time) => total + time, 0);
this.cpuNodeUserSecondsTotal = cpuTimes.user;
this.cpuNodeIdleSecondsTotal = cpuTimes.idle;
}
async collectMemoryData() {
const memory = await system.mem();
this.memoryNodeBytesTotal = memory.total;
this.memoryNodeBytesFree = memory.free;
this.memoryNodeBytesCached = memory.cached;
this.memoryNodeBytesBuffers = memory.buffers;
}
async collectDiskData() {
const fileSystems = await system.fsSize();
// get file system root, on windows this is the name of the hard disk partition
const rootFs = process.platform === "win32" ? process.cwd().split(path.sep)[0] : "/";
// only consider root file system, if it does not exist use first entry in the list
const fileSystem = fileSystems.find((fs) => fs.mount === rootFs) ?? fileSystems[0];
this.diskNodeBytesTotal = fileSystem.size;
this.diskNodeBytesFree = fileSystem.available;
if (this.diskIOMeasurable) {
const disk = await system.disksIO();
if (disk != null && disk.rIO !== 0) {
// Note: rIO and wIO might not be available inside container
// see https://github.com/sebhildebrandt/systeminformation/issues/777
this.diskNodeReadsTotal = disk.rIO;
this.diskNodeWritesTotal = disk.wIO;
}
else {
this.diskIOMeasurable = false;
}
}
}
async collectNetworkData() {
// defaults to first external network interface
const [network] = await system.networkStats();
// Note: rx_bytes and tx_bytes will be inaccurate if process
// runs inside container as it only captures local network traffic
this.networkNodeBytesTotalReceive = network.rx_bytes;
this.networkNodeBytesTotalTransmit = network.tx_bytes;
}
getNormalizedOsVersion() {
switch (process.platform) {
case "linux":
return "lin";
case "darwin":
return "mac";
case "win32":
return "win";
default:
return "unk";
}
}
getSystemBootTime() {
return Math.floor(Date.now() / 1000 - os.uptime());
}
}
export default new System();
//# sourceMappingURL=system.js.map