project files added
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
import * as memoize from 'memoizee';
|
||||
declare const _default: ((urlString: string) => string) & memoize.Memoized<(urlString: string) => string>;
|
||||
export default _default;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const memoize = require("memoizee");
|
||||
const url_1 = require("url");
|
||||
const extractURLDomain = (urlString) => {
|
||||
const url = url_1.parse(urlString);
|
||||
if (url.protocol == 'https:' || url.protocol == 'http:') {
|
||||
return url.hostname;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
// memoize it for performance
|
||||
exports.default = memoize(extractURLDomain, { max: 100 });
|
||||
//# sourceMappingURL=extractURLDomain.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"extractURLDomain.js","sourceRoot":"","sources":["../src/extractURLDomain.ts"],"names":[],"mappings":";;AAAA,oCAAoC;AACpC,6BAA4B;AAE5B,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAU,EAAE;IACrD,MAAM,GAAG,GAAG,WAAK,CAAC,SAAS,CAAC,CAAC;IAE7B,IAAI,GAAG,CAAC,QAAQ,IAAI,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,OAAO,EAAE;QACvD,OAAO,GAAG,CAAC,QAAQ,CAAC;KACrB;IAED,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,6BAA6B;AAC7B,kBAAe,OAAO,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC"}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { Observable } from 'rxjs';
|
||||
export interface onProcessMetricsOptions {
|
||||
/** in ms */
|
||||
samplingInterval?: number;
|
||||
}
|
||||
export interface PidUsage {
|
||||
cpu: number;
|
||||
memory: number;
|
||||
pid: number;
|
||||
ppid: number;
|
||||
ctime: number;
|
||||
elapsed: number;
|
||||
timestamp: number;
|
||||
}
|
||||
export declare const getAppUsage: (pid: number) => Promise<PidUsage[]>;
|
||||
/**
|
||||
* Returns an Observable that emits Electron.ProcessMetric[] on a regular interval.
|
||||
*
|
||||
* For a given `app` and a given `samplingInterval`, the returned observable is shared
|
||||
* for performance reasons.
|
||||
*
|
||||
* options.samplingInterval = 1000 (1s) by default
|
||||
* @param app
|
||||
* @param options
|
||||
*/
|
||||
export declare const onProcessMetrics: (app: Electron.App, options: onProcessMetricsOptions) => Observable<Electron.ProcessMetric[]>;
|
||||
/**
|
||||
* Returns an Rx.Observable that emits `PidUsage[]` every `options.samplingInterval` ms.
|
||||
*
|
||||
* For a given `pid` and a given `samplingInterval`, the returned observable is shared
|
||||
* for performance reasons.
|
||||
* `pid` is the root of the process tree.
|
||||
*
|
||||
* @param pid
|
||||
* @param {object} options
|
||||
* @param {number} options.samplingInterval - 1000 (1s) by default
|
||||
*
|
||||
* @example
|
||||
* - pid: main process
|
||||
* - rendererPid1: renderer process
|
||||
* - rendererPid2: renderer process
|
||||
*/
|
||||
export declare const onProcessTreeMetricsForPid: (pid: number, options: onProcessMetricsOptions) => Observable<PidUsage[]>;
|
||||
export interface ExtendedProcessMetric extends Electron.ProcessMetric {
|
||||
webContents?: {
|
||||
type: string;
|
||||
id: number;
|
||||
pid: number;
|
||||
URL: string;
|
||||
URLDomain: string;
|
||||
}[];
|
||||
}
|
||||
/**
|
||||
* Returns an Rx.Observable that emits reports of `ExtendedProcessMetric`
|
||||
* every `options.samplingInterval` ms.
|
||||
*
|
||||
* Default `options.samplingInterval` = 1000ms
|
||||
*
|
||||
* Compared to `onProcessMetrics` it adds data on the `webContents` associated
|
||||
* to the given process.
|
||||
*
|
||||
* @param app the electron app instance
|
||||
* @param options
|
||||
*/
|
||||
export declare const onExtendedProcessMetrics: (app: Electron.App, options?: onProcessMetricsOptions) => Observable<ExtendedProcessMetric[]>;
|
||||
export interface onExcessiveCPUUsageOptions extends onProcessMetricsOptions {
|
||||
/**Number of samples to consider */
|
||||
samplesCount?: number;
|
||||
/**CPU usage percent minimum to consider a sample exceeds CPU usage */
|
||||
percentCPUUsageThreshold?: number;
|
||||
}
|
||||
/**
|
||||
* Will emit an array of `PidUsage` when a process of the tree exceeds the
|
||||
* `options.percentCPUUsageThreshold` on more than `options.samplesCount`
|
||||
* samples.
|
||||
* It monitors the whole tree of pids, starting from `childPid`.
|
||||
* The reason behind this is that the `process.pid` of the main process is at the same
|
||||
* level as all renderers.
|
||||
* So we fetch their common ancestor, which is the `ppid` of the main process.
|
||||
* The parent pid of `childPid` is not part of the end result
|
||||
* (that way, we monitor the same processes as `getAppMetrics`).
|
||||
*
|
||||
* In opposite to onExcessiveCPUUsage, onExcessiveCPUUsageInProcessTree does not use
|
||||
* Electron's internal measurement but rather use `pidusage`, a cross-platform
|
||||
* process cpu % and memory usage of a PID. It is known to have lower pressure on CPU.
|
||||
* Also, as this leverage `pidusage`, the measures on Windows can be considered
|
||||
* as not accurate.
|
||||
*
|
||||
* Default `options.samplesCount` = 10
|
||||
* Default `options.percentCPUUsageThreshold` = 80
|
||||
*
|
||||
* @param pid - the pid of the main process
|
||||
* @param options
|
||||
*/
|
||||
export declare const onExcessiveCPUUsageInProcessTree: (pid: number, options: onExcessiveCPUUsageOptions) => Observable<PidUsage[]>;
|
||||
/**
|
||||
* Will emit an array `ExtendedProcessMetric` when a process exceeds the
|
||||
* `options.percentCPUUsageThreshold` on more than `options.samplesCount`
|
||||
* samples.
|
||||
*
|
||||
* Default `options.samplesCount` = 10
|
||||
* Default `options.percentCPUUsageThreshold` = 80
|
||||
*
|
||||
* @param app the electron app instance
|
||||
* @param options
|
||||
*/
|
||||
export declare const onExcessiveCPUUsage: (app: Electron.App, options: onExcessiveCPUUsageOptions) => Observable<ExtendedProcessMetric[]>;
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const electron_1 = require("electron");
|
||||
const memoize = require("memoizee");
|
||||
// @ts-ignore: no declaration file
|
||||
const pidtree = require("pidtree");
|
||||
// @ts-ignore: no declaration file
|
||||
const pidusage = require("pidusage");
|
||||
const rxjs_1 = require("rxjs");
|
||||
const extractURLDomain_1 = require("./extractURLDomain");
|
||||
exports.getAppUsage = (pid) => {
|
||||
return pidtree(pid, { root: true })
|
||||
.then(pidusage)
|
||||
.then((usages) => Object.values(usages).filter(Boolean));
|
||||
};
|
||||
let getSharedProcessMetricsPollerByPid = (pid, samplingInterval) => rxjs_1.Observable.timer(0, samplingInterval)
|
||||
.map(() => rxjs_1.Observable.fromPromise(exports.getAppUsage(pid)))
|
||||
.mergeAll()
|
||||
.share();
|
||||
getSharedProcessMetricsPollerByPid = memoize(getSharedProcessMetricsPollerByPid);
|
||||
let getSharedProcessMetricsPollerByApp = (app, samplingInterval) => rxjs_1.Observable.timer(0, samplingInterval)
|
||||
.map(() => app.getAppMetrics())
|
||||
.share();
|
||||
getSharedProcessMetricsPollerByApp = memoize(getSharedProcessMetricsPollerByApp);
|
||||
/**
|
||||
* Returns an Observable that emits Electron.ProcessMetric[] on a regular interval.
|
||||
*
|
||||
* For a given `app` and a given `samplingInterval`, the returned observable is shared
|
||||
* for performance reasons.
|
||||
*
|
||||
* options.samplingInterval = 1000 (1s) by default
|
||||
* @param app
|
||||
* @param options
|
||||
*/
|
||||
exports.onProcessMetrics = (app, options) => {
|
||||
options = Object.assign({ samplingInterval: 1000 }, options);
|
||||
return getSharedProcessMetricsPollerByApp(app, options.samplingInterval);
|
||||
};
|
||||
/**
|
||||
* Returns an Rx.Observable that emits `PidUsage[]` every `options.samplingInterval` ms.
|
||||
*
|
||||
* For a given `pid` and a given `samplingInterval`, the returned observable is shared
|
||||
* for performance reasons.
|
||||
* `pid` is the root of the process tree.
|
||||
*
|
||||
* @param pid
|
||||
* @param {object} options
|
||||
* @param {number} options.samplingInterval - 1000 (1s) by default
|
||||
*
|
||||
* @example
|
||||
* - pid: main process
|
||||
* - rendererPid1: renderer process
|
||||
* - rendererPid2: renderer process
|
||||
*/
|
||||
exports.onProcessTreeMetricsForPid = (pid, options) => {
|
||||
options = Object.assign({ samplingInterval: 1000 }, options);
|
||||
return getSharedProcessMetricsPollerByPid(pid, options.samplingInterval);
|
||||
};
|
||||
const getExtendedAppMetrics = (appMetrics) => {
|
||||
const allWebContents = electron_1.webContents.getAllWebContents();
|
||||
const webContentsInfo = allWebContents.map((wc) => ({
|
||||
type: wc.getType(),
|
||||
id: wc.id,
|
||||
pid: wc.getOSProcessId(),
|
||||
URL: wc.getURL(),
|
||||
URLDomain: extractURLDomain_1.default(wc.getURL()),
|
||||
}));
|
||||
return appMetrics.map(proc => {
|
||||
const report = proc;
|
||||
const wc = webContentsInfo.find(wc => wc.pid === proc.pid);
|
||||
if (!wc)
|
||||
return report;
|
||||
report.webContents = [wc];
|
||||
return report;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Returns an Rx.Observable that emits reports of `ExtendedProcessMetric`
|
||||
* every `options.samplingInterval` ms.
|
||||
*
|
||||
* Default `options.samplingInterval` = 1000ms
|
||||
*
|
||||
* Compared to `onProcessMetrics` it adds data on the `webContents` associated
|
||||
* to the given process.
|
||||
*
|
||||
* @param app the electron app instance
|
||||
* @param options
|
||||
*/
|
||||
exports.onExtendedProcessMetrics = (app, options = {}) => exports.onProcessMetrics(app, options).map(getExtendedAppMetrics);
|
||||
/**
|
||||
* Will emit an array of `PidUsage` when a process of the tree exceeds the
|
||||
* `options.percentCPUUsageThreshold` on more than `options.samplesCount`
|
||||
* samples.
|
||||
* It monitors the whole tree of pids, starting from `childPid`.
|
||||
* The reason behind this is that the `process.pid` of the main process is at the same
|
||||
* level as all renderers.
|
||||
* So we fetch their common ancestor, which is the `ppid` of the main process.
|
||||
* The parent pid of `childPid` is not part of the end result
|
||||
* (that way, we monitor the same processes as `getAppMetrics`).
|
||||
*
|
||||
* In opposite to onExcessiveCPUUsage, onExcessiveCPUUsageInProcessTree does not use
|
||||
* Electron's internal measurement but rather use `pidusage`, a cross-platform
|
||||
* process cpu % and memory usage of a PID. It is known to have lower pressure on CPU.
|
||||
* Also, as this leverage `pidusage`, the measures on Windows can be considered
|
||||
* as not accurate.
|
||||
*
|
||||
* Default `options.samplesCount` = 10
|
||||
* Default `options.percentCPUUsageThreshold` = 80
|
||||
*
|
||||
* @param pid - the pid of the main process
|
||||
* @param options
|
||||
*/
|
||||
exports.onExcessiveCPUUsageInProcessTree = (pid, options) => {
|
||||
options = Object.assign({ samplesCount: 10, percentCPUUsageThreshold: 80 }, options);
|
||||
return exports.onProcessTreeMetricsForPid(pid, options)
|
||||
.map(appUsage => rxjs_1.Observable.from(appUsage))
|
||||
.mergeAll()
|
||||
.groupBy(appUsage => appUsage.pid)
|
||||
.map(g => g.bufferCount(options.samplesCount))
|
||||
.mergeAll()
|
||||
.filter(processMetricsSamples => {
|
||||
const excessiveSamplesCount = processMetricsSamples.filter(p => p.cpu >= options.percentCPUUsageThreshold).length;
|
||||
return excessiveSamplesCount === processMetricsSamples.length;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Will emit an array `ExtendedProcessMetric` when a process exceeds the
|
||||
* `options.percentCPUUsageThreshold` on more than `options.samplesCount`
|
||||
* samples.
|
||||
*
|
||||
* Default `options.samplesCount` = 10
|
||||
* Default `options.percentCPUUsageThreshold` = 80
|
||||
*
|
||||
* @param app the electron app instance
|
||||
* @param options
|
||||
*/
|
||||
exports.onExcessiveCPUUsage = (app, options) => {
|
||||
options = Object.assign({ samplesCount: 10, percentCPUUsageThreshold: 80 }, options);
|
||||
return exports.onExtendedProcessMetrics(app, options)
|
||||
.map(report => rxjs_1.Observable.from(report))
|
||||
.mergeAll()
|
||||
.groupBy(processMetric => processMetric.pid)
|
||||
.map(g => g.bufferCount(options.samplesCount))
|
||||
.mergeAll()
|
||||
.filter(processMetricsSamples => {
|
||||
const excessiveSamplesCount = processMetricsSamples.filter(p => p.cpu.percentCPUUsage >= options.percentCPUUsageThreshold).length;
|
||||
return excessiveSamplesCount == processMetricsSamples.length;
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,uCAAuC;AACvC,oCAAoC;AACpC,kCAAkC;AAClC,mCAAmC;AACnC,kCAAkC;AAClC,qCAAqC;AACrC,+BAAkC;AAElC,yDAAkD;AAsBrC,QAAA,WAAW,GAAG,CAAC,GAAW,EAAuB,EAAE;IAC9D,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAChC,IAAI,CAAC,QAAQ,CAAC;SACd,IAAI,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAe,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF,IAAI,kCAAkC,GAAG,CAAC,GAAW,EAAE,gBAAwB,EAAE,EAAE,CACjF,iBAAU,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC;KAClC,GAAG,CAAC,GAAG,EAAE,CAAC,iBAAU,CAAC,WAAW,CAAC,mBAAW,CAAC,GAAG,CAAC,CAAC,CAAC;KACnD,QAAQ,EAAE;KACV,KAAK,EAAE,CAAC;AAEb,kCAAkC,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;AAEjF,IAAI,kCAAkC,GAAG,CAAC,GAAiB,EAAE,gBAAwB,EAAE,EAAE,CACvF,iBAAU,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC;KAClC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;KAC9B,KAAK,EAAE,CAAC;AAEb,kCAAkC,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;AAEjF;;;;;;;;;GASG;AACU,QAAA,gBAAgB,GAAG,CAC9B,GAAiB,EACjB,OAAgC,EACM,EAAE;IACxC,OAAO,mBAAK,gBAAgB,EAAE,IAAI,IAAK,OAAO,CAAE,CAAC;IACjD,OAAO,kCAAkC,CAAC,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACU,QAAA,0BAA0B,GAAG,CACxC,GAAW,EACX,OAAgC,EACR,EAAE;IAC1B,OAAO,mBAAK,gBAAgB,EAAE,IAAI,IAAK,OAAO,CAAE,CAAC;IACjD,OAAO,kCAAkC,CAAC,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC3E,CAAC,CAAC;AAYF,MAAM,qBAAqB,GAAG,CAAC,UAAoC,EAAE,EAAE;IACrE,MAAM,cAAc,GAAG,sBAAW,CAAC,iBAAiB,EAAE,CAAC;IACvD,MAAM,eAAe,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,EAAwB,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE;QAClB,EAAE,EAAE,EAAE,CAAC,EAAE;QACT,GAAG,EAAE,EAAE,CAAC,cAAc,EAAE;QACxB,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE;QAChB,SAAS,EAAE,0BAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;KACzC,CAAC,CAAC,CAAC;IAEJ,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC3B,MAAM,MAAM,GAA0B,IAAI,CAAC;QAE3C,MAAM,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAEvB,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC,CAAC;QAE1B,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACU,QAAA,wBAAwB,GAAG,CAAC,GAAiB,EAAE,UAAmC,EAAE,EAAE,EAAE,CACnG,wBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;AAS5D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACU,QAAA,gCAAgC,GAAG,CAAC,GAAW,EAAE,OAAmC,EAAE,EAAE;IACnG,OAAO,mBACL,YAAY,EAAE,EAAE,EAChB,wBAAwB,EAAE,EAAE,IACzB,OAAO,CACX,CAAC;IAEF,OAAO,kCAA0B,CAAC,GAAG,EAAE,OAAO,CAAC;SAC5C,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,iBAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC1C,QAAQ,EAAE;SACV,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;SAC7C,QAAQ,EAAE;SACV,MAAM,CAAC,qBAAqB,CAAC,EAAE;QAC9B,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC,MAAM,CAAC;QAClH,OAAO,qBAAqB,KAAK,qBAAqB,CAAC,MAAM,CAAC;IAChE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,mBAAmB,GAAG,CAAC,GAAiB,EAAE,OAAmC,EAAE,EAAE;IAC5F,OAAO,mBACL,YAAY,EAAE,EAAE,EAChB,wBAAwB,EAAE,EAAE,IACzB,OAAO,CACX,CAAC;IAEF,OAAO,gCAAwB,CAAC,GAAG,EAAE,OAAO,CAAC;SAC1C,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,iBAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACtC,QAAQ,EAAE;SACV,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC;SAC3C,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;SAC7C,QAAQ,EAAE;SACV,MAAM,CAAC,qBAAqB,CAAC,EAAE;QAC9B,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,MAAM,CACxD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,wBAAwB,CAC/D,CAAC,MAAM,CAAC;QACT,OAAO,qBAAqB,IAAI,qBAAqB,CAAC,MAAM,CAAC;IAC/D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"}
|
||||
Reference in New Issue
Block a user