Repository: aksakalli/gtop Branch: master Commit: ac6c2e11a683 Files: 23 Total size: 15.7 KB Directory structure: gitextract_hnj0je3y/ ├── .editorconfig ├── .github/ │ ├── CONTRIBUTING.md │ ├── ISSUE_TEMPLATE.md │ └── workflows/ │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .npmignore ├── CLI.md ├── Dockerfile ├── LICENSE ├── README.md ├── bin/ │ └── gtop ├── index.js ├── lib/ │ ├── gtop.js │ ├── monitor/ │ │ ├── cpu.js │ │ ├── disk.js │ │ ├── index.js │ │ ├── mem.js │ │ ├── net.js │ │ └── proc.js │ └── utils.js ├── package.json └── snap/ └── snapcraft.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true end_of_line = lf # editorconfig-tools is unable to ignore longs strings or urls max_line_length = null ================================================ FILE: .github/CONTRIBUTING.md ================================================ PRs are welcome, please make sure that your changes are well tested ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ #### Environment - OS: - Node version: (`$ node --version`) - gtop version: (`$ npm info gtop version`) #### Description *A description of the issue* ================================================ FILE: .github/workflows/ci.yml ================================================ name: Node.js CI on: push: branches: - master pull_request: branches: - master jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js 17.x uses: actions/setup-node@v2 with: node-version: '17.x' - name: Install dependencies run: npm ci - name: Lint check run: npm run lint-check - name: Test run: npm test ================================================ FILE: .github/workflows/release.yml ================================================ name: Node.js Package on: release: types: [created] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Setup .npmrc file to publish to npm - uses: actions/setup-node@v2 with: node-version: '17.x' registry-url: 'https://registry.npmjs.org' - run: npm install - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Typescript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env ================================================ FILE: .npmignore ================================================ .git* test/ img/ node_modules/ *.gif *.png .github/ snap/ ================================================ FILE: CLI.md ================================================ GTOP ===== > gtop - System monitoring dashboard for terminal ## SYNOPSIS `gtop` ## DESCRIPTION gtop is a system monitoring dashboard for terminal much like htop, top, etc... ## INTERACTIVE COMMANDS The following commands are supported while in gtop: - `p` sort the process table by Process Id - `c` sort the process table by CPU usage - `m` sort the process table by Memory usage ## Website https://github.com/aksakalli/gtop ## BUGS Please report any bugs to https://github.com/aksakalli/gtop. ## LICENSE Copyright (c) 2017, Can Güney Aksakalli (MIT License). ## SEE ALSO node.js(1), ================================================ FILE: Dockerfile ================================================ FROM node:15-alpine RUN apk --no-cache add procps ENV LANG=en_US.utf8 \ TERM=xterm-256color COPY lib lib COPY bin bin COPY package.json . COPY package-lock.json . RUN npm install --production ENTRYPOINT ["./bin/gtop"] ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2017 Can Güney Aksakalli 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 ================================================ # gtop ![screen record](https://raw.githubusercontent.com/aksakalli/gtop/master/img/demo.gif) System monitoring dashboard for terminal. [![NPM Version](https://img.shields.io/npm/v/gtop.svg)](https://npmjs.org/package/gtop) [![NPM Downloads](https://img.shields.io/npm/dm/gtop.svg)](https://npmjs.org/package/gtop) [![Snap Status](https://snapcraft.io/gtop/badge.svg)](https://snapcraft.io/gtop) [![Docker Pulls](https://img.shields.io/docker/pulls/aksakalli/gtop)](https://hub.docker.com/r/aksakalli/gtop) [![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/aksakalli/gtop)](https://hub.docker.com/r/aksakalli/gtop/builds) ### Requirements * Linux / OSX / Windows (partial support) * Node.js >= v8 ### Installation ```sh $ npm install gtop -g ``` #### Docker You need to assign host `net` and `pid` to access the metrics in the host machine. ```sh $ docker run --rm -it \ --name gtop \ --net="host" \ --pid="host" \ aksakalli/gtop ``` ### Usage Start gtop with the `gtop` command ```sh $ gtop ``` To stop gtop use `q`, or `ctrl+c` in most shell environments. You can sort the process table by pressing * `p`: Process Id * `c`: CPU usage * `m`: Memory usage ### Troubleshooting If you see question marks or other different characters, try to run it with these environment variables: ```sh $ LANG=en_US.utf8 TERM=xterm-256color gtop ``` ## License Released under [the MIT license](LICENSE). ================================================ FILE: bin/gtop ================================================ #!/usr/bin/env node require('../lib/gtop').init() ================================================ FILE: index.js ================================================ module.exports = require('./lib/gtop'); ================================================ FILE: lib/gtop.js ================================================ var blessed = require('blessed'), contrib = require('blessed-contrib'), monitor = require('./monitor'); var screen = blessed.screen(); var grid = new contrib.grid({ rows: 12, cols: 12, screen: screen, }); var cpuLine = grid.set(0, 0, 4, 12, contrib.line, { showNthLabel: 5, maxY: 100, label: 'CPU History', showLegend: true, }); var memLine = grid.set(4, 0, 4, 8, contrib.line, { showNthLabel: 5, maxY: 100, label: 'Memory and Swap History', showLegend: true, legend: { width: 10, }, }); var memDonut = grid.set(4, 8, 2, 4, contrib.donut, { radius: 8, arcWidth: 3, yPadding: 2, remainColor: 'black', label: 'Memory', }); var swapDonut = grid.set(6, 8, 2, 4, contrib.donut, { radius: 8, arcWidth: 3, yPadding: 2, remainColor: 'black', label: 'Swap', }); var netSpark = grid.set(8, 0, 2, 6, contrib.sparkline, { label: 'Network History', tags: true, style: { fg: 'blue', }, }); var diskDonut = grid.set(10, 0, 2, 6, contrib.donut, { radius: 8, arcWidth: 3, yPadding: 2, remainColor: 'black', label: 'Disk usage', }); var procTable = grid.set(8, 6, 4, 6, contrib.table, { keys: true, label: 'Processes', columnSpacing: 1, columnWidth: [7, 24, 7, 7], }); procTable.focus(); screen.render(); screen.on('resize', function(a) { cpuLine.emit('attach'); memLine.emit('attach'); memDonut.emit('attach'); swapDonut.emit('attach'); netSpark.emit('attach'); diskDonut.emit('attach'); procTable.emit('attach'); }); screen.key(['escape', 'q', 'C-c'], function(ch, key) { return process.exit(0); }); function init() { new monitor.Cpu(cpuLine); //no Windows support new monitor.Mem(memLine, memDonut, swapDonut); new monitor.Net(netSpark); new monitor.Disk(diskDonut); new monitor.Proc(procTable); // no Windows support } process.on('uncaughtException', function(err) { // avoid exiting due to unsupported system resources in Windows }); module.exports = { init: init, monitor: monitor, }; ================================================ FILE: lib/monitor/cpu.js ================================================ var si = require('systeminformation'), utils = require('../utils'); var colors = utils.colors; function Cpu(line) { this.line = line; si.currentLoad(data => { this.cpuData = data.cpus.map((cpu, i) => { return { title: 'CPU' + (i + 1), style: { line: colors[i % colors.length], }, x: Array(61) .fill() .map((_, i) => 60 - i), y: Array(61).fill(0), }; }); this.updateData(data); this.interval = setInterval(() => { si.currentLoad(data => { this.updateData(data); }); }, 1000); }); } Cpu.prototype.updateData = function(data) { data.cpus.forEach((cpu, i) => { var loadString = cpu.load.toFixed(1).toString(); while (loadString.length < 6) { loadString = ' ' + loadString; } loadString = loadString + '%'; this.cpuData[i].title = 'CPU' + (i + 1) + loadString; this.cpuData[i].y.shift(); this.cpuData[i].y.push(cpu.load); }); this.line.setData(this.cpuData); this.line.screen.render(); }; module.exports = Cpu; ================================================ FILE: lib/monitor/disk.js ================================================ var si = require('systeminformation'), utils = require('../utils'); var colors = utils.colors; function Disk(donut) { this.donut = donut; si.fsSize(data => { this.updateData(data); }); this.interval = setInterval(() => { si.fsSize(data => { this.updateData(data); }); }, 10000); } Disk.prototype.updateData = function(data) { var disk = data[0]; var label = utils.humanFileSize(disk.used, true) + ' of ' + utils.humanFileSize(disk.size, true); this.donut.setData([ { percent: disk.use / 100, label: label, color: colors[5], }, ]); this.donut.screen.render(); }; module.exports = Disk; ================================================ FILE: lib/monitor/index.js ================================================ module.exports = { Cpu: require('./cpu'), Mem: require('./mem'), Net: require('./net'), Disk: require('./disk'), Proc: require('./proc'), }; ================================================ FILE: lib/monitor/mem.js ================================================ var si = require('systeminformation'), utils = require('../utils'); var colors = utils.colors; function Mem(line, memDonut, swapDonut) { this.line = line; this.memDonut = memDonut; this.swapDonut = swapDonut; si.mem(data => { this.memData = [ { title: 'Memory', style: { line: colors[0], }, x: Array(61) .fill() .map((_, i) => 60 - i), y: Array(61).fill(0), }, { title: 'Swap', style: { line: colors[1], }, x: Array(61) .fill() .map((_, i) => 60 - i), y: Array(61).fill(0), }, ]; this.updateData(data); this.interval = setInterval(() => { si.mem(data => { this.updateData(data); }); }, 1000); }); } Mem.prototype.updateData = function(data) { var memPer = (100 * (1 - data.available / data.total)).toFixed(); var swapPer = (100 * (1 - data.swapfree / data.swaptotal)).toFixed(); swapPer = isNaN(swapPer) ? 0 : swapPer; this.memData[0].y.shift(); this.memData[0].y.push(memPer); this.memData[1].y.shift(); this.memData[1].y.push(swapPer); var memTitle = utils.humanFileSize(data.total - data.available) + ' of ' + utils.humanFileSize(data.total); var swapTitle = utils.humanFileSize(data.swaptotal - data.swapfree) + ' of ' + utils.humanFileSize(data.swaptotal); this.line.setData(this.memData); this.memDonut.setData([ { percent: memPer / 100, label: memTitle, color: colors[0], }, ]); this.swapDonut.setData([ { percent: swapPer / 100, label: swapTitle, color: colors[1], }, ]); this.line.screen.render(); }; module.exports = Mem; ================================================ FILE: lib/monitor/net.js ================================================ var si = require('systeminformation'), utils = require('../utils'); var colors = utils.colors; function Net(sparkline) { this.sparkline = sparkline; this.netData = [Array(61).fill(0), Array(61).fill(0)]; si.networkInterfaceDefault(iface => { var that = this; var updater = function() { si.networkStats(iface, data => { that.updateData(data[0]); }); }; updater(); this.interval = setInterval(updater, 1000); }); } Net.prototype.updateData = function(data) { var rx_sec = Math.max(0, data['rx_sec']); var tx_sec = Math.max(0, data['tx_sec']); this.netData[0].shift(); this.netData[0].push(rx_sec); this.netData[1].shift(); this.netData[1].push(tx_sec); rx_label = 'Receiving: ' + utils.humanFileSize(rx_sec) + '/s \nTotal received: ' + utils.humanFileSize(data['rx_bytes']); tx_label = 'Transferring: ' + utils.humanFileSize(tx_sec) + '/s \nTotal transferred: ' + utils.humanFileSize(data['tx_bytes']); this.sparkline.setData([rx_label, tx_label], this.netData); this.sparkline.screen.render(); }; module.exports = Net; ================================================ FILE: lib/monitor/proc.js ================================================ var si = require('systeminformation'), utils = require('../utils'); var colors = utils.colors; var pars = { p: 'pid', c: 'cpu', m: 'mem', }; function Proc(table) { this.table = table; this.pSort = pars.c; this.reIndex = false; this.reverse = false; var that = this; var updater = function() { si.processes(data => { that.updateData(data); }); }; updater(); this.interval = setInterval(updater, 3000); this.table.screen.key(['m', 'c', 'p'], function(ch, key) { if (pars[ch] == that.pSort) { that.reverse = !that.reverse; } else { that.pSort = pars[ch] || that.pSort; } that.reIndex = true; updater(); }); } Proc.prototype.updateData = function(data) { var par = this.pSort; var data = data.list .sort(function(a, b) { return b[par] - a[par]; }) .map(p => { return [ p.pid, p.command, //.slice(0,10), ' ' + p.cpu.toFixed(1), p.mem.toFixed(1), ]; }); var headers = ['PID', 'Command', '%CPU', '%MEM']; headers[ { pid: 0, cpu: 2, mem: 3, }[this.pSort] ] += this.reverse ? '▲' : '▼'; this.table.setData({ headers: headers, data: this.reverse ? data.reverse() : data, }); if (this.reIndex) { this.table.rows.select(0); this.reIndex = false; } this.table.screen.render(); }; module.exports = Proc; ================================================ FILE: lib/utils.js ================================================ var utils = {}; utils.humanFileSize = function(bytes, isDecimal) { isDecimal = typeof isDecimal !== 'undefined' ? isDecimal : false; if (bytes == 0) { return '0.00 B'; } var base = isDecimal ? 1000 : 1024; var e = Math.floor(Math.log(bytes) / Math.log(base)); return ( (bytes / Math.pow(base, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + (isDecimal || e == 0 ? '' : 'i') + 'B' ); }; utils.colors = ['magenta', 'cyan', 'blue', 'yellow', 'green', 'red']; module.exports = utils; ================================================ FILE: package.json ================================================ { "name": "gtop", "version": "1.1.5", "description": "graphic top", "main": "./index.js", "bin": { "gtop": "./bin/gtop" }, "scripts": { "test": "echo \"Test will be implemented.\" && exit 0", "start": "./bin/gtop", "lint": "prettier --single-quote --trailing-comma es5 --write 'lib/**/*.js'", "lint-check": "prettier --check --single-quote --trailing-comma es5 'lib/**/*.js'", "prepublishOnly": "marked-man --version $npm_package_version --manual 'Gtop Help' --section 1 ./CLI.md > gtop.1" }, "man": ["./gtop.1"], "repository": { "type": "git", "url": "git+https://github.com/aksakalli/gtop.git" }, "keywords": [ "system", "monitoring", "top", "chart", "monitor", "dashboard", "os" ], "author": "aksakalli", "license": "MIT", "bugs": { "url": "https://github.com/aksakalli/gtop/issues" }, "homepage": "https://github.com/aksakalli/gtop#readme", "dependencies": { "blessed": "^0.1.81", "blessed-contrib": "^4.11.0", "systeminformation": "^5.18.15" }, "engines": { "node": ">=4.0.0" }, "devDependencies": { "marked-man": "^1.3.3", "prettier": "1.19.1" } } ================================================ FILE: snap/snapcraft.yaml ================================================ name: gtop summary: System monitoring dashboard for terminal description: | System monitoring dashboard for terminal version: v1.1.5 base: core22 grade: stable confinement: classic apps: gtop: command: bin/gtop parts: gtop: source: https://github.com/aksakalli/gtop.git source-tag: ${SNAPCRAFT_PROJECT_VERSION} plugin: npm npm-include-node: true npm-node-version: "17.3.0"