Socket
Socket
Sign inDemoInstall

@nearform/heap-profiler

Package Overview
Dependencies
5
Maintainers
34
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0 to 2.0.0

.eslintrc.js

68

CODE_OF_CONDUCT.md

@@ -5,71 +5,43 @@ # Contributor Covenant Code of Conduct

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [clinic@nearform.com][clinic]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at opensource@nearform.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[clinic]: mailto:clinic@nearform.com
[homepage]: https://www.contributor-covenant.org
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

@@ -1,52 +0,66 @@

# Contributing to Clinic.js
# Welcome to @nearform/heap-profiler!
The Clinic.js project welcomes all contributions from anyone willing to
work in good faith with other contributors and the community. No contribution
is too small and all contributions are valued.
Please take a second to read over this before opening an issue. Providing complete information upfront will help us address any issue (and ship new features!) faster.
## Code of Conduct
We greatly appreciate bug fixes, documentation improvements and new features, however when contributing a new major feature, it is a good idea to idea to first open an issue, to make sure the feature it fits with the goal of the project, so we don't waste your or our time.
The Clinic.js project has a [Code of Conduct][CoC] that all contributors are
expected to follow.
## Bug Reports
## Licensing and Certification
A perfect bug report would have the following:
All contributions to the Clinic.js project are submitted to the
project under the MIT license.
1. Summary of the issue you are experiencing.
2. Details on what versions of node and XZY you are using (`node -v`).
3. A simple repeatable test case for us to run. Please try to run through it 2-3 times to ensure it is completely repeatable.
The Clinic.js project uses a Contribution Certification that is derived from
the [Developer Certificate of Origin][DCO]. It is important to note that the
Contribution Certification *is not the same as the standard DCO* and we do not
use the term "DCO" or "Developer Certificate of Origin" to describe it to avoid
confusion. Nevertheless, the intent and purpose is effectively the same.
We would like to avoid issues that require a follow up questions to identify the bug. These follow ups are difficult to do unless we have a repeatable test case.
Every contributor agrees to the Contribution Certification by including a
`Signed-off-by` statement within each commit. The statement *must* include
the contributor's real full name and email address.
## For Developers
All contributions should fit the [standard](https://github.com/standard/standard) linter, and pass the tests.
You can test this by running:
```
Signed-off-by: J. Random User <j.random.user@example.com>
npm lint
npm test
```
### Certification
## For Collaborators
Make sure to get a `:thumbsup:`, `+1` or `LGTM` from another collaborator before merging a PR. If you aren't sure if a release should happen, open an issue.
Release process:
- `npm test`
- `npm version <major|minor|patch>`
- `git push && git push --tags`
- `npm publish`
---
<a id="developers-certificate-of-origin"></a>
## Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have the right
to and hereby submit it under the MIT license; or
- (a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my
knowledge, is covered under an appropriate open source license and I have the
right under that license to submit that work with modifications, whether created
in whole or in part by me, under the MIT License; or
- (b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other person who
certified (a), (b) or (c) and I have not modified it.
- (c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution are public
and that a record of the contribution (including all personal information I
submit with it, including my sign-off) is maintained indefinitely and may be
redistributed consistent with this project or license(s) involved.
[CoC]: CODE_OF_CONDUCT.md
[DCO]: https://developercertificate.org/
- (d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
{
"name": "@nearform/heap-profiler",
"version": "1.0.0",
"engines": {
"node": ">= 10.12.0"
"version": "2.0.0",
"description": "Heap dump, sample profiler and allocation timeline generator for Node.",
"author": "NearForm Ltd",
"homepage": "https://github.com/nearform/heap-profiler",
"contributors": [
{
"name": "Paolo Insogna",
"url": "https://github.com/ShogunPanda"
},
{
"name": "Damien Simonin Feugas",
"url": "https://github.com/feugy"
},
{
"name": "Matteo Collina",
"url": "https://github.com/mcollina"
},
{
"name": "James M Snell",
"url": "https://github.com/jasnell"
}
],
"license": "Apache-2.0",
"licenses": [
{
"type": "Apache-2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0"
}
],
"keywords": [
"heap",
"profile",
"sampling",
"snapshot",
"allocation",
"timeline"
],
"repository": {
"type": "git",
"url": "git+https://github.com/nearform/heap-profiler.git"
},
"description": "Programmable interface to Clinic.js Heap Profiler",
"repository": "https://github.com/clinicjs/node-clinic-heap-profiler",
"bugs": {
"url": "https://github.com/nearform/heap-profiler/issues"
},
"main": "src/index.js",
"scripts": {
"visualize-watch": "node debug/visualize-watch.js",
"visualize-all": "node debug/visualize-all.js",
"test": "npm run lint && tap",
"test:file": "standard | snazzy && tap --no-cov",
"ci-lint": "npm run lint",
"ci-test-cov": "tap",
"ci-test-no-cov": "tap --no-cov",
"lint": "standard --fix | snazzy"
"prepublishOnly": "npm run ci",
"postpublish": "git push origin && git push origin -f --tags",
"lint": "eslint src/**/*.js test/**/*.js",
"test": "tap --gc --reporter=spec --coverage-report=html --coverage-report=text --no-browser test/*.spec.js",
"ci": "npm run lint && tap --gc --no-color --reporter=spec --coverage-report=json --coverage-report=text --branches 90 --functions 90 --lines 90 --statements 90 --timeout 180 test/*.spec.js"
},
"tap": {
"nyc-arg": [
"--exclude=test/*.js",
"--exclude=visualizer/d3.js",
"--exclude=visualizer/data-tree.js",
"--exclude=visualizer/no-data-node.js"
]
},
"author": "",
"license": "MIT",
"dependencies": {
"@nearform/clinic-common": "^4.0.0",
"@nearform/heap-profiler": "^0.8.1",
"abort-controller": "^3.0.0",
"copy-to-clipboard": "^3.0.8",
"d3-array": "^2.0.2",
"d3-fg": "^6.13.1",
"d3-selection": "^1.3.2",
"fs-extra": "^9.0.1",
"lodash.debounce": "^4.0.8",
"on-net-listen": "1.1.2",
"pump": "^3.0.0",
"querystringify": "^2.1.0",
"sinusoidal-decimal": "^1.0.0"
"sonic-boom": "^1.0.1",
"abort-controller": "^3.0.0"
},
"devDependencies": {
"autocannon": "^6.5.0",
"chalk": "^4.1.0",
"chokidar": "^3.4.2",
"fastify": "^3.7.0",
"ioredis": "^4.17.3",
"open": "^7.3.0",
"snazzy": "^8.0.0",
"standard": "^14.3.1",
"tap": "^14.10.6"
"docker-namesgenerator": "0.0.1",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"prettier": "^1.19.1",
"sinon": "^9.0.1",
"tap": "^14.10.7",
"tmp-promise": "^2.0.2"
},
"engines": {
"node": ">= 12.13.0"
}
}

@@ -1,103 +0,108 @@

# Clinic.js Heap Profiler
# @nearform/heap-profiler
[![npm version][npm-version]][npm-url] [![Stability Stable][stability-stable]][stability-docs] [![Github Actions build status][actions-status]][actions-url]
[![Downloads][npm-downloads]][npm-url] [![Code style][lint-standard]][lint-standard-url]
[![Package Version](https://img.shields.io/npm/v/@nearform/heap-profiler.svg)](https://npm.im/@nearform/heap-profiler)
[![Dependency Status](https://img.shields.io/david/nearform/heap-profiler)](https://david-dm.org/nearform/heap-profiler)
[![Build Status](https://img.shields.io/github/workflow/status/nearform/heap-profiler/CI)](https://github.com/nearform/heap-profiler/actions?query=workflow%3ACI)
Programmable interface to [Clinic.js][clinic-url] Heap Profiler. Learn more about Clinic.js: https://clinicjs.org/
Heap dump and sample profiler generator for Node.
![Screenshot](screenshot.png)
## Installation
## Supported node versions
Just run:
- Node.js 10 and above
```bash
npm install @nearform/heap-profiler
```
## Example
## Preloader
```js
const ClinicHeapProfiler = require('@nearform/clinic-heap-profiler')
const heapProfiler = new ClinicHeapProfiler()
Once installed, the profiler can be used as a preloader that adds a listener to `SIGUSR2` signal.
heapProfiler.collect(['node', './path-to-script.js'], function (err, filepath) {
if (err) throw err
If you start your application like this:
heapProfiler.visualize(filepath, filepath + '.html', function (err) {
if (err) throw err
})
})
```
node -r @nearform/heap-profiler index.js
```
## Documentation
Then you will be able make a snapshot, start profiling heap, and start tracking allocation timeline by sending the process a SIGUSR2 signal, like this:
```js
const ClinicHeapProfiler = require('@nearform/clinic-heap-profiler')
const heapProfiler = new ClinicHeapProfiler()
```
kill -USR2 $PID
```
### new ClinicHeapProfiler([settings])
Heap snapshot will be generated immediately.
- settings [`<Object>`][]
- detectPort [`<boolean>`][] **Default**: false
- collectOnFailure [`<boolean>`][] If set to true, the collected data will be returned even if the process exits with non-zero code.
**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`
Heap sampling profiler and allocation timeline must be stopped, by sending another SIGUSR2 signal to the process.
#### `heapProfiler.collect(args, callback)`
Then the tool will await on the next signal, to resume profiling/tracking/shooting the heap.
Starts a process by using [@nearform/heap-profiler](https://github.com/nearform/heap-profiler).
The preloader uses the following environment variables to control its behavior:
The process sampling is started as soon as the process starts. The filepath with collected data will be the value in the callback.
- `HEAP_PROFILER_PRELOADER_DISABLED`: If set to `true`, the preloader is not installed and you need to use the API to sample the process.
`stdout`, `stderr`, and `stdin` will be relayed to the calling process.
- `HEAP_PROFILER_SNAPSHOT`: If set to `false`, it will not generate heap dump snapshots.
The sampling is stopped and data collected right before the process exits.
- `HEAP_PROFILER_SNAPSHOT_DESTINATION`: The path where to store the snapshot. The default will be a `.heapsnapshot` in the current directory.
If you want to collect data earlier, you can send the process a `SIGINT` or, if `detectPort` is `true`, you can call `heapProfiler.stopViaIPC()`.
- `HEAP_PROFILER_SNAPSHOT_RUN_GC`: If to run the garbage collector before taking the snapshot. The default is `false` and it is ignored if the process is not started with the `--expose-gc` flag.
#### `heapProfiler.visualize(dataFilename, outputFilename, callback)`
- `HEAP_PROFILER_PROFILE`: If set to `false`, it will not generate heap sampling profile.
Will consume the datafile specified by `dataFilename`, this datafile will be
produced by the sampler using `heapProfiler.collect`.
- `HEAP_PROFILER_PROFILE_DESTINATION`: The path where to store the profile. The default will be a `.heapprofile` in the current directory.
`heapProfiler.visualize` will then output a standalone HTML file to `outputFilename`.
When completed the `callback` will be called with no extra arguments, except a
possible error.
- `HEAP_PROFILER_PROFILE_INTERVAL`: Heap sampling profile interval, in bytes. Default is `32768` (32KB).
#### `heapProfiler.stopViaIPC()`
- `HEAP_PROFILER_TIMELINE`: If set to `false`, it will not start tracking timeline allocation.
When the profiler is started with `detectPort=true`, the profiler establish a TCP based IPC communication.
- `HEAP_PROFILER_TIMELINE_DESTINATION`: The path where to store the allocation timeline. The default will be a `.heaptimeline` in the current directory.
This method can therefore be called to collect the data at any time.
- `HEAP_PROFILER_TIMELINE_RUN_GC`: Whether or not running Garbage Collector before and after the allocation timeline, to see only remaining objects (default to false).
If no TCP channel is opened or available, the method will perform no operation so it is safe to call at all times.
- `HEAP_PROFILER_LOGGING_DISABLED`: If set to `true`, it will disable logging.
## Examples
## API
See the `examples` folder. All example should be run from the repository main folder:
All module functions can be used with promises and by providing a callback as last option.
```sh
node examples/redis-web-service
```
The promise resolved value (or the callback argument) will be the generated file path.
Each `index.js` will contain any specific setup step required by the example, if any.
The available functions are:
- `generateHeapSnapshot([options], [callback]): [Promise]`: Generates a heap dump
- `destination`: The path where to store the snapshot. The default will be a `.heapsnapshot` in the current directory.
- `runGC`: If to run the garbage collector before taking the snapshot. The default is `false` and it is ignored if the process is not started with the `--expose-gc` flag.
- `generateHeapSamplingProfile([options], [callback]): [Promise]`: Starts generating a heap sampling profiler. The valid options are:
- `destination`: The path where to store the profile. The default will be a `.heapprofile` in the current directory.
- `interval`: Sample interval, in bytes. Default is `32768` (32KB).
- `duration`: Sample duration, in milliseconds. Default is `10000` (10 seconds), and it is ignored if `signal` is provided.
- `signal`: The [AbortController](http://npm.im/abort-controller) `signal` to use to stop the operation.
The function accepts a callback function, otherwise it returns a Promise. The resolved value (or the callback argument) will be
the generated file path.
- `recordAllocationTimeline([options], [callback]): [Promise]`: Starts recording allocation on heap. The valid options are:
- `destination`: The path where to store the timeline. The default will be a `.heaptimeline` in the current directory.
- `runGC`: If to run the garbage collector at the begining and the end of the timeline. The default is `false` and it is ignored if the process is not started with the `--expose-gc` flag.
- `duration`: Recording duration, in milliseconds. Default is `10000` (10 seconds), and it is ignored if `signal` is provided.
- `signal`: The [AbortController](http://npm.im/abort-controller) `signal` to use to stop the operation.
The function accepts a callback function, otherwise it returns a Promise. The resolved value (or the callback argument) will be
the generated file path.
## Performance impact
Generating a heap dump snapshot is handled synchronously by Node and therefore **will block your process completely**.
Generating a heap sampling profile or record allocation timeline is instead asynchronous and lightweight. Our test showed that the **performance decrease is around 10%**.
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md)
## License
[MIT](LICENSE)
[stability-stable]: https://img.shields.io/badge/stability-stable-green.svg?style=flat-square
[stability-docs]: https://nodejs.org/api/documentation.html#documentation_stability_index
[npm-version]: https://img.shields.io/npm/v/@nearform/clinic-heap-profiler.svg?style=flat-square
[npm-url]: https://www.npmjs.org/@nearform/clinic-heap-profiler
[npm-downloads]: http://img.shields.io/npm/dm/@nearform/clinic-heap-profiler.svg?style=flat-square
[lint-standard]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
[lint-standard-url]: https://github.com/feross/standard
[clinic-url]: https://github.com/nearform/node-clinic
[`<object>`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[`<number>`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
[`<boolean>`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
[`<string>`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
[actions-status]: https://github.com/nearform/node-clinic-flame/workflows/CI/badge.svg
[actions-url]: https://github.com/nearform/node-clinic-flame/actions
Copyright NearForm Ltd 2020. Licensed under the [Apache-2.0 license](http://www.apache.org/licenses/LICENSE-2.0).
'use strict'
const { spawn } = require('child_process')
const events = require('events')
const fs = require('fs')
const { ensureDir } = require('fs-extra')
const { createConnection, createServer } = require('net')
const path = require('path')
const pump = require('pump')
const buildJs = require('@nearform/clinic-common/scripts/build-js')
const buildCss = require('@nearform/clinic-common/scripts/build-css')
const mainTemplate = require('@nearform/clinic-common/templates/main')
const { analyse } = require('./analysis/index.js')
const generateHeapSnapshot = require('./snapshot')
const generateHeapSamplingProfile = require('./profile')
/* istanbul ignore next */
const noop = function () {}
module.exports = { generateHeapSnapshot, generateHeapSamplingProfile }
function execute (instance, args, env, nodeOptions, cb) {
ensureDir(path.dirname(instance.dest), err => {
/* istanbul ignore if */
if (err) {
cb(err)
return
}
if (process.env.HEAP_PROFILER_PRELOADER_DISABLED !== 'true' && require.main === undefined) {
let logger = console
env.NODE_OPTIONS = nodeOptions
/*
By default spawn creates a process in the same process group of the current one.
This means that SIGINT are received both from the parent and child processes.
We handle SIGINT in the child, so we want to ignore in the parent.
*/
process.once('SIGINT', noop)
instance.process = spawn(args[0], args.slice(1), { stdio: ['ignore', 'inherit', 'inherit'], env })
instance.process.once('exit', (code, signal) => {
process.removeListener('SIGINT', noop)
instance.emit('analysing')
if (code && !instance.collectOnFailure) {
cb(new Error(`Child process exited with code ${code}.`))
return
}
cb(null, instance.dest)
})
})
}
function writeHtml (data, outputFilename, debug, cb) {
const fakeDataPath = path.join(__dirname, 'visualizer', 'data.json')
const stylePath = path.join(__dirname, 'visualizer', 'style.css')
const scriptPath = path.join(__dirname, 'visualizer', 'main.js')
const logoPath = path.join(__dirname, 'visualizer/assets', 'heap-profiler-logo.svg')
const nearFormLogoPath = path.join(__dirname, 'visualizer', 'nearform-logo.svg')
const clinicFaviconPath = path.join(__dirname, 'visualizer', 'clinic-favicon.png.b64')
// add logos
const logoFile = fs.createReadStream(logoPath)
const nearFormLogoFile = fs.createReadStream(nearFormLogoPath)
const clinicFaviconBase64 = fs.createReadStream(clinicFaviconPath)
const version = require('../package.json').version
// build JS
const scriptFile = buildJs({
basedir: __dirname,
debug,
fakeDataPath,
scriptPath,
beforeBundle (b) {
b.require({ source: JSON.stringify(data), file: fakeDataPath })
},
env: {
PRESENTATION_MODE: process.env.PRESENTATION_MODE
}
})
// build CSS
const styleFile = buildCss({ stylePath, debug })
// generate HTML
const outputFile = mainTemplate({
favicon: clinicFaviconBase64,
title: 'Clinic Heap Profiler',
styles: styleFile,
script: scriptFile,
headerLogoUrl: 'https://clinicjs.org/heap-profiler/',
headerLogoTitle: 'Clinic Heap Profiler on Clinicjs.org',
headerLogo: logoFile,
headerText: 'Heap Profiler',
toolVersion: version,
nearFormLogo: nearFormLogoFile,
uploadId: outputFilename.split('/').pop().split('.html').shift(),
body: '<main></main>'
})
pump(outputFile, fs.createWriteStream(outputFilename), cb)
}
class ClinicHeapProfiler extends events.EventEmitter {
constructor (settings = {}) {
super()
const {
detectPort = false,
collectOnFailure = false,
debug = false,
dest = `.clinic/${process.pid}.clinic-heapprofile`
} = settings
this.detectPort = !!detectPort
this.collectOnFailure = !!collectOnFailure
this.debug = debug
this.dest = dest
if (process.env.HEAP_PROFILER_LOGGING_DISABLED === 'true') {
logger = { info: () => {}, error: () => {} }
}
collect (args, cb) {
const nodeOptions = ` -r ${path.join(__dirname, './injects/ipc.js')}`
const env = {
...process.env,
HEAP_PROFILER_DESTINATION: this.dest,
HEAP_PROFILER_PRELOADER_DISABLED: 'true',
HEAP_PROFILER_USE_IPC: this.detectPort
}
if (!this.detectPort) {
execute(this, args, env, nodeOptions, cb)
return
}
let applicationPort
const server = createServer(socket => {
socket.on('data', raw => {
const port = parseInt(raw.toString(), 0)
/* istanbul ignore if */
if (isNaN(port)) {
return
}
// That's the IPC port
if (port < 0) {
this.ipcPort = -port
} else {
applicationPort = port
}
if (this.detectPort && this.ipcPort && applicationPort) {
server.close()
/*
The last argument, by clinic CLI contract, is required when using --autocannon or --on-port option.
The CLI invokes the callback when the tool --autocannon or --on-port tool has finished.
*/
this.emit('port', applicationPort, null, this.stopViaIPC.bind(this))
}
})
}).on(
'error',
/* istanbul ignore next */
err => {
return cb(err)
}
)
// Grab an arbitrary unused port
server.listen(0, () => {
env.CLINIC_HEAP_PROFILER_PORT = server.address().port
execute(this, args, env, nodeOptions, cb)
})
}
visualize (sourceFile, outputFilename, cb) {
analyse(sourceFile, (err, converted) => {
if (err) {
return cb(err)
}
writeHtml(converted, outputFilename, this.debug, cb)
})
}
stopViaIPC () {
if (!this.ipcPort) {
return
}
const client = createConnection({ port: this.ipcPort }, () => {
client.end('clinic-heap-profiler:stop')
})
// Ignore if nobody is listening
client.on('error', noop)
}
require('./preloader')(logger)
}
module.exports = ClinicHeapProfiler

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc