pm2-perfmonitor 2.1.1 → 2.1.3
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/lib/app.js +40 -8
- package/lib/perf-sampler.js +8 -8
- package/package.json +1 -1
package/lib/app.js
CHANGED
|
@@ -54,10 +54,11 @@ const nodeInspectorSampleDuration = parseParamToNumber(
|
|
|
54
54
|
// 存储每个进程的 CPU 采样历史(pm_id -> [cpu1, cpu2, ...])
|
|
55
55
|
const zombieCpuHistory = new Map()
|
|
56
56
|
const zombieRestartHistory = new Map()
|
|
57
|
-
const
|
|
57
|
+
const zombieRestartFailedHistory = new Map()
|
|
58
58
|
|
|
59
59
|
const cpuOverloadHistory = new Map()
|
|
60
60
|
const cpuOverloadRestartHistory = new Map()
|
|
61
|
+
const cpuOverloadRestartFailedHistory = new Map()
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* @param {'log' | 'info' | 'error' | 'warn'} type
|
|
@@ -129,11 +130,25 @@ const setCpuOverloadHistory = (pm_id, appCpuUsage) => {
|
|
|
129
130
|
return history
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
134
|
-
|
|
133
|
+
const setZombieRestartFailedHistory = (pm_id) => {
|
|
134
|
+
if (!zombieRestartFailedHistory.has(pm_id)) {
|
|
135
|
+
zombieRestartFailedHistory.set(pm_id, 1)
|
|
135
136
|
} else {
|
|
136
|
-
|
|
137
|
+
zombieRestartFailedHistory.set(
|
|
138
|
+
pm_id,
|
|
139
|
+
zombieRestartFailedHistory.get(pm_id) + 1,
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const setCpuOverloadRestartFailedHistory = (pm_id) => {
|
|
145
|
+
if (!cpuOverloadRestartFailedHistory.has(pm_id)) {
|
|
146
|
+
cpuOverloadRestartFailedHistory.set(pm_id, 1)
|
|
147
|
+
} else {
|
|
148
|
+
cpuOverloadRestartFailedHistory.set(
|
|
149
|
+
pm_id,
|
|
150
|
+
cpuOverloadRestartFailedHistory.get(pm_id) + 1,
|
|
151
|
+
)
|
|
137
152
|
}
|
|
138
153
|
}
|
|
139
154
|
|
|
@@ -222,7 +237,7 @@ const processChecker = async () => {
|
|
|
222
237
|
restartErr,
|
|
223
238
|
)
|
|
224
239
|
|
|
225
|
-
|
|
240
|
+
setZombieRestartFailedHistory(pm_id)
|
|
226
241
|
}
|
|
227
242
|
}
|
|
228
243
|
}
|
|
@@ -271,7 +286,7 @@ const processChecker = async () => {
|
|
|
271
286
|
restartErr,
|
|
272
287
|
)
|
|
273
288
|
|
|
274
|
-
|
|
289
|
+
setCpuOverloadRestartFailedHistory(pm_id)
|
|
275
290
|
}
|
|
276
291
|
}
|
|
277
292
|
}
|
|
@@ -323,7 +338,7 @@ const runModule = () => {
|
|
|
323
338
|
value: () => {
|
|
324
339
|
const res = []
|
|
325
340
|
|
|
326
|
-
for (const [k, v] of
|
|
341
|
+
for (const [k, v] of zombieRestartFailedHistory) {
|
|
327
342
|
if (v > 0) {
|
|
328
343
|
res.push([k, v])
|
|
329
344
|
}
|
|
@@ -385,6 +400,23 @@ const runModule = () => {
|
|
|
385
400
|
return res.join(',')
|
|
386
401
|
},
|
|
387
402
|
})
|
|
403
|
+
|
|
404
|
+
Probe.metric({
|
|
405
|
+
name: 'CPU Overload Restarts (failed)',
|
|
406
|
+
value: () => {
|
|
407
|
+
const res = []
|
|
408
|
+
|
|
409
|
+
for (const [k, v] of cpuOverloadRestartFailedHistory) {
|
|
410
|
+
if (v > 0) {
|
|
411
|
+
res.push([k, v])
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (!res.length) return 'N/A'
|
|
416
|
+
|
|
417
|
+
return res.map((v) => `[${v[0]}]:${v[1]}`).join(' ; ')
|
|
418
|
+
},
|
|
419
|
+
})
|
|
388
420
|
}
|
|
389
421
|
|
|
390
422
|
runModule()
|
package/lib/perf-sampler.js
CHANGED
|
@@ -25,10 +25,9 @@ const getExeca = async () => {
|
|
|
25
25
|
const execCommand = async (cmd, args, options = {}) => {
|
|
26
26
|
try {
|
|
27
27
|
const execa = await getExeca()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
})
|
|
28
|
+
|
|
29
|
+
await execa(cmd, args, options)
|
|
30
|
+
|
|
32
31
|
return true
|
|
33
32
|
} catch (err) {
|
|
34
33
|
console.error(`Command failed: ${cmd} ${args.join(' ')}`, err.message)
|
|
@@ -122,10 +121,10 @@ const performPerfSampling = async ({
|
|
|
122
121
|
logger('error', `Perf permission check failed: ${err.message}`)
|
|
123
122
|
logger(
|
|
124
123
|
'error',
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
`Please ensure the perf command is installed and the user has permission to run it.\n
|
|
125
|
+
You can configure the system to allow non-root perf by setting:\n
|
|
126
|
+
"echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid"\n
|
|
127
|
+
"sudo setcap cap_sys_admin+ep $(which perf)"`,
|
|
129
128
|
)
|
|
130
129
|
return // 无权限则直接退出
|
|
131
130
|
}
|
|
@@ -189,6 +188,7 @@ const performPerfSampling = async ({
|
|
|
189
188
|
const scriptOk = await execCommand('perf', ['script', '-i', perfDataFile], {
|
|
190
189
|
stdout: fs.createWriteStream(perfStacksFile),
|
|
191
190
|
})
|
|
191
|
+
|
|
192
192
|
if (!scriptOk) return
|
|
193
193
|
|
|
194
194
|
logger('info', `PID:${pidNum} Perf sampling completed: ${perfStacksFile}`)
|