pm2-perfmonitor 2.1.3 → 2.1.6
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 +35 -0
- package/lib/perf-sampler.js +10 -4
- package/package.json +1 -1
package/lib/app.js
CHANGED
|
@@ -60,6 +60,12 @@ const cpuOverloadHistory = new Map()
|
|
|
60
60
|
const cpuOverloadRestartHistory = new Map()
|
|
61
61
|
const cpuOverloadRestartFailedHistory = new Map()
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* perf 样本是否采集中
|
|
65
|
+
* @type { Map<number,boolean> }
|
|
66
|
+
*/
|
|
67
|
+
const perfSamplingStats = new Map()
|
|
68
|
+
|
|
63
69
|
/**
|
|
64
70
|
* @param {'log' | 'info' | 'error' | 'warn'} type
|
|
65
71
|
*
|
|
@@ -152,11 +158,17 @@ const setCpuOverloadRestartFailedHistory = (pm_id) => {
|
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
|
|
161
|
+
let isProcessCheckerRunning = false
|
|
162
|
+
|
|
155
163
|
/**
|
|
156
164
|
* check process
|
|
157
165
|
*/
|
|
158
166
|
const processChecker = async () => {
|
|
167
|
+
if (isProcessCheckerRunning) return
|
|
168
|
+
|
|
159
169
|
try {
|
|
170
|
+
isProcessCheckerRunning = true
|
|
171
|
+
|
|
160
172
|
const apps = await listAppsAsync()
|
|
161
173
|
|
|
162
174
|
for (const app of apps) {
|
|
@@ -249,6 +261,8 @@ const processChecker = async () => {
|
|
|
249
261
|
)
|
|
250
262
|
|
|
251
263
|
if (enablePerfCollection) {
|
|
264
|
+
perfSamplingStats.set(pm_id, true)
|
|
265
|
+
|
|
252
266
|
await performPerfSampling({
|
|
253
267
|
pid,
|
|
254
268
|
moduleName: MODULE_NAME,
|
|
@@ -257,6 +271,8 @@ const processChecker = async () => {
|
|
|
257
271
|
sampleDuration: perfSampleDuration,
|
|
258
272
|
sampleFrequency: perfSampleFrequency,
|
|
259
273
|
})
|
|
274
|
+
|
|
275
|
+
perfSamplingStats.delete(pm_id)
|
|
260
276
|
}
|
|
261
277
|
|
|
262
278
|
try {
|
|
@@ -292,6 +308,8 @@ const processChecker = async () => {
|
|
|
292
308
|
}
|
|
293
309
|
} catch (err) {
|
|
294
310
|
logger('error', err)
|
|
311
|
+
} finally {
|
|
312
|
+
isProcessCheckerRunning = false
|
|
295
313
|
}
|
|
296
314
|
}
|
|
297
315
|
|
|
@@ -417,6 +435,23 @@ const runModule = () => {
|
|
|
417
435
|
return res.map((v) => `[${v[0]}]:${v[1]}`).join(' ; ')
|
|
418
436
|
},
|
|
419
437
|
})
|
|
438
|
+
|
|
439
|
+
Probe.metric({
|
|
440
|
+
name: 'Processes in Sampling (perf)',
|
|
441
|
+
value: () => {
|
|
442
|
+
const res = []
|
|
443
|
+
|
|
444
|
+
for (const [k, v] of perfSamplingStats) {
|
|
445
|
+
if (v === true) {
|
|
446
|
+
res.push(k)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (!res.length) return 'N/A'
|
|
451
|
+
|
|
452
|
+
return res.join(', ')
|
|
453
|
+
},
|
|
454
|
+
})
|
|
420
455
|
}
|
|
421
456
|
|
|
422
457
|
runModule()
|
package/lib/perf-sampler.js
CHANGED
|
@@ -30,7 +30,7 @@ const execCommand = async (cmd, args, options = {}) => {
|
|
|
30
30
|
|
|
31
31
|
return true
|
|
32
32
|
} catch (err) {
|
|
33
|
-
console.error(`Command failed: ${cmd} ${args.join(' ')}`, err.message)
|
|
33
|
+
console.error(`Command failed: [${cmd} ${args.join(' ')}]`, err.message)
|
|
34
34
|
return false
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -186,7 +186,9 @@ const performPerfSampling = async ({
|
|
|
186
186
|
|
|
187
187
|
// --- Step 2: perf script 导出为文本堆栈 ---
|
|
188
188
|
const scriptOk = await execCommand('perf', ['script', '-i', perfDataFile], {
|
|
189
|
-
stdout:
|
|
189
|
+
stdout: {
|
|
190
|
+
file: perfStacksFile,
|
|
191
|
+
},
|
|
190
192
|
})
|
|
191
193
|
|
|
192
194
|
if (!scriptOk) return
|
|
@@ -217,14 +219,18 @@ const performPerfSampling = async ({
|
|
|
217
219
|
stackcollapsePath,
|
|
218
220
|
[perfStacksFile],
|
|
219
221
|
{
|
|
220
|
-
stdout:
|
|
222
|
+
stdout: {
|
|
223
|
+
file: perfFoldedFile,
|
|
224
|
+
},
|
|
221
225
|
},
|
|
222
226
|
)
|
|
223
227
|
if (!collapseOk) return
|
|
224
228
|
|
|
225
229
|
// --- Step 5: 生成 SVG 火焰图 ---
|
|
226
230
|
const flameOk = await execCommand(flamegraphPath, [perfFoldedFile], {
|
|
227
|
-
stdout:
|
|
231
|
+
stdout: {
|
|
232
|
+
file: perfSvgFile,
|
|
233
|
+
},
|
|
228
234
|
})
|
|
229
235
|
if (flameOk) {
|
|
230
236
|
logger('info', `PID:${pidNum} Flame graph generated: ${perfSvgFile}`)
|