Repository: soyuka/pidusage
Branch: main
Commit: 36383b8d70c2
Files: 32
Total size: 62.8 KB
Directory structure:
gitextract_s94v4rqx/
├── .github/
│ └── workflows/
│ ├── alpine.yml
│ ├── lint.yml
│ ├── macos.yml
│ ├── test.yml
│ └── windows.yml
├── .gitignore
├── CHANGELOG.md
├── Dockerfile
├── LICENSE
├── README.md
├── examples/
│ ├── README.md
│ ├── server.js
│ └── stresstest.js
├── index.js
├── lib/
│ ├── bin.js
│ ├── gwmi.js
│ ├── helpers/
│ │ ├── cpu.js
│ │ └── parallel.js
│ ├── history.js
│ ├── procfile.js
│ ├── ps.js
│ ├── stats.js
│ └── wmic.js
├── package.json
└── test/
├── bench.js
├── fixtures/
│ └── _eventloop.js
├── gwmi.js
├── helpers/
│ └── _mocks.js
├── integration.js
├── procfile.js
├── ps.js
└── wmic.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/alpine.yml
================================================
name: test-alpine
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
test:
runs-on: ubuntu-latest
name: Test alpine
steps:
- uses: actions/checkout@v2
- run: |
docker build . -t pidusage
docker run -v $(pwd):/var/pidusage pidusage:latest npm install
docker run -v $(pwd):/var/pidusage pidusage:latest npm test
================================================
FILE: .github/workflows/lint.yml
================================================
name: lint
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
lint:
runs-on: ubuntu-latest
name: Lint
steps:
- name: Setup repo
uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v1
- name: Install dev dependencies
run: |
npm install --only=dev
- name: Run lint
run: npm run lint
================================================
FILE: .github/workflows/macos.yml
================================================
name: test-macos
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
test:
runs-on: macos-latest
name: Test MacOS
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
- run: npm install
- run: npm test
================================================
FILE: .github/workflows/test.yml
================================================
name: linux
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [ '18', '20', '22', '23' ]
name: Test Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- run: npm install
- run: npm test
coverage:
runs-on: ubuntu-latest
name: Test coverage
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
- run: npm install
- run: npm run coverage
- uses: codecov/codecov-action@v5
================================================
FILE: .github/workflows/windows.yml
================================================
name: test-windows
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
test:
runs-on: windows-latest
name: Test Windows
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
- run: npm install
- run: npm test
================================================
FILE: .gitignore
================================================
node_modules
.nyc_output
coverage
================================================
FILE: CHANGELOG.md
================================================
### 4.0.1
- fix spawned wmic processes not exiting after wmic/gwmi detection in packaged apps, leading to infinite build up of "WMI Commandline Utility" processes and system instability
### 4.0.0
- fix wmic removed on Windows 11 and add gwmi support
- node >= 17
### 3.0.1
- removed dynamic requires to allow for bundling #154
- add ibm platform (os400) #158
### 3.0
- removes node 8 support
- add z/OS (os390) support
- environment variables to configure pidusage (`PIDUSAGE_USE_PS`, `PIDUSAGE_MAXAGE`, `PIDUSAGE_SILENT`)
- use a default Date when `uptime` returns `undefined`
### 2.0.17
- allow to manually clear the event loop when needed it'll clear itself after a given timeout (default to `60000ms` but you can specify it with the `maxage` option, [see this file](https://github.com/soyuka/pidusage/blob/master/test/fixtures/eventloop.js#L3)) [1740a4f](https://github.com/soyuka/pidusage/commit/2779e520d3414a8318c86279cf14bebae3264604)
- fix elapsed and timestamp calculations on linux [#80](https://github.com/soyuka/pidusage/issues/80) [e5e2b01](https://github.com/soyuka/pidusage/commit/081984a04bc97ad8abd82315f936861cce1df0d6)
### 2.0.16
- fix ps on darwin, centisenconds multiplier was wrong and was giving bad cpu usage values [bcda538](https://github.com/soyuka/pidusage/commit/bcda538b76498c6d4bcaa36520238990554929c5)
### 2.0.15
- Fix Buffer.alloc for node < 4.5
### 2.0.14
- Version unpublished because of a publish mistake from my part due to a npm error message that confused me. Explanation [in isse #71](https://github.com/soyuka/pidusage/issues/72#issuecomment-407572581)
### 2.0.12
- fix #69 with `ps` use elapsed instead of etime to avoid negative cpu values [0994268](https://github.com/soyuka/pidusage/commit/0994268c297e23efa3d9052f24cbacf2cbe31629)
- fix typo in aix `ps` command #68 [7d55518](https://github.com/soyuka/pidusage/commit/7d55518b7d5d5aae964e64ddd7b13ecec75463a1)
### 2.0.10
- aix is using ps (was changed by mistake), still no aix CI though
- add alpine to the test suite and make it use procfile
- Improve procfile performances by keeping the procfile open [da1c5fb](https://github.com/soyuka/pidusage/commit/da1c5fb2480bdf8f871476d79161dac7733b89f3)
### 2.0.8
- After further discussion cpu formula got reverted to the initial one [f990f72](https://github.com/soyuka/pidusage/commit/f990f72fd185e4ba0a87048e6e6c59f814a016cc)
### 2.0.7
- Cpu formula changed a bit because of multi thread issues see [issue #58](https://github.com/soyuka/pidusage/issues/58) [88972d8](https://github.com/soyuka/pidusage/commit/88972d8cd38d4137b70261a830af22283b69c57c)
### 2.0.6
- procfiles are back because of performance issues [85e20fa](https://github.com/soyuka/pidusage/commit/85e20fa30aa9ff01d87d3ba9be7fec7f805fc5fb)
### 2.0
- allow multiple pids
- remove `advanced` option
- don't use `/proc` (procfiles) anymore but use `ps` instead
- more tests
- API change no more `stat` method, module exports a single function
- no more `unmonitor` method, this is handed internally
- the default call now returns more data:
```
{
cpu: 10.0, // percentage (it may happen to be greater than 100%)
memory: 357306368, // bytes
ppid: 312, // PPID
pid: 727, // PID
ctime: 867000, // ms user + system time
elapsed: 6650000, // ms since the start of the process
timestamp: 864000000 // ms since epoch
}
```
### 1.2.0
Introduce `advanced` option to get time, and start
### 1.1.0
Windows: (wmic) goes back to the first version of wmic, naming `wmic process {pid} get workingsetsize,usermodetime,kernelmodetime`. CPU usage % is computed on the flight, per pid.
### 1.0.5
Windows: (wmic) Use raw data instead of formatted this should speed up wmic
### 0.1.0
API changes:
```
require('pidusage').stat(pid, fn)
```
instead of:
```
require('pidusage')(pid, fn)
```
Adds a `unmonitor` method to clear process history
================================================
FILE: Dockerfile
================================================
FROM node:alpine
RUN mkdir -p /var/pidusage
WORKDIR /var/pidusage
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 soyuka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# pidusage
[](https://github.com/soyuka/pidusage/actions?query=workflow:lint+branch:main)
[](https://github.com/soyuka/pidusage/actions?query=workflow:test-macos+branch:main)
[](https://github.com/soyuka/pidusage/actions?query=workflow:linux+branch:main)
[](https://github.com/soyuka/pidusage/actions?query=workflow:test-windows+branch:main)
[](https://github.com/soyuka/pidusage/actions?query=workflow:test-alpine+branch:main)
[](https://codecov.io/gh/soyuka/pidusage)
[](https://www.npmjs.com/package/pidusage)
[](https://github.com/soyuka/pidusage/tree/master/license)
Cross-platform process cpu % and memory usage of a PID.
## Synopsis
Ideas from https://github.com/arunoda/node-usage but with no C-bindings.
Please note that if you need to check a Node.JS script process cpu and memory usage, you can use [`process.cpuUsage`][node:cpuUsage] and [`process.memoryUsage`][node:memUsage] since node v6.1.0. This script remain useful when you have no control over the remote script, or if the process is not a Node.JS process.
## Usage
```js
var pidusage = require('pidusage')
pidusage(process.pid, function (err, stats) {
console.log(stats)
// => {
// cpu: 10.0, // percentage (from 0 to 100*vcore)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
// ctime: 867000, // ms user + system time
// elapsed: 6650000, // ms since the start of the process
// timestamp: 864000000 // ms since epoch
// }
cb()
})
// It supports also multiple pids
pidusage([727, 1234], function (err, stats) {
console.log(stats)
// => {
// 727: {
// cpu: 10.0, // percentage (from 0 to 100*vcore)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
// ctime: 867000, // ms user + system time
// elapsed: 6650000, // ms since the start of the process
// timestamp: 864000000 // ms since epoch
// },
// 1234: {
// cpu: 0.1, // percentage (from 0 to 100*vcore)
// memory: 3846144, // bytes
// ppid: 727, // PPID
// pid: 1234, // PID
// ctime: 0, // ms user + system time
// elapsed: 20000, // ms since the start of the process
// timestamp: 864000000 // ms since epoch
// }
// }
})
// If no callback is given it returns a promise instead
const stats = await pidusage(process.pid)
console.log(stats)
// => {
// cpu: 10.0, // percentage (from 0 to 100*vcore)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
// ctime: 867000, // ms user + system time
// elapsed: 6650000, // ms since the start of the process
// timestamp: 864000000 // ms since epoch
// }
// Avoid using setInterval as they could overlap with asynchronous processing
function compute(cb) {
pidusage(process.pid, function (err, stats) {
console.log(stats)
// => {
// cpu: 10.0, // percentage (from 0 to 100*vcore)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
// ctime: 867000, // ms user + system time
// elapsed: 6650000, // ms since the start of the process
// timestamp: 864000000 // ms since epoch
// }
cb()
})
}
function interval(time) {
setTimeout(function() {
compute(function() {
interval(time)
})
}, time)
}
// Compute statistics every second:
interval(1000)
// Above example using async/await
const compute = async () => {
const stats = await pidusage(process.pid)
// do something
}
// Compute statistics every second:
const interval = async (time) => {
setTimeout(async () => {
await compute()
interval(time)
}, time)
}
interval(1000)
```
## Compatibility
| Property | Linux | FreeBSD | NetBSD | SunOS | macOS | Win | AIX | Alpine
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `cpu` | ✅ | ❓ | ❓ | ❓ | ✅ | ℹ️ | ❓ | ✅ |
| `memory` | ✅ | ❓ | ❓ | ❓ | ✅ | ✅ | ❓ | ✅ |
| `pid` | ✅ | ❓ | ❓ | ❓ | ✅ | ✅ | ❓ | ✅ |
| `ctime` | ✅ | ❓ | ❓ | ❓ | ✅ | ✅ | ❓ | ✅ |
| `elapsed` | ✅ | ❓ | ❓ | ❓ | ✅ | ✅ | ❓ | ✅ |
| `timestamp` | ✅ | ❓ | ❓ | ❓ | ✅ | ✅ | ❓ | ✅ |
✅ = Working
ℹ️ = Not Accurate
❓ = Should Work
❌ = Not Working
Please if your platform is not supported or if you have reported wrong readings
[file an issue][new issue].
By default, pidusage will use `procfile` parsing on most unix systems. If you want to use `ps` instead use the `usePs` option:
```
pidusage(pid, {usePs: true})
```
## API
### pidusage(pids, [options = {}], [callback]) ⇒ [Promise.<Object>]
Get pid informations.
**Kind**: global function
**Returns**: Promise.<Object> - Only when the callback is not provided.
**Access**: public
| Param | Type | Description |
| --- | --- | --- |
| pids | Number \| Array.<Number> \| String \| Array.<String> | A pid or a list of pids. |
| [options] | object | Options object. See the table below. |
| [callback] | function | Called when the statistics are ready. If not provided a promise is returned instead. |
### options
Setting the options programatically will override environment variables
| Param | Type | Environment variable | Default | Description |
| --- | --- | --- | --- | --- |
| [usePs] | boolean | `PIDUSAGE_USE_PS`| `false` | When true uses `ps` instead of proc files to fetch process information |
| [maxage] | number | `PIDUSAGE_MAXAGE`| `60000` | Max age of a process on history. |
`PIDUSAGE_SILENT=1` can be used to remove every console message triggered by pidusage.
### pidusage.clear()
If needed this function can be used to delete all in-memory metrics and clear the event loop. This is not necessary before exiting as the interval we're registring does not hold up the event loop.
## Related
- [pidusage-tree][gh:pidusage-tree] -
Compute a pidusage tree
## Authors
- **Antoine Bluchet** - [soyuka][github:soyuka]
- **Simone Primarosa** - [simonepri][github:simonepri]
See also the list of [contributors][contributors] who participated in this project.
## License
This project is licensed under the MIT License - see the [LICENSE][license] file for details.
[new issue]: https://github.com/soyuka/pidusage/issues/new
[license]: https://github.com/soyuka/pidusage/tree/master/LICENSE
[contributors]: https://github.com/soyuka/pidusage/contributors
[github:soyuka]: https://github.com/soyuka
[github:simonepri]: https://github.com/simonepri
[gh:pidusage-tree]: https://github.com/soyuka/pidusage-tree
[node:cpuUsage]: https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue
[node:memUsage]: https://nodejs.org/api/process.html#process_process_memoryusage
================================================
FILE: examples/README.md
================================================
# Example section
## server.js
Used to be tested with an HTTP benchmark tool like this one: https://github.com/wg/wrk.
Start the server, run the tests on `localhost:8020`
## stresstest.js
Just start node stresstest.js (but be carefull though...)
================================================
FILE: examples/server.js
================================================
const http = require('http')
const pidusage = require('../')
http.createServer(function (req, res) {
res.writeHead(200)
res.end('hello world\n')
}).listen(8020)
const interval = setInterval(function () {
pidusage(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log(stat)
})
}, 100)
process.on('exit', function () {
clearInterval(interval)
})
================================================
FILE: examples/stresstest.js
================================================
const pusage = require('../')
// stress test to compare with top or another tool
console.log('This is my PID: %s', process.pid)
// classic "drop somewhere"... yeah I'm a lazy guy
const formatBytes = function (bytes, precision) {
const kilobyte = 1024
const megabyte = kilobyte * 1024
const gigabyte = megabyte * 1024
const terabyte = gigabyte * 1024
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B '
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB '
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB '
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB '
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB '
} else {
return bytes + ' B '
}
}
let i = 0
const bigMemoryLeak = []
const stress = function (cb) {
let j = 500
const arr = []
while (j--) {
arr[j] = []
for (let k = 0; k < 1000; k++) {
arr[j][k] = { lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum non odio venenatis, pretium ligula nec, fringilla ipsum. Sed a erat et sem blandit dignissim. Pellentesque sollicitudin felis eu mattis porta. Nullam nec nibh nisl. Phasellus convallis vulputate massa vitae fringilla. Etiam facilisis lectus in odio lacinia rutrum. Praesent facilisis vitae urna a suscipit. Aenean lacinia blandit lorem, et ullamcorper metus sagittis faucibus. Nam porta eros nisi, at adipiscing quam varius eu. Vivamus sed sem quis lorem varius posuere ut quis elit.' }
}
}
bigMemoryLeak.push(arr)
pusage(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
if (i === 100) {
return cb(null, true)
} else if (stat.memory > 3e8) {
console.log("That's enough right?")
cb(null, true)
}
i++
return cb(null, false)
})
}
const interval = function () {
return setTimeout(function () {
stress(function (err, stop) {
if (err) {
throw err
}
if (stop) {
process.exit()
} else {
return interval()
}
})
}, 400)
}
setTimeout(function () {
interval()
}, 2000)
================================================
FILE: index.js
================================================
'use strict'
const stats = require('./lib/stats')
/**
* Get pid informations.
* @public
* @param {Number|Number[]|String|String[]} pids A pid or a list of pids.
* @param {Object} [options={}] Options object
* @param {Function} [callback=undefined] Called when the statistics are ready.
* If not provided a promise is returned instead.
* @returns {Promise.