@lakutata/monitor 3.0.0-beta.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.
Files changed (48) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +114 -0
  3. package/dist/cjs/exports/Monitor.d.ts +9 -0
  4. package/dist/cjs/exports/Monitor.js +28 -0
  5. package/dist/cjs/monitor/CpuMonitor.d.ts +60 -0
  6. package/dist/cjs/monitor/CpuMonitor.js +96 -0
  7. package/dist/cjs/monitor/EventLoopMonitor.d.ts +65 -0
  8. package/dist/cjs/monitor/EventLoopMonitor.js +92 -0
  9. package/dist/cjs/monitor/HttpRequestMonitor.d.ts +61 -0
  10. package/dist/cjs/monitor/HttpRequestMonitor.js +92 -0
  11. package/dist/cjs/monitor/MemoryMonitor.d.ts +61 -0
  12. package/dist/cjs/monitor/MemoryMonitor.js +152 -0
  13. package/dist/cjs/monitor/interfaces/ICpuMonitorStatistics.d.ts +40 -0
  14. package/dist/cjs/monitor/interfaces/ICpuMonitorStatistics.js +2 -0
  15. package/dist/cjs/monitor/interfaces/IEventLoopMonitorStatistics.d.ts +45 -0
  16. package/dist/cjs/monitor/interfaces/IEventLoopMonitorStatistics.js +2 -0
  17. package/dist/cjs/monitor/interfaces/IHttpRequestMonitorStatistics.d.ts +43 -0
  18. package/dist/cjs/monitor/interfaces/IHttpRequestMonitorStatistics.js +2 -0
  19. package/dist/cjs/monitor/interfaces/IMemoryMonitorStatistics.d.ts +124 -0
  20. package/dist/cjs/monitor/interfaces/IMemoryMonitorStatistics.js +2 -0
  21. package/dist/cjs/monitor/interfaces/IMonitor.d.ts +10 -0
  22. package/dist/cjs/monitor/interfaces/IMonitor.js +2 -0
  23. package/dist/cjs/monitor/lib/Samples.d.ts +57 -0
  24. package/dist/cjs/monitor/lib/Samples.js +119 -0
  25. package/dist/cjs/package.json +1 -0
  26. package/dist/esm/exports/Monitor.js +9 -0
  27. package/dist/esm/monitor/CpuMonitor.js +92 -0
  28. package/dist/esm/monitor/EventLoopMonitor.js +88 -0
  29. package/dist/esm/monitor/HttpRequestMonitor.js +88 -0
  30. package/dist/esm/monitor/MemoryMonitor.js +115 -0
  31. package/dist/esm/monitor/interfaces/ICpuMonitorStatistics.js +1 -0
  32. package/dist/esm/monitor/interfaces/IEventLoopMonitorStatistics.js +1 -0
  33. package/dist/esm/monitor/interfaces/IHttpRequestMonitorStatistics.js +1 -0
  34. package/dist/esm/monitor/interfaces/IMemoryMonitorStatistics.js +1 -0
  35. package/dist/esm/monitor/interfaces/IMonitor.js +1 -0
  36. package/dist/esm/monitor/lib/Samples.js +114 -0
  37. package/dist/types/exports/Monitor.d.ts +9 -0
  38. package/dist/types/monitor/CpuMonitor.d.ts +60 -0
  39. package/dist/types/monitor/EventLoopMonitor.d.ts +65 -0
  40. package/dist/types/monitor/HttpRequestMonitor.d.ts +61 -0
  41. package/dist/types/monitor/MemoryMonitor.d.ts +61 -0
  42. package/dist/types/monitor/interfaces/ICpuMonitorStatistics.d.ts +40 -0
  43. package/dist/types/monitor/interfaces/IEventLoopMonitorStatistics.d.ts +45 -0
  44. package/dist/types/monitor/interfaces/IHttpRequestMonitorStatistics.d.ts +43 -0
  45. package/dist/types/monitor/interfaces/IMemoryMonitorStatistics.d.ts +124 -0
  46. package/dist/types/monitor/interfaces/IMonitor.d.ts +10 -0
  47. package/dist/types/monitor/lib/Samples.d.ts +57 -0
  48. package/package.json +44 -0
@@ -0,0 +1,61 @@
1
+ import { Component } from '@lakutata/core';
2
+ import { IMonitor } from './interfaces/IMonitor.js';
3
+ import { IMemoryMonitorStatistics } from './interfaces/IMemoryMonitorStatistics.js';
4
+ /**
5
+ * The memory monitor: measures the memory of the process, in bytes, with `process.memoryUsage()`: its resident set
6
+ * (the physical memory it occupies, `rss`), its V8 heap (`heapTotal` reserved, `heapUsed` occupied by the JavaScript
7
+ * objects) and its external memory (the C++ objects bound to JavaScript ones, the `Buffer`s included). It takes a
8
+ * sample when it is created then every second, and keeps the statistics of every sample since it was created or last
9
+ * {@link MemoryMonitor.reset}: the minimum, the maximum, the mean and percentiles, in constant memory.
10
+ *
11
+ * Declare it in the `components` of the application (`{class: MemoryMonitor}`) and get it with `@Inject` or
12
+ * `getObject()`; it is a singleton. It starts sampling when it is created: list it in `bootstrap` to measure from the
13
+ * launch. Its timer does not keep the process alive, and stops when the component is destroyed.
14
+ * @example
15
+ * ```typescript
16
+ * import {Application} from 'lakutata'
17
+ * import {MemoryMonitor, type IMemoryMonitorStatistics} from 'lakutata/com/monitor'
18
+ *
19
+ * Application
20
+ * .run(() => ({
21
+ * id: 'memory.app',
22
+ * name: 'Memory',
23
+ * components: {
24
+ * memory: {class: MemoryMonitor}
25
+ * },
26
+ * bootstrap: ['memory']
27
+ * }))
28
+ * .onLaunched(async (app: Application): Promise<void> => {
29
+ * const memory: MemoryMonitor = await app.getObject('memory')
30
+ * setInterval((): void => {
31
+ * const statistics: IMemoryMonitorStatistics = memory.statistics
32
+ * const megabytes = (bytes: number): string => (bytes / 1048576).toFixed(1)
33
+ * console.log(`RSS ${megabytes(statistics.physicalUsed)} MB (${statistics.physicalUsage}% of the host), heap ${statistics.heapUsage}% used`)
34
+ * }, 60000)
35
+ * })
36
+ * ```
37
+ */
38
+ export declare class MemoryMonitor extends Component implements IMonitor<IMemoryMonitorStatistics> {
39
+ #private;
40
+ /**
41
+ * The memory statistics, computed at each read: the latest sample (`physicalUsed`, `heapTotal`, `heapUsed`,
42
+ * `externalUsed`, in bytes, and the percentages `physicalUsage` and `heapUsage`, rounded to 2 decimals), the host's
43
+ * total memory, and the minimum, maximum, mean (rounded to 2 decimals) and percentiles of the samples since the
44
+ * monitor was created or reset. The percentiles are approximate (3 significant digits). The statistics of the
45
+ * samples are 0 after a reset until the next sample.
46
+ */
47
+ get statistics(): IMemoryMonitorStatistics;
48
+ /**
49
+ * Take a sample of the memory of the process: it becomes the latest usage and is added to the statistics. Called
50
+ * when the monitor is created, then every second.
51
+ * @protected
52
+ */
53
+ protected sampleMemoryUsage(): void;
54
+ protected init(): Promise<void>;
55
+ protected destroy(): Promise<void>;
56
+ /**
57
+ * Forget the samples: the minimum, maximum, mean and percentiles are 0 until the next sample, then cover the samples
58
+ * taken since. The latest usage is kept.
59
+ */
60
+ reset(): void;
61
+ }
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MemoryMonitor = void 0;
37
+ const os = __importStar(require("node:os"));
38
+ const core_1 = require("@lakutata/core");
39
+ const Samples_js_1 = require("./lib/Samples.js");
40
+ /**
41
+ * The memory monitor: measures the memory of the process, in bytes, with `process.memoryUsage()`: its resident set
42
+ * (the physical memory it occupies, `rss`), its V8 heap (`heapTotal` reserved, `heapUsed` occupied by the JavaScript
43
+ * objects) and its external memory (the C++ objects bound to JavaScript ones, the `Buffer`s included). It takes a
44
+ * sample when it is created then every second, and keeps the statistics of every sample since it was created or last
45
+ * {@link MemoryMonitor.reset}: the minimum, the maximum, the mean and percentiles, in constant memory.
46
+ *
47
+ * Declare it in the `components` of the application (`{class: MemoryMonitor}`) and get it with `@Inject` or
48
+ * `getObject()`; it is a singleton. It starts sampling when it is created: list it in `bootstrap` to measure from the
49
+ * launch. Its timer does not keep the process alive, and stops when the component is destroyed.
50
+ * @example
51
+ * ```typescript
52
+ * import {Application} from 'lakutata'
53
+ * import {MemoryMonitor, type IMemoryMonitorStatistics} from 'lakutata/com/monitor'
54
+ *
55
+ * Application
56
+ * .run(() => ({
57
+ * id: 'memory.app',
58
+ * name: 'Memory',
59
+ * components: {
60
+ * memory: {class: MemoryMonitor}
61
+ * },
62
+ * bootstrap: ['memory']
63
+ * }))
64
+ * .onLaunched(async (app: Application): Promise<void> => {
65
+ * const memory: MemoryMonitor = await app.getObject('memory')
66
+ * setInterval((): void => {
67
+ * const statistics: IMemoryMonitorStatistics = memory.statistics
68
+ * const megabytes = (bytes: number): string => (bytes / 1048576).toFixed(1)
69
+ * console.log(`RSS ${megabytes(statistics.physicalUsed)} MB (${statistics.physicalUsage}% of the host), heap ${statistics.heapUsage}% used`)
70
+ * }, 60000)
71
+ * })
72
+ * ```
73
+ */
74
+ class MemoryMonitor extends core_1.Component {
75
+ #fractionDigits = 2;
76
+ #intervalDelay = 1000;
77
+ #totalMemorySize = os.totalmem();
78
+ #physical = new Samples_js_1.Samples();
79
+ #heap = new Samples_js_1.Samples();
80
+ #external = new Samples_js_1.Samples();
81
+ #latest = process.memoryUsage();
82
+ #sampleInterval;
83
+ /**
84
+ * The memory statistics, computed at each read: the latest sample (`physicalUsed`, `heapTotal`, `heapUsed`,
85
+ * `externalUsed`, in bytes, and the percentages `physicalUsage` and `heapUsage`, rounded to 2 decimals), the host's
86
+ * total memory, and the minimum, maximum, mean (rounded to 2 decimals) and percentiles of the samples since the
87
+ * monitor was created or reset. The percentiles are approximate (3 significant digits). The statistics of the
88
+ * samples are 0 after a reset until the next sample.
89
+ */
90
+ get statistics() {
91
+ const latest = this.#latest;
92
+ return {
93
+ physicalTotal: this.#totalMemorySize,
94
+ physicalUsed: latest.rss,
95
+ physicalUsage: (0, Samples_js_1.round)(latest.rss / this.#totalMemorySize * 100, this.#fractionDigits),
96
+ physicalUsedMin: this.#physical.min,
97
+ physicalUsedMax: this.#physical.max,
98
+ physicalUsedAvg: (0, Samples_js_1.round)(this.#physical.mean, this.#fractionDigits),
99
+ physicalUsedP50: this.#physical.percentile(50),
100
+ physicalUsedP90: this.#physical.percentile(90),
101
+ physicalUsedP95: this.#physical.percentile(95),
102
+ physicalUsedP99: this.#physical.percentile(99),
103
+ heapTotal: latest.heapTotal,
104
+ heapUsed: latest.heapUsed,
105
+ heapUsage: (0, Samples_js_1.round)(latest.heapTotal ? latest.heapUsed / latest.heapTotal * 100 : 0, this.#fractionDigits),
106
+ heapUsedMin: this.#heap.min,
107
+ heapUsedMax: this.#heap.max,
108
+ heapUsedAvg: (0, Samples_js_1.round)(this.#heap.mean, this.#fractionDigits),
109
+ heapUsedP50: this.#heap.percentile(50),
110
+ heapUsedP90: this.#heap.percentile(90),
111
+ heapUsedP95: this.#heap.percentile(95),
112
+ heapUsedP99: this.#heap.percentile(99),
113
+ externalUsed: latest.external,
114
+ externalUsedMin: this.#external.min,
115
+ externalUsedMax: this.#external.max,
116
+ externalUsedAvg: (0, Samples_js_1.round)(this.#external.mean, this.#fractionDigits),
117
+ externalUsedP50: this.#external.percentile(50),
118
+ externalUsedP90: this.#external.percentile(90),
119
+ externalUsedP95: this.#external.percentile(95),
120
+ externalUsedP99: this.#external.percentile(99)
121
+ };
122
+ }
123
+ /**
124
+ * Take a sample of the memory of the process: it becomes the latest usage and is added to the statistics. Called
125
+ * when the monitor is created, then every second.
126
+ * @protected
127
+ */
128
+ sampleMemoryUsage() {
129
+ const usage = process.memoryUsage();
130
+ this.#latest = usage;
131
+ this.#physical.record(usage.rss);
132
+ this.#heap.record(usage.heapUsed);
133
+ this.#external.record(usage.external);
134
+ }
135
+ async init() {
136
+ this.sampleMemoryUsage();
137
+ this.#sampleInterval = setInterval(() => this.sampleMemoryUsage(), this.#intervalDelay).unref();
138
+ }
139
+ async destroy() {
140
+ clearInterval(this.#sampleInterval);
141
+ }
142
+ /**
143
+ * Forget the samples: the minimum, maximum, mean and percentiles are 0 until the next sample, then cover the samples
144
+ * taken since. The latest usage is kept.
145
+ */
146
+ reset() {
147
+ this.#physical.reset();
148
+ this.#heap.reset();
149
+ this.#external.reset();
150
+ }
151
+ }
152
+ exports.MemoryMonitor = MemoryMonitor;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The statistics of a {@link CpuMonitor}: the CPU usage of the process in percent of one core (100 is one core fully
3
+ * busy; above 100 with several cores busy), each sample the average over one second, rounded to 5 decimals. The
4
+ * minimum, maximum, mean and percentiles cover the samples since the monitor was created or reset; the percentiles are
5
+ * approximate (3 significant digits). All 0 before the first sample.
6
+ */
7
+ export interface ICpuMonitorStatistics {
8
+ /**
9
+ * The CPU usage over the latest second (the latest sample), in percent of one core.
10
+ */
11
+ usage: number;
12
+ /**
13
+ * The lowest sample, in percent of one core.
14
+ */
15
+ usageMin: number;
16
+ /**
17
+ * The highest sample, in percent of one core.
18
+ */
19
+ usageMax: number;
20
+ /**
21
+ * The mean of the samples, in percent of one core.
22
+ */
23
+ usageAvg: number;
24
+ /**
25
+ * The median sample (50% of the seconds used less), in percent of one core.
26
+ */
27
+ usageP50: number;
28
+ /**
29
+ * The 90th percentile of the samples (90% of the seconds used less), in percent of one core.
30
+ */
31
+ usageP90: number;
32
+ /**
33
+ * The 95th percentile of the samples, in percent of one core.
34
+ */
35
+ usageP95: number;
36
+ /**
37
+ * The 99th percentile of the samples, in percent of one core.
38
+ */
39
+ usageP99: number;
40
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The statistics of an {@link EventLoopMonitor} since it was created or reset: the event loop delays, in milliseconds
3
+ * (measured by a timer due every millisecond: about 1 ms when the loop is idle, more while synchronous work blocks
4
+ * it; all 0 before the first measure), and the loop utilization, in percent. The percentiles
5
+ * come from Node's histogram.
6
+ */
7
+ export interface IEventLoopMonitorStatistics {
8
+ /**
9
+ * The shortest delay, in milliseconds.
10
+ */
11
+ min: number;
12
+ /**
13
+ * The longest delay, in milliseconds: the longest the loop was blocked.
14
+ */
15
+ max: number;
16
+ /**
17
+ * The mean delay, in milliseconds.
18
+ */
19
+ avg: number;
20
+ /**
21
+ * The standard deviation of the delays, in milliseconds.
22
+ */
23
+ stdDev: number;
24
+ /**
25
+ * The median delay, in milliseconds.
26
+ */
27
+ p50: number;
28
+ /**
29
+ * The 90th percentile of the delays (90% were shorter), in milliseconds.
30
+ */
31
+ p90: number;
32
+ /**
33
+ * The 95th percentile of the delays, in milliseconds.
34
+ */
35
+ p95: number;
36
+ /**
37
+ * The 99th percentile of the delays, in milliseconds: the usual pick for an alert.
38
+ */
39
+ p99: number;
40
+ /**
41
+ * The share of the time the event loop was busy running code rather than waiting for I/O, in percent (0 to
42
+ * 100), since the monitor was created or reset. Not rounded.
43
+ */
44
+ utilRate: number;
45
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The statistics of an {@link HttpRequestMonitor} since it was created or reset: the number of HTTP requests received
3
+ * and their durations, from their arrival to the end of their response, in milliseconds rounded to 2 decimals. The
4
+ * percentiles are approximate (3 significant digits). All 0 before the first request.
5
+ */
6
+ export interface IHttpRequestMonitorStatistics {
7
+ /**
8
+ * The number of requests received whose response ended.
9
+ */
10
+ count: number;
11
+ /**
12
+ * The shortest request, in milliseconds.
13
+ */
14
+ min: number;
15
+ /**
16
+ * The longest request, in milliseconds.
17
+ */
18
+ max: number;
19
+ /**
20
+ * The mean duration, in milliseconds.
21
+ */
22
+ avg: number;
23
+ /**
24
+ * The standard deviation of the durations, in milliseconds.
25
+ */
26
+ stdDev: number;
27
+ /**
28
+ * The median duration, in milliseconds.
29
+ */
30
+ p50: number;
31
+ /**
32
+ * The 90th percentile of the durations (90% of the requests were faster), in milliseconds.
33
+ */
34
+ p90: number;
35
+ /**
36
+ * The 95th percentile of the durations, in milliseconds.
37
+ */
38
+ p95: number;
39
+ /**
40
+ * The 99th percentile of the durations, in milliseconds.
41
+ */
42
+ p99: number;
43
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,124 @@
1
+ /**
2
+ * The statistics of a {@link MemoryMonitor}, in bytes unless stated: the latest sample of the process memory
3
+ * (`process.memoryUsage()`), and the minimum, maximum, mean and percentiles of the samples taken every second since
4
+ * the monitor was created or reset (0 after a reset until the next sample). The percentiles are approximate (3
5
+ * significant digits).
6
+ */
7
+ export interface IMemoryMonitorStatistics {
8
+ /**
9
+ * The total physical memory of the host (`os.totalmem()`), in bytes; under a container, the host's,
10
+ * not the container's limit.
11
+ */
12
+ physicalTotal: number;
13
+ /**
14
+ * The resident set size of the process (`rss`) at the latest sample: the physical memory it occupies, in
15
+ * bytes.
16
+ */
17
+ physicalUsed: number;
18
+ /**
19
+ * `physicalUsed` as a percentage of `physicalTotal`, rounded to 2 decimals.
20
+ */
21
+ physicalUsage: number;
22
+ /**
23
+ * The lowest resident set size sampled, in bytes.
24
+ */
25
+ physicalUsedMin: number;
26
+ /**
27
+ * The highest resident set size sampled, in bytes.
28
+ */
29
+ physicalUsedMax: number;
30
+ /**
31
+ * The mean resident set size of the samples, in bytes, rounded to 2 decimals.
32
+ */
33
+ physicalUsedAvg: number;
34
+ /**
35
+ * The median resident set size of the samples, in bytes.
36
+ */
37
+ physicalUsedP50: number;
38
+ /**
39
+ * The 90th percentile of the resident set size samples, in bytes.
40
+ */
41
+ physicalUsedP90: number;
42
+ /**
43
+ * The 95th percentile of the resident set size samples, in bytes.
44
+ */
45
+ physicalUsedP95: number;
46
+ /**
47
+ * The 99th percentile of the resident set size samples, in bytes.
48
+ */
49
+ physicalUsedP99: number;
50
+ /**
51
+ * The size of the V8 heap reserved by the process at the latest sample, in bytes.
52
+ */
53
+ heapTotal: number;
54
+ /**
55
+ * The part of the V8 heap occupied by JavaScript objects at the latest sample, in bytes.
56
+ */
57
+ heapUsed: number;
58
+ /**
59
+ * `heapUsed` as a percentage of `heapTotal`, rounded to 2 decimals. V8 grows the heap as needed, so a
60
+ * high value alone is not a leak: a leak shows as `heapUsedMin` rising from one reset period to the next.
61
+ */
62
+ heapUsage: number;
63
+ /**
64
+ * The lowest used heap sampled, in bytes.
65
+ */
66
+ heapUsedMin: number;
67
+ /**
68
+ * The highest used heap sampled, in bytes.
69
+ */
70
+ heapUsedMax: number;
71
+ /**
72
+ * The mean used heap of the samples, in bytes, rounded to 2 decimals.
73
+ */
74
+ heapUsedAvg: number;
75
+ /**
76
+ * The median used heap of the samples, in bytes.
77
+ */
78
+ heapUsedP50: number;
79
+ /**
80
+ * The 90th percentile of the used heap samples, in bytes.
81
+ */
82
+ heapUsedP90: number;
83
+ /**
84
+ * The 95th percentile of the used heap samples, in bytes.
85
+ */
86
+ heapUsedP95: number;
87
+ /**
88
+ * The 99th percentile of the used heap samples, in bytes.
89
+ */
90
+ heapUsedP99: number;
91
+ /**
92
+ * The memory of the C++ objects bound to JavaScript objects (the `Buffer`s included) at the latest
93
+ * sample, in bytes.
94
+ */
95
+ externalUsed: number;
96
+ /**
97
+ * The lowest external memory sampled, in bytes.
98
+ */
99
+ externalUsedMin: number;
100
+ /**
101
+ * The highest external memory sampled, in bytes.
102
+ */
103
+ externalUsedMax: number;
104
+ /**
105
+ * The mean external memory of the samples, in bytes, rounded to 2 decimals.
106
+ */
107
+ externalUsedAvg: number;
108
+ /**
109
+ * The median external memory of the samples, in bytes.
110
+ */
111
+ externalUsedP50: number;
112
+ /**
113
+ * The 90th percentile of the external memory samples, in bytes.
114
+ */
115
+ externalUsedP90: number;
116
+ /**
117
+ * The 95th percentile of the external memory samples, in bytes.
118
+ */
119
+ externalUsedP95: number;
120
+ /**
121
+ * The 99th percentile of the external memory samples, in bytes.
122
+ */
123
+ externalUsedP99: number;
124
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A monitor: a component exposing the statistics of what it measures.
3
+ * @typeParam T The type of its statistics.
4
+ */
5
+ export interface IMonitor<T> {
6
+ /**
7
+ * The statistics of the measures, computed at each read.
8
+ */
9
+ statistics: T;
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The statistics of the samples of a measure, in a constant memory: the latest value, the minimum, the maximum, the
3
+ * mean and the standard deviation are exact, the percentiles come from a histogram (3 significant digits)
4
+ */
5
+ export declare class Samples {
6
+ #private;
7
+ protected readonly scale: number;
8
+ /**
9
+ * @param scale the factor of the precision of the percentiles (100 keeps 2 decimals)
10
+ */
11
+ constructor(scale?: number);
12
+ /**
13
+ * Record a sample (a negative value is recorded as 0)
14
+ * @param value
15
+ */
16
+ record(value: number): void;
17
+ /**
18
+ * The number of samples
19
+ */
20
+ get count(): number;
21
+ /**
22
+ * The latest sample, 0 without sample
23
+ */
24
+ get latest(): number;
25
+ /**
26
+ * The minimum, 0 without sample
27
+ */
28
+ get min(): number;
29
+ /**
30
+ * The maximum, 0 without sample
31
+ */
32
+ get max(): number;
33
+ /**
34
+ * The mean, 0 without sample
35
+ */
36
+ get mean(): number;
37
+ /**
38
+ * The (population) standard deviation, 0 without sample
39
+ */
40
+ get stdDev(): number;
41
+ /**
42
+ * A percentile, 0 without sample
43
+ * @param percentile from 0 to 100
44
+ */
45
+ percentile(percentile: number): number;
46
+ /**
47
+ * Forget the samples
48
+ */
49
+ reset(): void;
50
+ }
51
+ /**
52
+ * Round a number to a number of decimals
53
+ * @param value
54
+ * @param fractionDigits
55
+ * @constructor
56
+ */
57
+ export declare function round(value: number, fractionDigits: number): number;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Samples = void 0;
4
+ exports.round = round;
5
+ const node_perf_hooks_1 = require("node:perf_hooks");
6
+ /**
7
+ * The statistics of the samples of a measure, in a constant memory: the latest value, the minimum, the maximum, the
8
+ * mean and the standard deviation are exact, the percentiles come from a histogram (3 significant digits)
9
+ */
10
+ class Samples {
11
+ /**
12
+ * The histogram of the percentiles: it records integers from 1, so a value is recorded multiplied by the scale,
13
+ * plus 1 (a value may be 0)
14
+ */
15
+ #histogram = (0, node_perf_hooks_1.createHistogram)();
16
+ #count = 0;
17
+ #latest = 0;
18
+ #min = 0;
19
+ #max = 0;
20
+ #mean = 0;
21
+ //The sum of the squares of the differences from the mean (Welford's algorithm)
22
+ #m2 = 0;
23
+ /**
24
+ * @param scale the factor of the precision of the percentiles (100 keeps 2 decimals)
25
+ */
26
+ constructor(scale = 1) {
27
+ this.scale = scale;
28
+ }
29
+ /**
30
+ * Record a sample (a negative value is recorded as 0)
31
+ * @param value
32
+ */
33
+ record(value) {
34
+ const sample = Number.isFinite(value) && value > 0 ? value : 0;
35
+ this.#histogram.record(Math.round(sample * this.scale) + 1);
36
+ this.#count++;
37
+ this.#latest = sample;
38
+ if (this.#count === 1) {
39
+ this.#min = sample;
40
+ this.#max = sample;
41
+ }
42
+ else {
43
+ if (sample < this.#min)
44
+ this.#min = sample;
45
+ if (sample > this.#max)
46
+ this.#max = sample;
47
+ }
48
+ const delta = sample - this.#mean;
49
+ this.#mean += delta / this.#count;
50
+ this.#m2 += delta * (sample - this.#mean);
51
+ }
52
+ /**
53
+ * The number of samples
54
+ */
55
+ get count() {
56
+ return this.#count;
57
+ }
58
+ /**
59
+ * The latest sample, 0 without sample
60
+ */
61
+ get latest() {
62
+ return this.#latest;
63
+ }
64
+ /**
65
+ * The minimum, 0 without sample
66
+ */
67
+ get min() {
68
+ return this.#min;
69
+ }
70
+ /**
71
+ * The maximum, 0 without sample
72
+ */
73
+ get max() {
74
+ return this.#max;
75
+ }
76
+ /**
77
+ * The mean, 0 without sample
78
+ */
79
+ get mean() {
80
+ return this.#mean;
81
+ }
82
+ /**
83
+ * The (population) standard deviation, 0 without sample
84
+ */
85
+ get stdDev() {
86
+ return this.#count ? Math.sqrt(this.#m2 / this.#count) : 0;
87
+ }
88
+ /**
89
+ * A percentile, 0 without sample
90
+ * @param percentile from 0 to 100
91
+ */
92
+ percentile(percentile) {
93
+ if (!this.#count)
94
+ return 0;
95
+ return Math.min(Math.max((this.#histogram.percentile(percentile) - 1) / this.scale, this.#min), this.#max);
96
+ }
97
+ /**
98
+ * Forget the samples
99
+ */
100
+ reset() {
101
+ this.#histogram.reset();
102
+ this.#count = 0;
103
+ this.#latest = 0;
104
+ this.#min = 0;
105
+ this.#max = 0;
106
+ this.#mean = 0;
107
+ this.#m2 = 0;
108
+ }
109
+ }
110
+ exports.Samples = Samples;
111
+ /**
112
+ * Round a number to a number of decimals
113
+ * @param value
114
+ * @param fractionDigits
115
+ * @constructor
116
+ */
117
+ function round(value, fractionDigits) {
118
+ return parseFloat(value.toFixed(fractionDigits));
119
+ }
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}