GeezerVison is showing github.com — process: add custom dir support for heapsnapshot-signal · nodejs/node@ad043ba
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/process/pre_execution.js +37-2Lines changed: 37 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | const { | 4 | 4 | ArrayPrototypeForEach, | | 5 | + Date, | | 6 | + DatePrototypeGetDate, | | 7 | + DatePrototypeGetFullYear, | | 8 | + DatePrototypeGetHours, | | 9 | + DatePrototypeGetMinutes, | | 10 | + DatePrototypeGetMonth, | | 11 | + DatePrototypeGetSeconds, | 5 | 12 | NumberParseInt, | 6 | 13 | ObjectDefineProperties, | 7 | 14 | ObjectDefineProperty, | 8 | 15 | ObjectGetOwnPropertyDescriptor, | 9 | 16 | SafeMap, | | 17 | + String, | 10 | 18 | StringPrototypeStartsWith, | 11 | 19 | Symbol, | 12 | | - SymbolDispose, | 13 | 20 | SymbolAsyncDispose, | | 21 | + SymbolDispose, | 14 | 22 | globalThis, | 15 | 23 | } = primordials; | 16 | 24 |
| @@ -400,6 +408,7 @@ function initializeReportSignalHandlers() { | 400 | 408 |
| 401 | 409 | function initializeHeapSnapshotSignalHandlers() { | 402 | 410 | const signal = getOptionValue('--heapsnapshot-signal'); | | 411 | + const diagnosticDir = getOptionValue('--diagnostic-dir'); | 403 | 412 |
| 404 | 413 | if (!signal) | 405 | 414 | return; | @@ -408,7 +417,8 @@ function initializeHeapSnapshotSignalHandlers() { | 408 | 417 | const { writeHeapSnapshot } = require('v8'); | 409 | 418 |
| 410 | 419 | function doWriteHeapSnapshot() { | 411 | | - writeHeapSnapshot(); | | 420 | + const heapSnapshotFilename = getHeapSnapshotFilename(diagnosticDir); | | 421 | + writeHeapSnapshot(heapSnapshotFilename); | 412 | 422 | } | 413 | 423 | process.on(signal, doWriteHeapSnapshot); | 414 | 424 |
| @@ -700,6 +710,31 @@ function markBootstrapComplete() { | 700 | 710 | internalBinding('performance').markBootstrapComplete(); | 701 | 711 | } | 702 | 712 |
| | 713 | +// Sequence number for diagnostic filenames | | 714 | +let sequenceNumOfheapSnapshot = 0; | | 715 | + | | 716 | +// To generate the HeapSnapshotFilename while using custom diagnosticDir | | 717 | +function getHeapSnapshotFilename(diagnosticDir) { | | 718 | + if (!diagnosticDir) return undefined; | | 719 | + | | 720 | + const date = new Date(); | | 721 | + | | 722 | + const year = DatePrototypeGetFullYear(date); | | 723 | + const month = String(DatePrototypeGetMonth(date) + 1).padStart(2, '0'); | | 724 | + const day = String(DatePrototypeGetDate(date)).padStart(2, '0'); | | 725 | + const hours = String(DatePrototypeGetHours(date)).padStart(2, '0'); | | 726 | + const minutes = String(DatePrototypeGetMinutes(date)).padStart(2, '0'); | | 727 | + const seconds = String(DatePrototypeGetSeconds(date)).padStart(2, '0'); | | 728 | + | | 729 | + const dateString = `${year}${month}${day}`; | | 730 | + const timeString = `${hours}${minutes}${seconds}`; | | 731 | + const pid = process.pid; | | 732 | + const threadId = internalBinding('worker').threadId; | | 733 | + const fileSequence = (++sequenceNumOfheapSnapshot).toString().padStart(3, '0'); | | 734 | + | | 735 | + return `${diagnosticDir}/Heap.${dateString}.${timeString}.${pid}.${threadId}.${fileSequence}.heapsnapshot`; | | 736 | +} | | 737 | + | 703 | 738 | module.exports = { | 704 | 739 | setupUserModules, | 705 | 740 | prepareMainThreadExecution, | |
Collapse file Copy file name to clipboard +50Lines changed: 50 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | +const common = require('../common'); | | 3 | + | | 4 | + | | 5 | +if (common.isWindows) | | 6 | + common.skip('test not supported on Windows'); | | 7 | + | | 8 | +const assert = require('assert'); | | 9 | + | | 10 | +const validateHeapSnapshotFile = () => { | | 11 | + const fs = require('fs'); | | 12 | + | | 13 | + assert.strictEqual(process.listenerCount('SIGUSR2'), 1); | | 14 | + process.kill(process.pid, 'SIGUSR2'); | | 15 | + process.kill(process.pid, 'SIGUSR2'); | | 16 | + | | 17 | + // Asynchronously wait for the snapshot. Use an async loop to be a bit more | | 18 | + // robust in case platform or machine differences throw off the timing. | | 19 | + (function validate() { | | 20 | + const files = fs.readdirSync(process.cwd()); | | 21 | + | | 22 | + if (files.length === 0) | | 23 | + return setImmediate(validate); | | 24 | + | | 25 | + assert.strictEqual(files.length, 2); | | 26 | + | | 27 | + for (let i = 0; i < files.length; i++) { | | 28 | + assert.match(files[i], /^Heap\..+\.heapsnapshot$/); | | 29 | + | | 30 | + // Check the file is parsable as JSON | | 31 | + JSON.parse(fs.readFileSync(files[i])); | | 32 | + } | | 33 | + })(); | | 34 | +}; | | 35 | + | | 36 | +if (process.argv[2] === 'child') { | | 37 | + validateHeapSnapshotFile(); | | 38 | +} else { | | 39 | + // Modify the timezone. So we can check the file date string still returning correctly. | | 40 | + process.env.TZ = 'America/New_York'; | | 41 | + const { spawnSync } = require('child_process'); | | 42 | + const tmpdir = require('../common/tmpdir'); | | 43 | + | | 44 | + tmpdir.refresh(); | | 45 | + const args = ['--heapsnapshot-signal', 'SIGUSR2', '--diagnostic-dir', tmpdir.path, __filename, 'child']; | | 46 | + const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); | | 47 | + | | 48 | + assert.strictEqual(child.status, 0); | | 49 | + assert.strictEqual(child.signal, null); | | 50 | +} |
|