@crawlee/utils 3.12.3-beta.8 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +5 -1
- package/index.js.map +1 -1
- package/index.mjs +5 -0
- package/internals/general.d.ts +10 -0
- package/internals/general.d.ts.map +1 -1
- package/internals/general.js +60 -0
- package/internals/general.js.map +1 -1
- package/internals/systemInfoV2/cpu-info.d.ts +64 -0
- package/internals/systemInfoV2/cpu-info.d.ts.map +1 -0
- package/internals/systemInfoV2/cpu-info.js +221 -0
- package/internals/systemInfoV2/cpu-info.js.map +1 -0
- package/internals/systemInfoV2/memory-info.d.ts +28 -0
- package/internals/systemInfoV2/memory-info.d.ts.map +1 -0
- package/internals/systemInfoV2/memory-info.js +122 -0
- package/internals/systemInfoV2/memory-info.js.map +1 -0
- package/internals/systemInfoV2/ps-tree.d.ts +18 -0
- package/internals/systemInfoV2/ps-tree.d.ts.map +1 -0
- package/internals/systemInfoV2/ps-tree.js +149 -0
- package/internals/systemInfoV2/ps-tree.js.map +1 -0
- package/package.json +3 -3
- package/tsconfig.build.tsbuildinfo +1 -1
package/README.md
CHANGED
|
@@ -80,6 +80,28 @@ await crawler.run(['https://crawlee.dev']);
|
|
|
80
80
|
|
|
81
81
|
By default, Crawlee stores data to `./storage` in the current working directory. You can override this directory via Crawlee configuration. For details, see [Configuration guide](https://crawlee.dev/docs/guides/configuration), [Request storage](https://crawlee.dev/docs/guides/request-storage) and [Result storage](https://crawlee.dev/docs/guides/result-storage).
|
|
82
82
|
|
|
83
|
+
### Installing pre-release versions
|
|
84
|
+
|
|
85
|
+
We provide automated beta builds for every merged code change in Crawlee. You can find them in the npm [list of releases](https://www.npmjs.com/package/crawlee?activeTab=versions). If you want to test new features or bug fixes before we release them, feel free to install a beta build like this:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm install crawlee@3.12.3-beta.13
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need to specify dependency overrides in your `package.json` file so that you don't end up with multiple versions of Crawlee installed:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"overrides": {
|
|
96
|
+
"apify": {
|
|
97
|
+
"@crawlee/core": "3.12.3-beta.13",
|
|
98
|
+
"@crawlee/types": "3.12.3-beta.13",
|
|
99
|
+
"@crawlee/utils": "3.12.3-beta.13"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
83
105
|
## 🛠 Features
|
|
84
106
|
|
|
85
107
|
- Single interface for **HTTP and headless browser** crawling
|
package/index.d.ts
CHANGED
|
@@ -12,5 +12,7 @@ export * from './internals/gotScraping';
|
|
|
12
12
|
export * from './internals/robots';
|
|
13
13
|
export * from './internals/sitemap';
|
|
14
14
|
export * from './internals/url';
|
|
15
|
+
export { getCurrentCpuTicksV2 } from './internals/systemInfoV2/cpu-info';
|
|
16
|
+
export { getMemoryInfoV2 } from './internals/systemInfoV2/memory-info';
|
|
15
17
|
export { Dictionary, Awaitable, Constructor } from '@crawlee/types';
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.social = void 0;
|
|
3
|
+
exports.getMemoryInfoV2 = exports.getCurrentCpuTicksV2 = exports.social = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
tslib_1.__exportStar(require("./internals/blocked"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./internals/cheerio"), exports);
|
|
@@ -16,4 +16,8 @@ tslib_1.__exportStar(require("./internals/gotScraping"), exports);
|
|
|
16
16
|
tslib_1.__exportStar(require("./internals/robots"), exports);
|
|
17
17
|
tslib_1.__exportStar(require("./internals/sitemap"), exports);
|
|
18
18
|
tslib_1.__exportStar(require("./internals/url"), exports);
|
|
19
|
+
var cpu_info_1 = require("./internals/systemInfoV2/cpu-info");
|
|
20
|
+
Object.defineProperty(exports, "getCurrentCpuTicksV2", { enumerable: true, get: function () { return cpu_info_1.getCurrentCpuTicksV2; } });
|
|
21
|
+
var memory_info_1 = require("./internals/systemInfoV2/memory-info");
|
|
22
|
+
Object.defineProperty(exports, "getMemoryInfoV2", { enumerable: true, get: function () { return memory_info_1.getMemoryInfoV2; } });
|
|
19
23
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,8DAAoC;AACpC,8DAAoC;AACpC,4DAAkC;AAClC,mEAAyC;AACzC,8DAAoC;AACpC,kEAAwC;AACxC,4DAAkC;AAClC,qEAA6C;AAC7C,+DAAqC;AACrC,wEAA8C;AAC9C,kEAAwC;AACxC,6DAAmC;AACnC,8DAAoC;AACpC,0DAAgC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,8DAAoC;AACpC,8DAAoC;AACpC,4DAAkC;AAClC,mEAAyC;AACzC,8DAAoC;AACpC,kEAAwC;AACxC,4DAAkC;AAClC,qEAA6C;AAC7C,+DAAqC;AACrC,wEAA8C;AAC9C,kEAAwC;AACxC,6DAAmC;AACnC,8DAAoC;AACpC,0DAAgC;AAEhC,8DAAyE;AAAhE,gHAAA,oBAAoB,OAAA;AAC7B,oEAAuE;AAA9D,8GAAA,eAAe,OAAA"}
|
package/index.mjs
CHANGED
|
@@ -16,10 +16,15 @@ export const entries = mod.entries;
|
|
|
16
16
|
export const expandShadowRoots = mod.expandShadowRoots;
|
|
17
17
|
export const extractUrls = mod.extractUrls;
|
|
18
18
|
export const extractUrlsFromCheerio = mod.extractUrlsFromCheerio;
|
|
19
|
+
export const getCgroupsVersion = mod.getCgroupsVersion;
|
|
20
|
+
export const getCurrentCpuTicksV2 = mod.getCurrentCpuTicksV2;
|
|
19
21
|
export const getMemoryInfo = mod.getMemoryInfo;
|
|
22
|
+
export const getMemoryInfoV2 = mod.getMemoryInfoV2;
|
|
20
23
|
export const gotScraping = mod.gotScraping;
|
|
21
24
|
export const htmlToText = mod.htmlToText;
|
|
25
|
+
export const isContainerized = mod.isContainerized;
|
|
22
26
|
export const isDocker = mod.isDocker;
|
|
27
|
+
export const isLambda = mod.isLambda;
|
|
23
28
|
export const keys = mod.keys;
|
|
24
29
|
export const parseOpenGraph = mod.parseOpenGraph;
|
|
25
30
|
export const parseSitemap = mod.parseSitemap;
|
package/internals/general.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ export declare const URL_WITH_COMMAS_REGEX: RegExp;
|
|
|
12
12
|
* Returns a `Promise` that resolves to true if the code is running in a Docker container.
|
|
13
13
|
*/
|
|
14
14
|
export declare function isDocker(forceReset?: boolean): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Detects if crawlee is running in a containerized environment.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isContainerized(): Promise<boolean>;
|
|
19
|
+
export declare function isLambda(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* gets the cgroup version by checking for a file at /sys/fs/cgroup/memory
|
|
22
|
+
* @returns "V1" or "V2" for the version of cgroup or null if cgroup is not found.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getCgroupsVersion(forceReset?: boolean): Promise<"V1" | "V2" | null>;
|
|
15
25
|
/**
|
|
16
26
|
* Computes a weighted average of an array of numbers, complemented by an array of weights.
|
|
17
27
|
* @ignore
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../src/internals/general.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAC+G,CAAC;AAEhJ;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAC8G,CAAC;AAoBjJ;;GAEG;AACH,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAKrE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAW7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA8B5D"}
|
|
1
|
+
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../src/internals/general.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAC+G,CAAC;AAEhJ;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAC8G,CAAC;AAoBjJ;;GAEG;AACH,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAKrE;AAID;;GAEG;AACH,wBAAsB,eAAe,qBA0BpC;AAED,wBAAgB,QAAQ,YAEvB;AAGD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,OAAO,+BAoB3D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAW7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA8B5D"}
|
package/internals/general.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.URL_WITH_COMMAS_REGEX = exports.URL_NO_COMMAS_REGEX = void 0;
|
|
4
4
|
exports.isDocker = isDocker;
|
|
5
|
+
exports.isContainerized = isContainerized;
|
|
6
|
+
exports.isLambda = isLambda;
|
|
7
|
+
exports.getCgroupsVersion = getCgroupsVersion;
|
|
5
8
|
exports.weightedAvg = weightedAvg;
|
|
6
9
|
exports.sleep = sleep;
|
|
7
10
|
exports.snakeCaseToCamelCase = snakeCaseToCamelCase;
|
|
@@ -41,6 +44,63 @@ async function isDocker(forceReset) {
|
|
|
41
44
|
isDockerPromiseCache = createIsDockerPromise();
|
|
42
45
|
return isDockerPromiseCache;
|
|
43
46
|
}
|
|
47
|
+
let isContainerizedResult;
|
|
48
|
+
/**
|
|
49
|
+
* Detects if crawlee is running in a containerized environment.
|
|
50
|
+
*/
|
|
51
|
+
async function isContainerized() {
|
|
52
|
+
// Value is very unlikley to change. Cache the result after the first execution.
|
|
53
|
+
if (isContainerizedResult !== undefined) {
|
|
54
|
+
return isContainerizedResult;
|
|
55
|
+
}
|
|
56
|
+
// return false if running in aws lambda
|
|
57
|
+
if (isLambda()) {
|
|
58
|
+
isContainerizedResult = false;
|
|
59
|
+
return isContainerizedResult;
|
|
60
|
+
}
|
|
61
|
+
const dockerenvCheck = promises_1.default
|
|
62
|
+
.stat('/.dockerenv')
|
|
63
|
+
.then(() => true)
|
|
64
|
+
.catch(() => false);
|
|
65
|
+
const cgroupCheck = promises_1.default
|
|
66
|
+
.readFile('/proc/self/cgroup', 'utf8')
|
|
67
|
+
.then((content) => content.includes('docker'))
|
|
68
|
+
.catch(() => false);
|
|
69
|
+
const [dockerenvResult, cgroupResult] = await Promise.all([dockerenvCheck, cgroupCheck]);
|
|
70
|
+
isContainerizedResult = dockerenvResult || cgroupResult || !!process.env.KUBERNETES_SERVICE_HOST;
|
|
71
|
+
return isContainerizedResult;
|
|
72
|
+
}
|
|
73
|
+
function isLambda() {
|
|
74
|
+
return !!process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
75
|
+
}
|
|
76
|
+
let _cgroupsVersion;
|
|
77
|
+
/**
|
|
78
|
+
* gets the cgroup version by checking for a file at /sys/fs/cgroup/memory
|
|
79
|
+
* @returns "V1" or "V2" for the version of cgroup or null if cgroup is not found.
|
|
80
|
+
*/
|
|
81
|
+
async function getCgroupsVersion(forceReset) {
|
|
82
|
+
// Parameter forceReset is just internal for unit tests.
|
|
83
|
+
if (_cgroupsVersion !== undefined && !forceReset) {
|
|
84
|
+
return _cgroupsVersion;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// If this directory does not exists, cgroups are not available
|
|
88
|
+
await promises_1.default.access('/sys/fs/cgroup/');
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
_cgroupsVersion = null;
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
_cgroupsVersion = 'V1';
|
|
95
|
+
try {
|
|
96
|
+
// If this directory does not exists, assume the container is using cgroups V2
|
|
97
|
+
await promises_1.default.access('/sys/fs/cgroup/memory/');
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
_cgroupsVersion = 'V2';
|
|
101
|
+
}
|
|
102
|
+
return _cgroupsVersion;
|
|
103
|
+
}
|
|
44
104
|
/**
|
|
45
105
|
* Computes a weighted average of an array of numbers, complemented by an array of weights.
|
|
46
106
|
* @ignore
|
package/internals/general.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general.js","sourceRoot":"","sources":["../../src/internals/general.ts"],"names":[],"mappings":";;;AAsCA,4BAKC;AAMD,kCAWC;AAkBD,sBAEC;AAMD,oDAQC;AAMD,8CA8BC;;
|
|
1
|
+
{"version":3,"file":"general.js","sourceRoot":"","sources":["../../src/internals/general.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets the "bare metal" cpu load.
|
|
3
|
+
* Used in
|
|
4
|
+
* - AWS Lambda
|
|
5
|
+
* - Containers without a cGroup quota
|
|
6
|
+
* - Uncontainerized environments
|
|
7
|
+
* @returns a number between 0 and 1 for the cpu load
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCurrentCpuTicks(): number;
|
|
11
|
+
/**
|
|
12
|
+
* Reads the cgroup cpu quota.
|
|
13
|
+
* In V1, a quota of -1 means “unlimited.”
|
|
14
|
+
* In V2, a first field of "max" means unlimited.
|
|
15
|
+
* @param cgroupsVersion the cGroup version
|
|
16
|
+
* @returns The Cpu Quota
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCpuQuota(cgroupsVersion: string): Promise<number | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Reads the cgroup cpu period.
|
|
22
|
+
* @param cgroupsVersion the cGroup version
|
|
23
|
+
* @returns The Cpu quota period
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function getCpuPeriod(cgroupsVersion: string): Promise<number>;
|
|
27
|
+
/**
|
|
28
|
+
* Reads the cgroup cpu usage of the container
|
|
29
|
+
*
|
|
30
|
+
* @param cgroupsVersion the cGroup version
|
|
31
|
+
* @returns the cpu usage
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare function getContainerCpuUsage(cgroupsVersion: string): Promise<number>;
|
|
35
|
+
/**
|
|
36
|
+
* Reads the cgroup cpu usage of the system from cgroup
|
|
37
|
+
*
|
|
38
|
+
* @returns the cpu usage
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export declare function getSystemCpuUsage(): Promise<number>;
|
|
42
|
+
/**
|
|
43
|
+
* a cpu sample with the container usage and system usage
|
|
44
|
+
*/
|
|
45
|
+
export interface CpuSample {
|
|
46
|
+
containerUsage: number;
|
|
47
|
+
systemUsage: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Takes a CPU usage sample for both the container and the system.
|
|
51
|
+
*
|
|
52
|
+
* @returns An object containing the container and system CPU usage.
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
export declare function sampleCpuUsage(cGroupsVersion: string): Promise<CpuSample>;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the cpu usage of the system.
|
|
58
|
+
* If the crawler is running in a containerized environment, crawlee will check for a cgroup enforced cpu limit.
|
|
59
|
+
* If a cgroup limit is found, it will be taken as the maximum load against which the current load will be gauged.
|
|
60
|
+
* @returns a number between 0 and 1 for the cpu load
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare function getCurrentCpuTicksV2(containerized?: boolean): Promise<number>;
|
|
64
|
+
//# sourceMappingURL=cpu-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu-info.d.ts","sourceRoot":"","sources":["../../../src/internals/systemInfoV2/cpu-info.ts"],"names":[],"mappings":"AA6BA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,WAejC;AAgBD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAahF;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU1E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBlF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,oBAiBtC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAM/E;AAID;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CjF"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCurrentCpuTicks = getCurrentCpuTicks;
|
|
4
|
+
exports.getCpuQuota = getCpuQuota;
|
|
5
|
+
exports.getCpuPeriod = getCpuPeriod;
|
|
6
|
+
exports.getContainerCpuUsage = getContainerCpuUsage;
|
|
7
|
+
exports.getSystemCpuUsage = getSystemCpuUsage;
|
|
8
|
+
exports.sampleCpuUsage = sampleCpuUsage;
|
|
9
|
+
exports.getCurrentCpuTicksV2 = getCurrentCpuTicksV2;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const promises_1 = require("node:fs/promises");
|
|
13
|
+
const node_os_1 = tslib_1.__importDefault(require("node:os"));
|
|
14
|
+
const log_1 = tslib_1.__importDefault(require("@apify/log"));
|
|
15
|
+
const general_1 = require("../general");
|
|
16
|
+
const CPU_FILE_PATHS = {
|
|
17
|
+
STAT: {
|
|
18
|
+
V1: '/sys/fs/cgroup/cpuacct/cpuacct.usage',
|
|
19
|
+
V2: '/sys/fs/cgroup/cpu.stat',
|
|
20
|
+
},
|
|
21
|
+
QUOTA: {
|
|
22
|
+
V1: '/sys/fs/cgroup/cpu/cpu.cfs_quota_us',
|
|
23
|
+
V2: '/sys/fs/cgroup/cpu.max',
|
|
24
|
+
},
|
|
25
|
+
PERIOD: {
|
|
26
|
+
V1: '/sys/fs/cgroup/cpu/cpu.cfs_period_us',
|
|
27
|
+
V2: '/sys/fs/cgroup/cpu.max',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
let CLOCK_TICKS_PER_SECOND = 100;
|
|
31
|
+
let CLOCK_TICKS_CHECKED = false;
|
|
32
|
+
const NANOSECONDS_PER_SECOND = 1e9;
|
|
33
|
+
const previousTicks = { idle: 0, total: 0 };
|
|
34
|
+
/**
|
|
35
|
+
* Gets the "bare metal" cpu load.
|
|
36
|
+
* Used in
|
|
37
|
+
* - AWS Lambda
|
|
38
|
+
* - Containers without a cGroup quota
|
|
39
|
+
* - Uncontainerized environments
|
|
40
|
+
* @returns a number between 0 and 1 for the cpu load
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
function getCurrentCpuTicks() {
|
|
44
|
+
const cpusCores = node_os_1.default.cpus();
|
|
45
|
+
const ticks = cpusCores.reduce((acc, cpu) => {
|
|
46
|
+
const cpuTimes = Object.values(cpu.times);
|
|
47
|
+
return {
|
|
48
|
+
idle: acc.idle + cpu.times.idle,
|
|
49
|
+
total: acc.total + cpuTimes.reduce((sum, num) => sum + num),
|
|
50
|
+
};
|
|
51
|
+
}, { idle: 0, total: 0 });
|
|
52
|
+
const idleTicksDelta = ticks.idle - previousTicks.idle;
|
|
53
|
+
const totalTicksDelta = ticks.total - previousTicks.total;
|
|
54
|
+
return totalTicksDelta ? 1 - idleTicksDelta / totalTicksDelta : 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reads the linux tick rate
|
|
58
|
+
* @returns the number of ticks per second
|
|
59
|
+
*/
|
|
60
|
+
function getClockTicks() {
|
|
61
|
+
try {
|
|
62
|
+
const result = (0, node_child_process_1.execSync)('getconf CLK_TCK').toString().trim();
|
|
63
|
+
return parseInt(result, 10);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
log_1.default.warningOnce('Failed to get clock ticks; defaulting to 100');
|
|
67
|
+
return 100;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Reads the cgroup cpu quota.
|
|
72
|
+
* In V1, a quota of -1 means “unlimited.”
|
|
73
|
+
* In V2, a first field of "max" means unlimited.
|
|
74
|
+
* @param cgroupsVersion the cGroup version
|
|
75
|
+
* @returns The Cpu Quota
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
async function getCpuQuota(cgroupsVersion) {
|
|
79
|
+
if (cgroupsVersion === 'V1') {
|
|
80
|
+
const quotaStr = await (0, promises_1.readFile)(CPU_FILE_PATHS.QUOTA.V1, 'utf8');
|
|
81
|
+
const quota = parseInt(quotaStr.trim(), 10);
|
|
82
|
+
return quota === -1 ? null : quota;
|
|
83
|
+
}
|
|
84
|
+
// cgroup v2
|
|
85
|
+
const maxStr = await (0, promises_1.readFile)(CPU_FILE_PATHS.QUOTA.V2, 'utf8');
|
|
86
|
+
const parts = maxStr.trim().split(/\s+/);
|
|
87
|
+
if (parts[0] === 'max') {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return parseInt(parts[0], 10);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Reads the cgroup cpu period.
|
|
94
|
+
* @param cgroupsVersion the cGroup version
|
|
95
|
+
* @returns The Cpu quota period
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
async function getCpuPeriod(cgroupsVersion) {
|
|
99
|
+
if (cgroupsVersion === 'V1') {
|
|
100
|
+
const quotaStr = await (0, promises_1.readFile)(CPU_FILE_PATHS.PERIOD.V1, 'utf8');
|
|
101
|
+
const quota = parseInt(quotaStr.trim(), 10);
|
|
102
|
+
return quota;
|
|
103
|
+
}
|
|
104
|
+
// cgroup v2
|
|
105
|
+
const maxStr = await (0, promises_1.readFile)(CPU_FILE_PATHS.PERIOD.V2, 'utf8');
|
|
106
|
+
const parts = maxStr.trim().split(/\s+/);
|
|
107
|
+
return parseInt(parts[1], 10);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Reads the cgroup cpu usage of the container
|
|
111
|
+
*
|
|
112
|
+
* @param cgroupsVersion the cGroup version
|
|
113
|
+
* @returns the cpu usage
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
async function getContainerCpuUsage(cgroupsVersion) {
|
|
117
|
+
if (cgroupsVersion === 'V1') {
|
|
118
|
+
const data = await (0, promises_1.readFile)(CPU_FILE_PATHS.STAT.V1, 'utf8');
|
|
119
|
+
return Number(data.trim());
|
|
120
|
+
}
|
|
121
|
+
// cgroup v2
|
|
122
|
+
const data = await (0, promises_1.readFile)(CPU_FILE_PATHS.STAT.V2, 'utf8');
|
|
123
|
+
const lines = data.split('\n');
|
|
124
|
+
let usageUsec = 0;
|
|
125
|
+
for (const line of lines) {
|
|
126
|
+
const parts = line.trim().split(/\s+/);
|
|
127
|
+
if (parts[0] === 'usage_usec') {
|
|
128
|
+
usageUsec = Number(parts[1]);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Convert microseconds to nanoseconds.
|
|
133
|
+
return usageUsec * 1000;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Reads the cgroup cpu usage of the system from cgroup
|
|
137
|
+
*
|
|
138
|
+
* @returns the cpu usage
|
|
139
|
+
* @internal
|
|
140
|
+
*/
|
|
141
|
+
async function getSystemCpuUsage() {
|
|
142
|
+
const statData = await (0, promises_1.readFile)('/proc/stat', 'utf8');
|
|
143
|
+
const lines = statData.split('\n');
|
|
144
|
+
for (const line of lines) {
|
|
145
|
+
if (line.startsWith('cpu ')) {
|
|
146
|
+
// Split the line and extract the first seven numeric fields:
|
|
147
|
+
// user, nice, system, idle, iowait, irq, softirq
|
|
148
|
+
const parts = line.split(/\s+/).slice(1, 8);
|
|
149
|
+
let totalTicks = 0;
|
|
150
|
+
for (const part of parts) {
|
|
151
|
+
totalTicks += Number(part);
|
|
152
|
+
}
|
|
153
|
+
// Convert clock ticks to nanoseconds.
|
|
154
|
+
return (totalTicks * NANOSECONDS_PER_SECOND) / CLOCK_TICKS_PER_SECOND;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
throw new Error('no cpu line'); // shouldnt ever happen
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Takes a CPU usage sample for both the container and the system.
|
|
161
|
+
*
|
|
162
|
+
* @returns An object containing the container and system CPU usage.
|
|
163
|
+
* @internal
|
|
164
|
+
*/
|
|
165
|
+
async function sampleCpuUsage(cGroupsVersion) {
|
|
166
|
+
const [containerUsage, systemUsage] = await Promise.all([
|
|
167
|
+
getContainerCpuUsage(cGroupsVersion),
|
|
168
|
+
getSystemCpuUsage(),
|
|
169
|
+
]);
|
|
170
|
+
return { containerUsage, systemUsage };
|
|
171
|
+
}
|
|
172
|
+
let previousSample = { containerUsage: 0, systemUsage: 0 };
|
|
173
|
+
/**
|
|
174
|
+
* Gets the cpu usage of the system.
|
|
175
|
+
* If the crawler is running in a containerized environment, crawlee will check for a cgroup enforced cpu limit.
|
|
176
|
+
* If a cgroup limit is found, it will be taken as the maximum load against which the current load will be gauged.
|
|
177
|
+
* @returns a number between 0 and 1 for the cpu load
|
|
178
|
+
* @internal
|
|
179
|
+
*/
|
|
180
|
+
async function getCurrentCpuTicksV2(containerized = false) {
|
|
181
|
+
try {
|
|
182
|
+
// if not containerized
|
|
183
|
+
if (!containerized) {
|
|
184
|
+
// bare metal cpu limit
|
|
185
|
+
return getCurrentCpuTicks();
|
|
186
|
+
}
|
|
187
|
+
if (!CLOCK_TICKS_CHECKED) {
|
|
188
|
+
CLOCK_TICKS_PER_SECOND = getClockTicks();
|
|
189
|
+
CLOCK_TICKS_CHECKED = true;
|
|
190
|
+
}
|
|
191
|
+
const cgroupsVersion = await (0, general_1.getCgroupsVersion)();
|
|
192
|
+
// if cgroup is not detected, return bare metal cpu limit
|
|
193
|
+
if (cgroupsVersion === null) {
|
|
194
|
+
log_1.default.deprecated('Your environment is containerized, but your system does not support cgroups.\n' +
|
|
195
|
+
"If you're running containers with limited cpu, cpu auto-scaling will not work properly.");
|
|
196
|
+
return getCurrentCpuTicks();
|
|
197
|
+
}
|
|
198
|
+
// cgroup aware cpu limit. If no limits are set, default to returning getCurrentCpuTicks.
|
|
199
|
+
const quota = await getCpuQuota(cgroupsVersion);
|
|
200
|
+
if (quota === null) {
|
|
201
|
+
// no cgroup limit, return host cpu load
|
|
202
|
+
return getCurrentCpuTicks();
|
|
203
|
+
}
|
|
204
|
+
const period = await getCpuPeriod(cgroupsVersion);
|
|
205
|
+
// eg. having a 200000us quots per 100000us means the cGroup can fully use 2 cores
|
|
206
|
+
const cpuAllowance = quota / period;
|
|
207
|
+
const sample = await sampleCpuUsage(cgroupsVersion);
|
|
208
|
+
const containerDelta = sample.containerUsage - previousSample.containerUsage;
|
|
209
|
+
const systemDelta = sample.systemUsage - previousSample.systemUsage;
|
|
210
|
+
previousSample = sample;
|
|
211
|
+
const numCpus = node_os_1.default.cpus().length;
|
|
212
|
+
// Calculate the CPU usage percentage.
|
|
213
|
+
return ((containerDelta / systemDelta) * numCpus) / cpuAllowance;
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
// if anything fails, default to bare metal metrics
|
|
217
|
+
log_1.default.exception(err, 'Cpu snapshot failed.');
|
|
218
|
+
return getCurrentCpuTicks();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=cpu-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu-info.js","sourceRoot":"","sources":["../../../src/internals/systemInfoV2/cpu-info.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describes memory usage of the process.
|
|
3
|
+
*/
|
|
4
|
+
export interface MemoryInfo {
|
|
5
|
+
/** Total memory available in the system or container */
|
|
6
|
+
totalBytes: number;
|
|
7
|
+
/** Amount of free memory in the system or container */
|
|
8
|
+
freeBytes: number;
|
|
9
|
+
/** Amount of memory used (= totalBytes - freeBytes) */
|
|
10
|
+
usedBytes: number;
|
|
11
|
+
/** Amount of memory used the current Node.js process */
|
|
12
|
+
mainProcessBytes: number;
|
|
13
|
+
/** Amount of memory used by child processes of the current Node.js process */
|
|
14
|
+
childProcessesBytes: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns memory statistics of the process and the system, see {@apilink MemoryInfo}.
|
|
18
|
+
*
|
|
19
|
+
* If the process runs inside of a container, the `getMemoryInfo` gets container memory limits,
|
|
20
|
+
* otherwise it gets system memory limits.
|
|
21
|
+
*
|
|
22
|
+
* Beware that the function is quite inefficient because it spawns a new process.
|
|
23
|
+
* Therefore you shouldn't call it too often, like more than once per second.
|
|
24
|
+
* @returns An object containing the free and used memory metrics.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function getMemoryInfoV2(containerized?: boolean): Promise<MemoryInfo>;
|
|
28
|
+
//# sourceMappingURL=memory-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-info.d.ts","sourceRoot":"","sources":["../../../src/internals/systemInfoV2/memory-info.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IAEnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAElB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAElB,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAC;IAEzB,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,aAAa,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAgGhF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMemoryInfoV2 = getMemoryInfoV2;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_child_process_1 = require("node:child_process");
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const node_os_1 = require("node:os");
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("@apify/log"));
|
|
9
|
+
const general_1 = require("../general");
|
|
10
|
+
const ps_tree_1 = require("./ps-tree");
|
|
11
|
+
const MEMORY_FILE_PATHS = {
|
|
12
|
+
TOTAL: {
|
|
13
|
+
V1: '/sys/fs/cgroup/memory/memory.limit_in_bytes',
|
|
14
|
+
V2: '/sys/fs/cgroup/memory.max',
|
|
15
|
+
},
|
|
16
|
+
USED: {
|
|
17
|
+
V1: '/sys/fs/cgroup/memory/memory.usage_in_bytes',
|
|
18
|
+
V2: '/sys/fs/cgroup/memory.current',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Returns memory statistics of the process and the system, see {@apilink MemoryInfo}.
|
|
23
|
+
*
|
|
24
|
+
* If the process runs inside of a container, the `getMemoryInfo` gets container memory limits,
|
|
25
|
+
* otherwise it gets system memory limits.
|
|
26
|
+
*
|
|
27
|
+
* Beware that the function is quite inefficient because it spawns a new process.
|
|
28
|
+
* Therefore you shouldn't call it too often, like more than once per second.
|
|
29
|
+
* @returns An object containing the free and used memory metrics.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
async function getMemoryInfoV2(containerized = false) {
|
|
33
|
+
let mainProcessBytes = -1;
|
|
34
|
+
let childProcessesBytes = 0;
|
|
35
|
+
// lambda does *not* have `ps` and other command line tools
|
|
36
|
+
// required to extract memory usage.
|
|
37
|
+
if ((0, general_1.isLambda)()) {
|
|
38
|
+
// reported in bytes
|
|
39
|
+
mainProcessBytes = process.memoryUsage().rss;
|
|
40
|
+
// https://stackoverflow.com/a/55914335/129415
|
|
41
|
+
const memInfo = (0, node_child_process_1.execSync)('cat /proc/meminfo').toString();
|
|
42
|
+
const values = memInfo.split(/[\n: ]/).filter((val) => val.trim());
|
|
43
|
+
// /proc/meminfo reports in kb, not bytes, the total used memory is reported by meminfo
|
|
44
|
+
// subtract memory used by the main node process in order to infer memory used by any child processes
|
|
45
|
+
childProcessesBytes = +values[19] * 1000 - mainProcessBytes;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Query both root and child processes
|
|
49
|
+
const processes = await (0, ps_tree_1.psTree)(process.pid, true);
|
|
50
|
+
processes.forEach((rec) => {
|
|
51
|
+
// Obtain main process' memory separately
|
|
52
|
+
if (rec.PID === `${process.pid}`) {
|
|
53
|
+
mainProcessBytes = rec.RSS;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
childProcessesBytes += rec.RSS;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
let totalBytes;
|
|
60
|
+
let usedBytes;
|
|
61
|
+
let freeBytes;
|
|
62
|
+
if ((0, general_1.isLambda)()) {
|
|
63
|
+
// memory size is defined in megabytes
|
|
64
|
+
totalBytes = parseInt(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE, 10) * 1000000;
|
|
65
|
+
usedBytes = mainProcessBytes + childProcessesBytes;
|
|
66
|
+
freeBytes = totalBytes - usedBytes;
|
|
67
|
+
log_1.default.debug(`lambda size of ${totalBytes} with ${freeBytes} free bytes`);
|
|
68
|
+
}
|
|
69
|
+
else if (containerized) {
|
|
70
|
+
// When running inside a container, use container memory limits
|
|
71
|
+
const cgroupsVersion = await (0, general_1.getCgroupsVersion)();
|
|
72
|
+
try {
|
|
73
|
+
if (cgroupsVersion === null) {
|
|
74
|
+
throw new Error('cgroup not available');
|
|
75
|
+
}
|
|
76
|
+
let [totalBytesStr, usedBytesStr] = await Promise.all([
|
|
77
|
+
(0, promises_1.readFile)(MEMORY_FILE_PATHS.TOTAL[cgroupsVersion], 'utf8'),
|
|
78
|
+
(0, promises_1.readFile)(MEMORY_FILE_PATHS.USED[cgroupsVersion], 'utf8'),
|
|
79
|
+
]);
|
|
80
|
+
// Cgroups V2 files contains newline character. Getting rid of it for better handling in later part of the code.
|
|
81
|
+
totalBytesStr = totalBytesStr.replace(/[^a-zA-Z0-9 ]/g, '');
|
|
82
|
+
usedBytesStr = usedBytesStr.replace(/[^a-zA-Z0-9 ]/g, '');
|
|
83
|
+
// Cgroups V2 contains 'max' string if memory is not limited
|
|
84
|
+
// See https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/tree/Documentation/admin-guide/cgroup-v2.rst (see "memory.max")
|
|
85
|
+
if (totalBytesStr === 'max') {
|
|
86
|
+
totalBytes = (0, node_os_1.totalmem)();
|
|
87
|
+
// Cgroups V1 is set to number related to platform and page size if memory is not limited
|
|
88
|
+
// See https://unix.stackexchange.com/q/420906
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
totalBytes = parseInt(totalBytesStr, 10);
|
|
92
|
+
const containerRunsWithUnlimitedMemory = totalBytes > Number.MAX_SAFE_INTEGER;
|
|
93
|
+
if (containerRunsWithUnlimitedMemory)
|
|
94
|
+
totalBytes = (0, node_os_1.totalmem)();
|
|
95
|
+
}
|
|
96
|
+
usedBytes = parseInt(usedBytesStr, 10);
|
|
97
|
+
freeBytes = totalBytes - usedBytes;
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
// log.deprecated logs a warning only once
|
|
101
|
+
log_1.default.deprecated('Your environment is containerized, but your system does not support memory cgroups. ' +
|
|
102
|
+
"If you're running containers with limited memory, memory auto-scaling will not work properly.\n\n" +
|
|
103
|
+
`Cause: ${err.message}`);
|
|
104
|
+
totalBytes = (0, node_os_1.totalmem)();
|
|
105
|
+
freeBytes = (0, node_os_1.freemem)();
|
|
106
|
+
usedBytes = totalBytes - freeBytes;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
totalBytes = (0, node_os_1.totalmem)();
|
|
111
|
+
freeBytes = (0, node_os_1.freemem)();
|
|
112
|
+
usedBytes = totalBytes - freeBytes;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
totalBytes,
|
|
116
|
+
freeBytes,
|
|
117
|
+
usedBytes,
|
|
118
|
+
mainProcessBytes,
|
|
119
|
+
childProcessesBytes,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=memory-info.js.map
|