badmfck-api-server 4.1.24 → 4.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apiServer/documentation/index.html +46 -46
- package/dist/apiServer/helper/Validator.js +2 -1
- package/dist/apiServer/http/Http.d.ts +19 -0
- package/dist/apiServer/http/Http.js +56 -4
- package/dist/apiServer/monitor/Monitor.d.ts +3 -0
- package/dist/apiServer/monitor/Monitor.js +17 -0
- package/dist/apiServer/monitor/ProcessMonitor.d.ts +117 -0
- package/dist/apiServer/monitor/ProcessMonitor.js +308 -0
- package/dist/apiServer/monitor/SystemInfo.d.ts +71 -0
- package/dist/apiServer/monitor/SystemInfo.js +218 -0
- package/dist/apiServer/monitor/index.html +78 -44
- package/package.json +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.collectSystemInfo = void 0;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const util_1 = require("util");
|
|
10
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
|
+
const execP = (0, util_1.promisify)(child_process_1.exec);
|
|
12
|
+
async function safeExec(cmd, timeoutMs = 3000) {
|
|
13
|
+
try {
|
|
14
|
+
const { stdout, stderr } = await execP(cmd, {
|
|
15
|
+
timeout: timeoutMs,
|
|
16
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
17
|
+
shell: "/bin/sh",
|
|
18
|
+
});
|
|
19
|
+
return { ok: true, stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), code: 0 };
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
stdout: e?.stdout != null ? String(e.stdout) : "",
|
|
25
|
+
stderr: e?.stderr != null ? String(e.stderr) : String(e?.message ?? e),
|
|
26
|
+
code: typeof e?.code === "number" ? e.code : -1,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function commandExists(cmd) {
|
|
31
|
+
const r = await safeExec(`command -v ${cmd}`, 1000);
|
|
32
|
+
return r.ok && r.stdout.trim().length > 0;
|
|
33
|
+
}
|
|
34
|
+
function cpuStatic() {
|
|
35
|
+
const cpus = os_1.default.cpus();
|
|
36
|
+
const models = {};
|
|
37
|
+
for (const c of cpus)
|
|
38
|
+
models[c.model] = (models[c.model] ?? 0) + 1;
|
|
39
|
+
return {
|
|
40
|
+
count: cpus.length,
|
|
41
|
+
models,
|
|
42
|
+
loadAvg: os_1.default.loadavg(),
|
|
43
|
+
platform: process.platform,
|
|
44
|
+
arch: process.arch,
|
|
45
|
+
uptimeSec: os_1.default.uptime(),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function cpuUsage(sampleMs = 200) {
|
|
49
|
+
if (process.platform !== "linux")
|
|
50
|
+
return null;
|
|
51
|
+
const read = async () => {
|
|
52
|
+
try {
|
|
53
|
+
const txt = await promises_1.default.readFile("/proc/stat", "utf-8");
|
|
54
|
+
const line = txt.split("\n", 1)[0];
|
|
55
|
+
const parts = line.split(/\s+/).slice(1).map(s => parseInt(s, 10) || 0);
|
|
56
|
+
return {
|
|
57
|
+
user: parts[0] ?? 0,
|
|
58
|
+
nice: parts[1] ?? 0,
|
|
59
|
+
system: parts[2] ?? 0,
|
|
60
|
+
idle: parts[3] ?? 0,
|
|
61
|
+
iowait: parts[4] ?? 0,
|
|
62
|
+
irq: parts[5] ?? 0,
|
|
63
|
+
softirq: parts[6] ?? 0,
|
|
64
|
+
steal: parts[7] ?? 0,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const a = await read();
|
|
72
|
+
if (!a)
|
|
73
|
+
return null;
|
|
74
|
+
await new Promise(r => setTimeout(r, sampleMs));
|
|
75
|
+
const b = await read();
|
|
76
|
+
if (!b)
|
|
77
|
+
return null;
|
|
78
|
+
const sum = (x) => x.user + x.nice + x.system + x.idle + x.iowait + x.irq + x.softirq + x.steal;
|
|
79
|
+
const total = sum(b) - sum(a);
|
|
80
|
+
if (total <= 0)
|
|
81
|
+
return null;
|
|
82
|
+
const pct = (delta) => Math.round((delta / total) * 1000) / 10;
|
|
83
|
+
return {
|
|
84
|
+
userPct: pct(b.user + b.nice - a.user - a.nice),
|
|
85
|
+
systemPct: pct(b.system - a.system),
|
|
86
|
+
idlePct: pct(b.idle - a.idle),
|
|
87
|
+
iowaitPct: pct(b.iowait - a.iowait),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function memory() {
|
|
91
|
+
const total = os_1.default.totalmem();
|
|
92
|
+
const free = os_1.default.freemem();
|
|
93
|
+
return {
|
|
94
|
+
total,
|
|
95
|
+
free,
|
|
96
|
+
used: total - free,
|
|
97
|
+
usedPct: Math.round(((total - free) / total) * 1000) / 10,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function disk() {
|
|
101
|
+
const r = await safeExec("df -kP");
|
|
102
|
+
if (!r.ok)
|
|
103
|
+
return null;
|
|
104
|
+
const lines = r.stdout.split("\n").slice(1).filter(l => l.trim().length > 0);
|
|
105
|
+
return lines
|
|
106
|
+
.map(line => {
|
|
107
|
+
const parts = line.trim().split(/\s+/);
|
|
108
|
+
if (parts.length < 6)
|
|
109
|
+
return null;
|
|
110
|
+
const sizeKB = parseInt(parts[1], 10) || 0;
|
|
111
|
+
const usedKB = parseInt(parts[2], 10) || 0;
|
|
112
|
+
const availKB = parseInt(parts[3], 10) || 0;
|
|
113
|
+
return {
|
|
114
|
+
filesystem: parts[0],
|
|
115
|
+
size: sizeKB * 1024,
|
|
116
|
+
used: usedKB * 1024,
|
|
117
|
+
available: availKB * 1024,
|
|
118
|
+
usePct: parts[4],
|
|
119
|
+
mount: parts.slice(5).join(" "),
|
|
120
|
+
};
|
|
121
|
+
})
|
|
122
|
+
.filter((d) => d !== null)
|
|
123
|
+
.filter(d => !/^(tmpfs|devtmpfs|squashfs|overlay|udev|none|run)/.test(d.filesystem));
|
|
124
|
+
}
|
|
125
|
+
async function httpConnections(ports = [80, 443]) {
|
|
126
|
+
const portList = ports.join("|");
|
|
127
|
+
const ssCmd = `ss -tnH 2>/dev/null | awk '$1=="ESTAB" && $4 ~ /:(${portList})$/ {print $4, $5}'`;
|
|
128
|
+
let r = await safeExec(ssCmd);
|
|
129
|
+
if (!r.ok || r.stdout.trim().length === 0) {
|
|
130
|
+
const nsCmd = `netstat -tn 2>/dev/null | awk '$6=="ESTABLISHED" && $4 ~ /:(${portList})$/ {print $4, $5}'`;
|
|
131
|
+
r = await safeExec(nsCmd);
|
|
132
|
+
if (!r.ok)
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const lines = r.stdout.split("\n").filter(l => l.trim().length > 0);
|
|
136
|
+
const byRemote = {};
|
|
137
|
+
for (const line of lines) {
|
|
138
|
+
const parts = line.split(/\s+/);
|
|
139
|
+
const remote = parts[1] ?? "";
|
|
140
|
+
const ipMatch = remote.match(/^\[?([^\]]+)\]?:\d+$/);
|
|
141
|
+
const ip = ipMatch ? ipMatch[1] : remote;
|
|
142
|
+
byRemote[ip] = (byRemote[ip] ?? 0) + 1;
|
|
143
|
+
}
|
|
144
|
+
const topRemote = Object.entries(byRemote)
|
|
145
|
+
.sort(([, a], [, b]) => b - a)
|
|
146
|
+
.slice(0, 20)
|
|
147
|
+
.map(([ip, count]) => ({ ip, count }));
|
|
148
|
+
return { ports, total: lines.length, topRemote };
|
|
149
|
+
}
|
|
150
|
+
async function nginx() {
|
|
151
|
+
const installed = await commandExists("nginx");
|
|
152
|
+
if (!installed)
|
|
153
|
+
return { installed: false };
|
|
154
|
+
const [version, status, listening, workers] = await Promise.all([
|
|
155
|
+
safeExec("nginx -v 2>&1", 1000),
|
|
156
|
+
safeExec("systemctl is-active nginx 2>/dev/null", 1000),
|
|
157
|
+
safeExec("ss -tlnH 2>/dev/null | awk '{print $4}'", 1000),
|
|
158
|
+
safeExec("pgrep -c nginx 2>/dev/null", 1000),
|
|
159
|
+
]);
|
|
160
|
+
return {
|
|
161
|
+
installed: true,
|
|
162
|
+
version: (version.stdout || version.stderr).trim(),
|
|
163
|
+
status: status.stdout.trim() || "unknown",
|
|
164
|
+
listening: listening.stdout.split("\n").filter(l => l.trim().length > 0),
|
|
165
|
+
workerCount: parseInt(workers.stdout.trim(), 10) || 0,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function pm2() {
|
|
169
|
+
const installed = await commandExists("pm2");
|
|
170
|
+
if (!installed)
|
|
171
|
+
return { installed: false };
|
|
172
|
+
const r = await safeExec("pm2 jlist 2>/dev/null", 3000);
|
|
173
|
+
if (!r.ok)
|
|
174
|
+
return { installed: true, error: r.stderr.slice(0, 500) };
|
|
175
|
+
const text = r.stdout;
|
|
176
|
+
const start = text.indexOf("[");
|
|
177
|
+
const end = text.lastIndexOf("]");
|
|
178
|
+
if (start === -1 || end === -1)
|
|
179
|
+
return { installed: true, error: "no JSON in pm2 jlist output" };
|
|
180
|
+
try {
|
|
181
|
+
const arr = JSON.parse(text.slice(start, end + 1));
|
|
182
|
+
const processes = arr.map((p) => ({
|
|
183
|
+
name: p.name,
|
|
184
|
+
pid: p.pid,
|
|
185
|
+
pm_id: p.pm_id,
|
|
186
|
+
status: p.pm2_env?.status,
|
|
187
|
+
uptime: p.pm2_env?.pm_uptime,
|
|
188
|
+
restarts: p.pm2_env?.restart_time,
|
|
189
|
+
cpu: p.monit?.cpu,
|
|
190
|
+
memory: p.monit?.memory,
|
|
191
|
+
exec_mode: p.pm2_env?.exec_mode,
|
|
192
|
+
instances: p.pm2_env?.instances,
|
|
193
|
+
node_version: p.pm2_env?.node_version,
|
|
194
|
+
}));
|
|
195
|
+
return { installed: true, processes };
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return { installed: true, error: "Failed to parse pm2 jlist output" };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function collectSystemInfo() {
|
|
202
|
+
const [cpuUsageData, diskData, connectionsData, nginxData, pm2Data] = await Promise.all([
|
|
203
|
+
cpuUsage().catch(() => null),
|
|
204
|
+
disk().catch(() => null),
|
|
205
|
+
httpConnections().catch(() => null),
|
|
206
|
+
nginx().catch(() => ({ installed: false, error: "probe failed" })),
|
|
207
|
+
pm2().catch(() => ({ installed: false, error: "probe failed" })),
|
|
208
|
+
]);
|
|
209
|
+
return {
|
|
210
|
+
cpu: { ...cpuStatic(), usage: cpuUsageData },
|
|
211
|
+
memory: memory(),
|
|
212
|
+
disk: diskData,
|
|
213
|
+
connections: connectionsData,
|
|
214
|
+
nginx: nginxData,
|
|
215
|
+
pm2: pm2Data,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
exports.collectSystemInfo = collectSystemInfo;
|