node-system-stats
Version:
Comprehensive library for monitoring system statistics including CPU, memory, disk, network, battery, and process information with time-series monitoring
254 lines • 9.83 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCpuTemperature = exports.avgClockMHz = exports.clockMHz = exports.getLoadAverage = exports.usagePercent = exports.cpuModel = exports.totalCores = void 0;
const os_1 = __importDefault(require("os"));
const util_1 = require("../utils/util");
/**
* Total number of CPU cores
*/
exports.totalCores = os_1.default.cpus().length;
/**
* CPU model name
*/
exports.cpuModel = os_1.default.cpus()[0]?.model || 'Unknown';
/**
* Get CPU usage percentage
* @param options Optional configuration
* @returns Promise resolving to CPU usage percentage
*/
function usagePercent(options) {
return new Promise((resolve, reject) => {
const opts = {
coreIndex: options?.coreIndex ?? -1,
sampleMs: options?.sampleMs ?? 1000,
};
// Validate core index
if (opts.coreIndex >= exports.totalCores) {
return reject((0, util_1.createCoreError)(opts.coreIndex, exports.totalCores));
}
try {
const startMeasure = cpuAverage(opts.coreIndex);
// Set delay to calculate usage
setTimeout(() => {
const endMeasure = cpuAverage(opts.coreIndex);
// Calculate the difference in idle and total time between the measurements
const idleDifference = endMeasure.idle - startMeasure.idle;
const totalDifference = endMeasure.total - startMeasure.total;
// Calculate the average percentage CPU usage
const percentageCpu = 100 - ~~(100 * idleDifference / totalDifference);
resolve({
percent: percentageCpu,
seconds: opts.sampleMs / 1000
});
}, opts.sampleMs);
}
catch (err) {
reject(err);
}
});
}
exports.usagePercent = usagePercent;
/**
* Get CPU load average
* @returns Load average information
*/
function getLoadAverage() {
const [oneMinute, fiveMinutes, fifteenMinutes] = os_1.default.loadavg();
return {
oneMinute,
fiveMinutes,
fifteenMinutes,
cpuCount: exports.totalCores
};
}
exports.getLoadAverage = getLoadAverage;
/**
* Get CPU clock speed for all or a specific CPU core
* @param coreIndex Optional core index (default: all cores)
* @returns CPU clock speed in MHz (average if no core specified)
*/
function clockMHz(coreIndex) {
const cpus = os_1.default.cpus();
if (coreIndex !== undefined) {
if (coreIndex >= exports.totalCores) {
throw (0, util_1.createCoreError)(coreIndex, exports.totalCores);
}
return cpus[coreIndex].speed;
}
return cpus.map(cpu => cpu.speed);
}
exports.clockMHz = clockMHz;
/**
* Get average clock speed across all CPU cores
* @returns Average clock speed in MHz
*/
function avgClockMHz() {
const cpus = os_1.default.cpus();
const totalSpeed = cpus.reduce((acc, cpu) => acc + cpu.speed, 0);
return totalSpeed / cpus.length;
}
exports.avgClockMHz = avgClockMHz;
/**
* Get CPU temperature (if available)
* @returns Promise resolving to CPU temperature information or null if not available
*/
async function getCpuTemperature() {
try {
const platform = process.platform;
if (platform === 'linux') {
// Linux implementation
try {
const { stdout: thermFileName } = await (0, util_1.execAsync)('find /sys/class/thermal -name "thermal_zone*" | head -n 1');
if (!thermFileName.trim()) {
return null;
}
const basePath = thermFileName.trim();
const { stdout: tempStr } = await (0, util_1.execAsync)(`cat ${basePath}/temp`);
const { stdout: typeStr } = await (0, util_1.execAsync)(`cat ${basePath}/type`);
// Convert millidegrees to degrees
const temp = parseInt(tempStr.trim(), 10) / 1000;
// Try to get multiple core temperatures
let coreTemps = [];
try {
// Try to find core temp sensors
const { stdout: sensorPaths } = await (0, util_1.execAsync)('find /sys/class/hwmon -name "hwmon*" | head -n 1');
if (sensorPaths.trim()) {
const sensorPath = sensorPaths.trim();
// Try to read multiple core temps
for (let i = 1; i <= exports.totalCores; i++) {
try {
const { stdout: coreTempStr } = await (0, util_1.execAsync)(`cat ${sensorPath}/temp${i}_input 2>/dev/null || echo 0`);
if (coreTempStr.trim() !== '0') {
coreTemps.push(parseInt(coreTempStr.trim(), 10) / 1000);
}
}
catch (err) {
// Skip this core if we can't read it
}
}
}
}
catch (err) {
// Fall back to main temperature for all cores
coreTemps = Array(exports.totalCores).fill(temp);
}
// If we couldn't get core temps, fill with main temp
if (coreTemps.length === 0) {
coreTemps = Array(exports.totalCores).fill(temp);
}
return {
main: temp,
cores: coreTemps
};
}
catch (err) {
return null;
}
}
else if (platform === 'darwin') {
// macOS implementation using smc
try {
const { stdout } = await (0, util_1.execAsync)('which smc >/dev/null 2>&1 && smc -k TC0P -r | cut -d " " -f 4');
if (!stdout.trim()) {
return null;
}
// Parse the temperature from hex string
const temp = parseInt(stdout.trim().replace(/[^0-9A-Fa-f]/g, ''), 16) / 100;
// Try to get core temps
const coreTemps = [];
for (let i = 0; i < exports.totalCores && i < 8; i++) {
try {
const { stdout: coreTempStr } = await (0, util_1.execAsync)(`smc -k TC${i}C -r | cut -d " " -f 4`);
if (coreTempStr.trim()) {
const coreTemp = parseInt(coreTempStr.trim().replace(/[^0-9A-Fa-f]/g, ''), 16) / 100;
coreTemps.push(coreTemp);
}
}
catch (err) {
// Skip this core if we can't read it
}
}
// If we couldn't get core temps, fill with main temp
if (coreTemps.length === 0) {
for (let i = 0; i < exports.totalCores; i++) {
coreTemps.push(temp);
}
}
return {
main: temp,
cores: coreTemps
};
}
catch (err) {
return null;
}
}
else if (platform === 'win32') {
// Windows implementation using wmic
try {
const { stdout } = await (0, util_1.execAsync)('wmic /namespace:\\\\root\\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature');
const lines = stdout.trim().split('\n').filter(line => line.trim() !== 'CurrentTemperature');
if (lines.length === 0) {
return null;
}
// Parse the temperature (in Kelvin * 10) to Celsius
const tempKelvin = parseInt(lines[0].trim(), 10);
const tempCelsius = tempKelvin / 10 - 273.15;
// Windows doesn't easily provide per-core temps
const coreTemps = Array(exports.totalCores).fill(tempCelsius);
return {
main: tempCelsius,
cores: coreTemps
};
}
catch (err) {
return null;
}
}
return null;
}
catch (error) {
console.error('Error getting CPU temperature:', error);
return null;
}
}
exports.getCpuTemperature = getCpuTemperature;
/**
* Calculate the average CPU usage across all cores or for a specific core
* @param coreIndex Optional core index (default: all cores)
* @returns Object with idle and total CPU time
* @private
*/
function cpuAverage(coreIndex = -1) {
const cpus = os_1.default.cpus();
if (coreIndex >= 0) {
if (coreIndex >= cpus.length) {
throw (0, util_1.createCoreError)(coreIndex, cpus.length);
}
const cpu = cpus[coreIndex];
const total = Object.values(cpu.times).reduce((acc, tv) => acc + tv, 0);
return {
idle: cpu.times.idle,
total,
};
}
else {
// Calculate the average of all cores
let totalIdle = 0;
let totalTick = 0;
for (const cpu of cpus) {
for (const type in cpu.times) {
totalTick += cpu.times[type];
}
totalIdle += cpu.times.idle;
}
return {
idle: totalIdle,
total: totalTick,
};
}
}
//# sourceMappingURL=cpu.js.map
;