| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- import { IPtyForkOptions, IWindowsPtyForkOptions, spawn } from 'node-pty';
- import { Logger, LogLevel } from '../../common/util/logger.class';
- const LOG_LEVEL: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'INFO';
- Logger.logLevel = LOG_LEVEL;
- export type MemoryUsage = { used: number; avail: number; unit: string };
- export class TopTTY {
- private cpuSubscriber?: (usage: number) => void;
- private ramSubscriber?: (usage: MemoryUsage) => void;
- public subscribe = {
- cpu: (subscriber: (usage: number) => void) => {
- this.cpuSubscriber = subscriber;
- },
- ram: (subscriber: (usage: MemoryUsage) => void) => {
- this.ramSubscriber = subscriber;
- }
- };
- public async runloop() {
- while (true) {
- try {
- await execTTY('top -d 0.5', { cols: 100, rows: 10, env: { LC_ALL: 'C' } }, (line: string) => {
- if (line.includes('Cpu')) {
- line = line.replace(/\u001b(\[|\()([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGKB]/g, ''); // get rid of tty color format codes
- line = line.replace(/:/g, ' ');
- const tokens = line.split(/\s+|,/g).filter(v => !!v); // split by whitespace and colon, omit emties
- const usage = Number(tokens[tokens.length - 14]) + Number(tokens[tokens.length - 16]);
- if (this.cpuSubscriber) this.cpuSubscriber(usage);
- } else if (/^([KMGPT]i)?B\s+Mem\s*:/.test(line)) {
- line = line.replace(/\u001b(\[|\()([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGKB]/g, ''); // get rid of tty color format codes
- line = line.replace(/:/g, ' ');
- const tokens = line.split(/\s+/g).filter(v => !!v); // split by whitespace, omit emties
- const unit = tokens[0];
- const avail = Number(tokens[2]);
- const used = Number(tokens[6]);
- if (this.ramSubscriber) this.ramSubscriber({ unit, avail, used });
- }
- });
- } catch (err) {
- Logger.error('top runloop crashed:', err);
- Logger.info('Restaring top runloop...');
- }
- await new Promise<void>(res => setTimeout(res, 1000));
- }
- }
- }
- function execTTY(command: string, options: IPtyForkOptions | IWindowsPtyForkOptions, stdout?: (...args: any[]) => void) {
- return new Promise<void>((resolve, reject) => {
- try {
- let stdoutbuf = '';
- // SPAWN PTY PROCESS
- const p = spawn(command.split(' ')[0], command.split(' ').slice(1), options);
- // PIPE STDOUT
- if (typeof stdout === 'function') {
- p.onData(chunk => {
- stdoutbuf += chunk;
- let i = -1;
- while ((i = stdoutbuf.indexOf('\n')) >= 0) {
- const line = stdoutbuf.substring(0, i);
- stdoutbuf = stdoutbuf.substring(i + 1);
- if (typeof stdout === 'function') {
- stdout(line);
- }
- }
- });
- p.onExit(() => resolve());
- }
- } catch (err) {
- reject(err);
- }
- });
- }
|