Skip to content

Commit

Permalink
fix: use child process PID instead of parent PID for default name, an…
Browse files Browse the repository at this point in the history
…d resolve issues with custom name and output destination (#148)

* fix: use child process PID instead of parent PID for default name, and resolve issues with custom name and output destination

* doc: update README
  • Loading branch information
rubenpad authored Jun 22, 2023
1 parent 3edbc56 commit ba66145
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 23 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ const heapProfiler = new ClinicHeapProfiler()
**Default**: false
- debug [`<boolean>`][] If set to true, the generated html will not be minified.
**Default**: false
- dest [`<String>`][] The file where the collected data is stored.
**Default**: `./.clinic/<process.pid>.clinic-heapprofile`
- dest [`<String>`][] Destination for the collected data
**Default**: `.clinic`
- name [`<String>`][] File name for the collected data
**Default**: `<process.pid>.clinic-heapprofiler`

#### `heapProfiler.collect(args, callback)`

Expand Down
14 changes: 8 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const { analyse } = require('./analysis/index.js')
const noop = function () {}

function execute (instance, args, env, nodeOptions, cb) {
ensureDir(path.dirname(instance.dest), err => {
ensureDir(instance.path, err => {
/* istanbul ignore if */
if (err) {
cb(err)
Expand Down Expand Up @@ -44,7 +44,7 @@ function execute (instance, args, env, nodeOptions, cb) {
return
}

cb(null, instance.dest)
cb(null, `${instance.path}/${instance.name || instance.process.pid}.clinic-heapprofiler`)
})
})
}
Expand Down Expand Up @@ -105,14 +105,15 @@ class ClinicHeapProfiler extends events.EventEmitter {
detectPort = false,
collectOnFailure = false,
debug = false,
name,
dest = `.clinic/${name || process.pid}.clinic-heapprofiler`
dest = '.clinic',
name
} = settings

this.detectPort = !!detectPort
this.collectOnFailure = !!collectOnFailure
this.debug = debug
this.dest = dest
this.path = dest
this.name = name
}

collect (args, cb) {
Expand All @@ -125,7 +126,8 @@ class ClinicHeapProfiler extends events.EventEmitter {

const env = {
...process.env,
HEAP_PROFILER_DESTINATION: this.dest,
HEAP_PROFILER_NAME: this.name,
HEAP_PROFILER_PATH: this.path,
HEAP_PROFILER_PRELOADER_DISABLED: 'true',
HEAP_PROFILER_USE_IPC: this.detectPort
}
Expand Down
5 changes: 4 additions & 1 deletion src/injects/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const onNetListen = require('on-net-listen')

const controller = new AbortController()
const clinicPort = parseInt(process.env.CLINIC_HEAP_PROFILER_PORT, 10)
const profilerOptions = { destination: process.env.HEAP_PROFILER_DESTINATION, signal: controller.signal }
const profilerOptions = {
destination: `${process.env.HEAP_PROFILER_PATH}/${process.env.HEAP_PROFILER_NAME || process.pid}.clinic-heapprofiler`,
signal: controller.signal
}

let toSend = 2 // We need to send two ports: the IPC one and the application one
let server
Expand Down
135 changes: 121 additions & 14 deletions test/cmd-dest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,152 @@ const path = require('path')
const { test } = require('tap')
const ClinicHeapProfiler = require('../src/index.js')

test('cmd - test collect - default name (child_process.pid) and output destination (.clinic)', t => {
const tool = new ClinicHeapProfiler({ debug: true })

function cleanup (err, filepath) {
function callback (err) {
t.error(err)
t.end()
}

t.error(err)

t.match(filepath, /^\.clinic(\/|\\)[0-9]+\.clinic-heapprofiler$/)

fs.rm(path.dirname(filepath), { recursive: true }, callback)
}

tool.collect([process.execPath, path.join('test', 'fixtures', 'randomHashes.js')], (err, filepath) => {
if (err) {
cleanup(err, filepath)
return
}

t.match(filepath, tool.process.pid.toString())

t.ok(fs.statSync(filepath).isFile())

tool.visualize(filepath, `${filepath}.html`, err => {
if (err) {
cleanup(err, filepath)
return
}

t.ok(fs.statSync(`${filepath}.html`).isFile())

cleanup(null, filepath)
})
})
})

test('cmd - test collect - custom output destination', t => {
const tool = new ClinicHeapProfiler({ debug: true, dest: 'test-output-destination' })

function cleanup (err, filename) {
let count = 0
function cleanup (err, filepath) {
function callback (err) {
t.error(err)
t.end()
}

t.error(err)

t.match(filepath, /^test-output-destination/)

fs.rm(path.dirname(filepath), { recursive: true }, callback)
}

tool.collect([process.execPath, path.join('test', 'fixtures', 'randomHashes.js')], (err, filepath) => {
if (err) {
cleanup(err, filepath)
return
}

t.ok(fs.statSync(filepath).isFile())

tool.visualize(filepath, `${filepath}.html`, err => {
if (err) {
cleanup(err, filepath)
return
}

t.ok(fs.statSync(`${filepath}.html`).isFile())

cleanup(null, filepath)
})
})
})

test('cmd - test collect - custom output name', t => {
const tool = new ClinicHeapProfiler({ debug: true, name: 'test-custom-name' })

function cleanup (err, filepath) {
function callback (err) {
t.error(err)
t.end()
}

if (++count === 2) {
t.end()
t.error(err)

t.equal(filepath, '.clinic/test-custom-name.clinic-heapprofiler')

fs.rm(path.dirname(filepath), { recursive: true }, callback)
}

tool.collect([process.execPath, path.join('test', 'fixtures', 'randomHashes.js')], (err, filepath) => {
if (err) {
cleanup(err, filepath)
return
}

t.ok(fs.statSync(filepath).isFile())

tool.visualize(filepath, `${filepath}.html`, err => {
if (err) {
cleanup(err, filepath)
return
}

t.ok(fs.statSync(`${filepath}.html`).isFile())

cleanup(null, filepath)
})
})
})

test('cmd - test collect - custom name and output destination', t => {
const tool = new ClinicHeapProfiler({ debug: true, name: 'test-custom-name', dest: 'test-output-destination' })

function cleanup (err, filepath) {
function callback (err) {
t.error(err)
t.end()
}

t.error(err)

t.match(filename, /^test-output-destination$/)
t.equal(filepath, 'test-output-destination/test-custom-name.clinic-heapprofiler')

fs.unlink(filename, callback)
fs.unlink(filename + '.html', callback)
fs.rm(path.dirname(filepath), { recursive: true }, callback)
}

tool.collect([process.execPath, path.join('test', 'fixtures', 'randomHashes.js')], (err, filename) => {
tool.collect([process.execPath, path.join('test', 'fixtures', 'randomHashes.js')], (err, filepath) => {
if (err) {
cleanup(err, filename)
cleanup(err, filepath)
return
}

t.ok(fs.statSync(filename).isFile())
t.ok(fs.statSync(filepath).isFile())

tool.visualize(filename, `${filename}.html`, err => {
tool.visualize(filepath, `${filepath}.html`, err => {
if (err) {
cleanup(err, filename)
cleanup(err, filepath)
return
}

t.ok(fs.statSync(`${filename}.html`).isFile())
t.ok(fs.statSync(`${filepath}.html`).isFile())

cleanup(null, filename)
cleanup(null, filepath)
})
})
})

0 comments on commit ba66145

Please sign in to comment.