mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-19 05:05:44 +08:00
139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
import os from 'node:os';
|
|
import EventEmitter from 'node:events';
|
|
|
|
export interface SystemStatus {
|
|
cpu: {
|
|
model: string,
|
|
speed: string
|
|
usage: {
|
|
system: string
|
|
qq: string
|
|
},
|
|
core: number
|
|
},
|
|
memory: {
|
|
total: string
|
|
usage: {
|
|
system: string
|
|
qq: string
|
|
}
|
|
},
|
|
arch: string
|
|
}
|
|
|
|
export class StatusHelper {
|
|
private psCpuUsage = process.cpuUsage();
|
|
private psCurrentTime = process.hrtime();
|
|
private cpuTimes = os.cpus().map(cpu => cpu.times);
|
|
|
|
private replaceNaN (value: number) {
|
|
return isNaN(value) ? 0 : value;
|
|
}
|
|
|
|
private sysCpuInfo () {
|
|
const currentTimes = os.cpus().map(cpu => cpu.times);
|
|
const { total, active } = currentTimes.map((times, index) => {
|
|
const prevTimes = this.cpuTimes[index];
|
|
const totalCurrent = times.user + times.nice + times.sys + times.idle + times.irq;
|
|
const totalPrev = (prevTimes?.user ?? 0) + (prevTimes?.nice ?? 0) + (prevTimes?.sys ?? 0) + (prevTimes?.idle ?? 0) + (prevTimes?.irq ?? 0);
|
|
const activeCurrent = totalCurrent - times.idle;
|
|
const activePrev = totalPrev - (prevTimes?.idle ?? 0);
|
|
return {
|
|
total: totalCurrent - totalPrev,
|
|
active: activeCurrent - activePrev,
|
|
};
|
|
}).reduce((acc, cur) => ({
|
|
total: acc.total + cur.total,
|
|
active: acc.active + cur.active,
|
|
}), { total: 0, active: 0 });
|
|
this.cpuTimes = currentTimes;
|
|
return {
|
|
usage: this.replaceNaN(((active / total) * 100)).toFixed(2),
|
|
model: os.cpus()[0]?.model ?? 'none',
|
|
speed: os.cpus()[0]?.speed ?? 0,
|
|
core: os.cpus().length,
|
|
};
|
|
}
|
|
|
|
private sysMemoryUsage () {
|
|
const { total, free } = { total: os.totalmem(), free: os.freemem() };
|
|
return ((total - free) / 1024 / 1024).toFixed(2);
|
|
}
|
|
|
|
private qqUsage () {
|
|
const mem = process.memoryUsage();
|
|
const numCpus = os.cpus().length;
|
|
const usageDiff = process.cpuUsage(this.psCpuUsage);
|
|
const endTime = process.hrtime(this.psCurrentTime);
|
|
this.psCpuUsage = process.cpuUsage();
|
|
this.psCurrentTime = process.hrtime();
|
|
const usageMS = (usageDiff.user + usageDiff.system) / 1e3;
|
|
const totalMS = endTime[0] * 1e3 + endTime[1] / 1e6;
|
|
const normPercent = (usageMS / totalMS / numCpus) * 100;
|
|
return {
|
|
cpu: this.replaceNaN(normPercent).toFixed(2),
|
|
memory: ((mem.heapTotal + mem.external + mem.arrayBuffers) / 1024 / 1024).toFixed(2),
|
|
};
|
|
}
|
|
|
|
systemStatus (): SystemStatus {
|
|
const qqUsage = this.qqUsage();
|
|
const sysCpuInfo = this.sysCpuInfo();
|
|
return {
|
|
cpu: {
|
|
core: sysCpuInfo.core,
|
|
model: sysCpuInfo.model,
|
|
speed: (sysCpuInfo.speed / 1000).toFixed(2),
|
|
usage: {
|
|
system: sysCpuInfo.usage,
|
|
qq: qqUsage.cpu,
|
|
},
|
|
},
|
|
memory: {
|
|
total: (os.totalmem() / 1024 / 1024).toFixed(2),
|
|
usage: {
|
|
system: this.sysMemoryUsage(),
|
|
qq: qqUsage.memory,
|
|
},
|
|
},
|
|
arch: `${os.platform()} ${os.arch()} ${os.release()}`,
|
|
};
|
|
}
|
|
}
|
|
|
|
class StatusHelperSubscription extends EventEmitter {
|
|
private statusHelper: StatusHelper;
|
|
private interval: NodeJS.Timeout | null = null;
|
|
|
|
constructor (time: number = 3000) {
|
|
super();
|
|
this.statusHelper = new StatusHelper();
|
|
this.on('newListener', (event: string) => {
|
|
if (event === 'statusUpdate' && this.listenerCount('statusUpdate') === 0) {
|
|
this.startInterval(time);
|
|
}
|
|
});
|
|
this.on('removeListener', (event: string) => {
|
|
if (event === 'statusUpdate' && this.listenerCount('statusUpdate') === 0) {
|
|
this.stopInterval();
|
|
}
|
|
});
|
|
}
|
|
|
|
private startInterval (time: number) {
|
|
this.interval ??= setInterval(() => {
|
|
const status = this.statusHelper.systemStatus();
|
|
this.emit('statusUpdate', status);
|
|
}, time);
|
|
}
|
|
|
|
private stopInterval () {
|
|
if (this.interval) {
|
|
clearInterval(this.interval);
|
|
this.interval = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
export const statusHelperSubscription = new StatusHelperSubscription();
|