@hadesz/monitor
Version:
A complete server monitoring system with agents, server and dashboard
219 lines (190 loc) • 5.52 kB
JavaScript
const os = require("os");
const { exec } = require("child_process");
const { promisify } = require("util");
const execAsync = promisify(exec);
const NetworkMonitor = require("./network");
const DiskIOMonitor = require("./disk");
class SystemMonitor {
constructor(agentId) {
this.agentId = agentId;
this.networkMonitor = new NetworkMonitor();
this.diskIOMonitor = new DiskIOMonitor();
this.prevCpu = os.cpus();
this.prevDiskStats = null;
}
// 获取 CPU 使用率
getCpuUsage() {
const cpus = os.cpus();
let user = 0,
system = 0,
idle = 0;
cpus.forEach((cpu, i) => {
const prev = this.prevCpu[i].times;
const curr = cpu.times;
const totalDiff =
curr.user +
curr.nice +
curr.sys +
curr.idle +
curr.irq -
(prev.user + prev.nice + prev.sys + prev.idle + prev.irq);
if (totalDiff > 0) {
user += (curr.user - prev.user) / totalDiff;
system += (curr.sys - prev.sys) / totalDiff;
idle += (curr.idle - prev.idle) / totalDiff;
}
});
this.prevCpu = cpus;
const cpuCount = cpus.length;
return {
usage: (1 - idle / cpuCount) * 100,
user: (user / cpuCount) * 100,
system: (system / cpuCount) * 100,
idle: (idle / cpuCount) * 100,
load1: os.loadavg()[0],
load5: os.loadavg()[1],
load15: os.loadavg()[2]
};
}
// 获取内存使用情况
getMemoryUsage() {
const total = os.totalmem();
const free = os.freemem();
const used = total - free;
return {
total: Math.round(total / 1024 / 1024), // MB
free: Math.round(free / 1024 / 1024),
used: Math.round(used / 1024 / 1024),
usage: (used / total) * 100
};
}
// 获取磁盘使用情况(异步)
async getDiskUsage() {
try {
const { stdout } = await execAsync(
"df -k | grep -E '^/dev/' | awk '{print $2,$3,$4}'"
);
const lines = stdout.trim().split("\n");
let total = 0;
let used = 0;
let free = 0;
lines.forEach((line) => {
const [blockTotal, blockUsed, blockFree] = line
.trim()
.split(" ")
.map(Number);
total += blockTotal;
used += blockUsed;
free += blockFree;
});
return {
total: Math.round(total / 1024), // MB
used: Math.round(used / 1024),
free: Math.round(free / 1024),
usage: (used / total) * 100
};
} catch (error) {
console.error("Error getting disk usage:", error);
return null;
}
}
// 获取磁盘 IO(替换原有的 getDiskIO 方法)
async getDiskIO() {
try {
return await this.diskIOMonitor.getDiskIO();
} catch (error) {
console.error("获取磁盘 IO 失败:", error);
return { read: 0, write: 0 };
}
}
async getNetworkIO() {
return await this.networkMonitor.getNetworkIO(); // 使用5秒间隔
}
// 获取进程信息
async getProcessInfo() {
try {
const { stdout } = await execAsync(
"ps -e -o state --no-headers | sort | uniq -c"
);
const lines = stdout.trim().split("\n");
const stats = {
total: 0,
running: 0,
sleeping: 0
};
lines.forEach((line) => {
const [count, state] = line.trim().split(" ");
stats.total += parseInt(count);
switch (state) {
case "R":
stats.running += parseInt(count);
break;
case "S":
case "D":
stats.sleeping += parseInt(count);
break;
}
});
return stats;
} catch (error) {
console.error("Error getting process info:", error);
return { total: 0, running: 0, sleeping: 0 };
}
}
// 获取 Docker 容器统计
async getDockerStats() {
try {
// 获取容器总数
const { stdout: totalStdout } = await execAsync("docker ps -aq | wc -l");
const total = parseInt(totalStdout.trim());
// 获取运行中的容器数量
const { stdout: runningStdout } = await execAsync("docker ps -q | wc -l");
const running = parseInt(runningStdout.trim());
// 获取暂停的容器数量
const { stdout: pausedStdout } = await execAsync(
"docker ps -q --filter status=paused | wc -l"
);
const paused = parseInt(pausedStdout.trim());
// 计算停止的容器数量
const stopped = total - running - paused;
return {
containers: total,
running: running,
paused: paused,
stopped: stopped
};
} catch (error) {
// Docker 未安装或未运行
if (this.config.verbose) {
console.log("Docker not available:", error.message);
}
return null;
}
}
// 收集所有指标
async collectAllMetrics() {
const [cpu, memory, disk, diskIO, processes, docker, networkIO] =
await Promise.all([
this.getCpuUsage(),
this.getMemoryUsage(),
this.getDiskUsage(),
this.getDiskIO(),
this.getProcessInfo(),
this.getDockerStats(),
this.getNetworkIO()
]);
const usage = await this.diskIOMonitor.getDiskUsage();
return {
agentId: this.agentId,
timestamp: new Date(),
cpu,
memory,
disk: { ...disk, ...diskIO },
network: networkIO,
processes,
docker,
uptime: os.uptime()
};
}
}
module.exports = SystemMonitor;