node-runtime-guardian 0.1.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/LICENSE +22 -0
- package/README.md +423 -0
- package/dist/core/EventLoopMonitor.d.ts +32 -0
- package/dist/core/EventLoopMonitor.d.ts.map +1 -0
- package/dist/core/EventLoopMonitor.js +131 -0
- package/dist/core/EventLoopMonitor.js.map +1 -0
- package/dist/core/GCMonitor.d.ts +32 -0
- package/dist/core/GCMonitor.d.ts.map +1 -0
- package/dist/core/GCMonitor.js +151 -0
- package/dist/core/GCMonitor.js.map +1 -0
- package/dist/core/Guardian.d.ts +76 -0
- package/dist/core/Guardian.d.ts.map +1 -0
- package/dist/core/Guardian.js +196 -0
- package/dist/core/Guardian.js.map +1 -0
- package/dist/core/HeuristicEngine.d.ts +27 -0
- package/dist/core/HeuristicEngine.d.ts.map +1 -0
- package/dist/core/HeuristicEngine.js +150 -0
- package/dist/core/HeuristicEngine.js.map +1 -0
- package/dist/core/MemoryMonitor.d.ts +33 -0
- package/dist/core/MemoryMonitor.d.ts.map +1 -0
- package/dist/core/MemoryMonitor.js +193 -0
- package/dist/core/MemoryMonitor.js.map +1 -0
- package/dist/core/ProtectionLayer.d.ts +42 -0
- package/dist/core/ProtectionLayer.d.ts.map +1 -0
- package/dist/core/ProtectionLayer.js +105 -0
- package/dist/core/ProtectionLayer.js.map +1 -0
- package/dist/core/ThreadPoolMonitor.d.ts +29 -0
- package/dist/core/ThreadPoolMonitor.d.ts.map +1 -0
- package/dist/core/ThreadPoolMonitor.js +144 -0
- package/dist/core/ThreadPoolMonitor.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/Plugin.d.ts +53 -0
- package/dist/plugins/Plugin.d.ts.map +1 -0
- package/dist/plugins/Plugin.js +74 -0
- package/dist/plugins/Plugin.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +18 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/server/MetricsServer.d.ts +26 -0
- package/dist/server/MetricsServer.d.ts.map +1 -0
- package/dist/server/MetricsServer.js +86 -0
- package/dist/server/MetricsServer.js.map +1 -0
- package/dist/types/index.d.ts +104 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/metrics.d.ts +67 -0
- package/dist/types/metrics.d.ts.map +1 -0
- package/dist/types/metrics.js +3 -0
- package/dist/types/metrics.js.map +1 -0
- package/dist/worker/WorkerPool.d.ts +44 -0
- package/dist/worker/WorkerPool.d.ts.map +1 -0
- package/dist/worker/WorkerPool.js +214 -0
- package/dist/worker/WorkerPool.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryMonitor.d.ts","sourceRoot":"","sources":["../../src/core/MemoryMonitor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EAMZ,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;gBAEzB,MAAM,GAAE,YAAiB;IAYrC;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;OAEG;IACH,IAAI,IAAI,IAAI;IAUZ;;OAEG;IACH,UAAU,IAAI,aAAa;IAW3B;;OAEG;IACH,WAAW,IAAI,WAAW,GAAG,IAAI;IAiCjC,OAAO,CAAC,cAAc;IAkFtB,OAAO,CAAC,WAAW;CAkDpB"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryMonitor = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
/**
|
|
6
|
+
* Monitors memory usage and detects drift patterns
|
|
7
|
+
*/
|
|
8
|
+
class MemoryMonitor extends events_1.EventEmitter {
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
super();
|
|
11
|
+
this.interval = null;
|
|
12
|
+
this.isRunning = false;
|
|
13
|
+
this.history = [];
|
|
14
|
+
this.maxHistorySize = 60; // Keep 60 samples for drift detection
|
|
15
|
+
this.config = {
|
|
16
|
+
enabled: config.enabled ?? true,
|
|
17
|
+
rssLimit: config.rssLimit ?? 0,
|
|
18
|
+
heapLimit: config.heapLimit ?? 0,
|
|
19
|
+
externalLimit: config.externalLimit ?? 0,
|
|
20
|
+
driftDetectionEnabled: config.driftDetectionEnabled ?? true,
|
|
21
|
+
driftThreshold: config.driftThreshold ?? 0.1, // 10% growth rate
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start monitoring memory
|
|
26
|
+
*/
|
|
27
|
+
start() {
|
|
28
|
+
if (!this.config.enabled || this.isRunning) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.interval = setInterval(() => {
|
|
32
|
+
this.collectMetrics();
|
|
33
|
+
}, 1000);
|
|
34
|
+
this.isRunning = true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Stop monitoring
|
|
38
|
+
*/
|
|
39
|
+
stop() {
|
|
40
|
+
if (this.interval) {
|
|
41
|
+
clearInterval(this.interval);
|
|
42
|
+
this.interval = null;
|
|
43
|
+
}
|
|
44
|
+
this.isRunning = false;
|
|
45
|
+
this.history = [];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get current memory metrics
|
|
49
|
+
*/
|
|
50
|
+
getMetrics() {
|
|
51
|
+
const usage = process.memoryUsage();
|
|
52
|
+
return {
|
|
53
|
+
heapUsed: usage.heapUsed,
|
|
54
|
+
heapTotal: usage.heapTotal,
|
|
55
|
+
rss: usage.rss,
|
|
56
|
+
external: usage.external,
|
|
57
|
+
arrayBuffers: usage.arrayBuffers,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Detect memory drift patterns
|
|
62
|
+
*/
|
|
63
|
+
detectDrift() {
|
|
64
|
+
if (!this.config.driftDetectionEnabled || this.history.length < 10) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const recent = this.history.slice(-10);
|
|
68
|
+
const older = this.history.slice(0, 10);
|
|
69
|
+
if (older.length === 0) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const rssGrowthRate = (recent[recent.length - 1].rss - older[0].rss) / older[0].rss;
|
|
73
|
+
const heapGrowthRate = (recent[recent.length - 1].heapUsed - older[0].heapUsed) /
|
|
74
|
+
older[0].heapUsed;
|
|
75
|
+
const externalGrowthRate = (recent[recent.length - 1].external - older[0].external) /
|
|
76
|
+
older[0].external;
|
|
77
|
+
const isLeakSuspected = rssGrowthRate > this.config.driftThreshold &&
|
|
78
|
+
heapGrowthRate < rssGrowthRate * 0.5; // RSS growing faster than heap suggests native leak
|
|
79
|
+
return {
|
|
80
|
+
rssGrowthRate,
|
|
81
|
+
heapGrowthRate,
|
|
82
|
+
externalGrowthRate,
|
|
83
|
+
isLeakSuspected,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
collectMetrics() {
|
|
87
|
+
const metrics = this.getMetrics();
|
|
88
|
+
// Add to history
|
|
89
|
+
this.history.push(metrics);
|
|
90
|
+
if (this.history.length > this.maxHistorySize) {
|
|
91
|
+
this.history.shift();
|
|
92
|
+
}
|
|
93
|
+
// Check limits
|
|
94
|
+
if (this.config.rssLimit > 0 && metrics.rss > this.config.rssLimit) {
|
|
95
|
+
this.emitWarning('memoryLimit', 'RSS memory limit exceeded', metrics);
|
|
96
|
+
}
|
|
97
|
+
if (this.config.heapLimit > 0 && metrics.heapUsed > this.config.heapLimit) {
|
|
98
|
+
this.emitWarning('memoryLimit', 'Heap memory limit exceeded', metrics);
|
|
99
|
+
}
|
|
100
|
+
if (this.config.externalLimit > 0 &&
|
|
101
|
+
metrics.external > this.config.externalLimit) {
|
|
102
|
+
this.emitWarning('memoryLimit', 'External memory limit exceeded', metrics);
|
|
103
|
+
}
|
|
104
|
+
// Detect drift
|
|
105
|
+
const drift = this.detectDrift();
|
|
106
|
+
if (drift && drift.isLeakSuspected) {
|
|
107
|
+
const emptyEventLoop = {
|
|
108
|
+
mean: 0,
|
|
109
|
+
max: 0,
|
|
110
|
+
min: 0,
|
|
111
|
+
p50: 0,
|
|
112
|
+
p95: 0,
|
|
113
|
+
p99: 0,
|
|
114
|
+
};
|
|
115
|
+
const emptyGC = {
|
|
116
|
+
estimatedCycles: 0,
|
|
117
|
+
minorGCCount: 0,
|
|
118
|
+
majorGCCount: 0,
|
|
119
|
+
gcPressure: 0,
|
|
120
|
+
};
|
|
121
|
+
const emptyThreadPool = {
|
|
122
|
+
saturationLevel: 0,
|
|
123
|
+
estimatedQueueSize: 0,
|
|
124
|
+
avgLatency: 0,
|
|
125
|
+
};
|
|
126
|
+
const emptyCPU = {
|
|
127
|
+
user: 0,
|
|
128
|
+
system: 0,
|
|
129
|
+
};
|
|
130
|
+
const warning = {
|
|
131
|
+
type: 'memoryDrift',
|
|
132
|
+
message: `Memory drift detected: RSS growing faster than heap (${(drift.rssGrowthRate * 100).toFixed(2)}% growth)`,
|
|
133
|
+
severity: 'high',
|
|
134
|
+
metrics: {
|
|
135
|
+
eventLoopDelay: emptyEventLoop,
|
|
136
|
+
memory: metrics,
|
|
137
|
+
gc: emptyGC,
|
|
138
|
+
threadPool: emptyThreadPool,
|
|
139
|
+
cpu: emptyCPU,
|
|
140
|
+
activeRequests: 0,
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
},
|
|
143
|
+
timestamp: Date.now(),
|
|
144
|
+
};
|
|
145
|
+
this.emit('warning', warning);
|
|
146
|
+
this.emit('memoryDrift', drift);
|
|
147
|
+
}
|
|
148
|
+
this.emit('metric', metrics);
|
|
149
|
+
}
|
|
150
|
+
emitWarning(type, message, metrics) {
|
|
151
|
+
const emptyEventLoop = {
|
|
152
|
+
mean: 0,
|
|
153
|
+
max: 0,
|
|
154
|
+
min: 0,
|
|
155
|
+
p50: 0,
|
|
156
|
+
p95: 0,
|
|
157
|
+
p99: 0,
|
|
158
|
+
};
|
|
159
|
+
const emptyGC = {
|
|
160
|
+
estimatedCycles: 0,
|
|
161
|
+
minorGCCount: 0,
|
|
162
|
+
majorGCCount: 0,
|
|
163
|
+
gcPressure: 0,
|
|
164
|
+
};
|
|
165
|
+
const emptyThreadPool = {
|
|
166
|
+
saturationLevel: 0,
|
|
167
|
+
estimatedQueueSize: 0,
|
|
168
|
+
avgLatency: 0,
|
|
169
|
+
};
|
|
170
|
+
const emptyCPU = {
|
|
171
|
+
user: 0,
|
|
172
|
+
system: 0,
|
|
173
|
+
};
|
|
174
|
+
const warning = {
|
|
175
|
+
type,
|
|
176
|
+
message,
|
|
177
|
+
severity: 'high',
|
|
178
|
+
metrics: {
|
|
179
|
+
eventLoopDelay: emptyEventLoop,
|
|
180
|
+
memory: metrics,
|
|
181
|
+
gc: emptyGC,
|
|
182
|
+
threadPool: emptyThreadPool,
|
|
183
|
+
cpu: emptyCPU,
|
|
184
|
+
activeRequests: 0,
|
|
185
|
+
timestamp: Date.now(),
|
|
186
|
+
},
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
};
|
|
189
|
+
this.emit('warning', warning);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.MemoryMonitor = MemoryMonitor;
|
|
193
|
+
//# sourceMappingURL=MemoryMonitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryMonitor.js","sourceRoot":"","sources":["../../src/core/MemoryMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { ProtectionConfig, RuntimeMetrics } from '../types';
|
|
4
|
+
export declare class ProtectionLayer extends EventEmitter {
|
|
5
|
+
private config;
|
|
6
|
+
private isProtectionActive;
|
|
7
|
+
private activeRequests;
|
|
8
|
+
constructor(config?: ProtectionConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Check if protection should be active based on metrics
|
|
11
|
+
*/
|
|
12
|
+
evaluateProtection(metrics: RuntimeMetrics): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Check if a request should be rejected
|
|
15
|
+
*/
|
|
16
|
+
shouldRejectRequest(metrics?: RuntimeMetrics): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Get rejection response details
|
|
19
|
+
*/
|
|
20
|
+
getRejectionResponse(): {
|
|
21
|
+
statusCode: number;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Track active request
|
|
26
|
+
*/
|
|
27
|
+
incrementRequest(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Track completed request
|
|
30
|
+
*/
|
|
31
|
+
decrementRequest(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get current active request count
|
|
34
|
+
*/
|
|
35
|
+
getActiveRequests(): number;
|
|
36
|
+
/**
|
|
37
|
+
* Get protection status
|
|
38
|
+
*/
|
|
39
|
+
isActive(): boolean;
|
|
40
|
+
private getProtectionReason;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=ProtectionLayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProtectionLayer.d.ts","sourceRoot":"","sources":["../../src/core/ProtectionLayer.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAgB5D,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,cAAc,CAAK;gBAEf,MAAM,GAAE,gBAAqB;IAgBzC;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IA0BpD;;OAEG;IACH,mBAAmB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO;IAYtD;;OAEG;IACH,oBAAoB,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAO/D;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB,OAAO,CAAC,mBAAmB;CAsB5B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProtectionLayer = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
class ProtectionLayer extends events_1.EventEmitter {
|
|
6
|
+
constructor(config = {}) {
|
|
7
|
+
super();
|
|
8
|
+
this.isProtectionActive = false;
|
|
9
|
+
this.activeRequests = 0;
|
|
10
|
+
this.config = {
|
|
11
|
+
enabled: config.enabled ?? false,
|
|
12
|
+
loadShedding: {
|
|
13
|
+
enabled: config.loadShedding?.enabled ?? true,
|
|
14
|
+
eventLoopThreshold: config.loadShedding?.eventLoopThreshold ?? 200,
|
|
15
|
+
memoryThreshold: config.loadShedding?.memoryThreshold ?? 0.9,
|
|
16
|
+
responseCode: config.loadShedding?.responseCode ?? 503,
|
|
17
|
+
responseMessage: config.loadShedding?.responseMessage ??
|
|
18
|
+
'Service temporarily unavailable',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if protection should be active based on metrics
|
|
24
|
+
*/
|
|
25
|
+
evaluateProtection(metrics) {
|
|
26
|
+
if (!this.config.enabled || !this.config.loadShedding.enabled) {
|
|
27
|
+
this.isProtectionActive = false;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const shouldProtect = metrics.eventLoopDelay.mean >
|
|
31
|
+
this.config.loadShedding.eventLoopThreshold ||
|
|
32
|
+
metrics.memory.heapUsed / metrics.memory.heapTotal >
|
|
33
|
+
this.config.loadShedding.memoryThreshold;
|
|
34
|
+
if (shouldProtect && !this.isProtectionActive) {
|
|
35
|
+
this.isProtectionActive = true;
|
|
36
|
+
this.emit('protectionActivated', {
|
|
37
|
+
reason: this.getProtectionReason(metrics),
|
|
38
|
+
metrics,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else if (!shouldProtect && this.isProtectionActive) {
|
|
42
|
+
this.isProtectionActive = false;
|
|
43
|
+
this.emit('protectionDeactivated', { metrics });
|
|
44
|
+
}
|
|
45
|
+
return this.isProtectionActive;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if a request should be rejected
|
|
49
|
+
*/
|
|
50
|
+
shouldRejectRequest(metrics) {
|
|
51
|
+
if (!this.config.enabled || !this.config.loadShedding.enabled) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (metrics) {
|
|
55
|
+
return this.evaluateProtection(metrics);
|
|
56
|
+
}
|
|
57
|
+
return this.isProtectionActive;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get rejection response details
|
|
61
|
+
*/
|
|
62
|
+
getRejectionResponse() {
|
|
63
|
+
return {
|
|
64
|
+
statusCode: this.config.loadShedding.responseCode,
|
|
65
|
+
message: this.config.loadShedding.responseMessage,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Track active request
|
|
70
|
+
*/
|
|
71
|
+
incrementRequest() {
|
|
72
|
+
this.activeRequests++;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Track completed request
|
|
76
|
+
*/
|
|
77
|
+
decrementRequest() {
|
|
78
|
+
this.activeRequests = Math.max(0, this.activeRequests - 1);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get current active request count
|
|
82
|
+
*/
|
|
83
|
+
getActiveRequests() {
|
|
84
|
+
return this.activeRequests;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get protection status
|
|
88
|
+
*/
|
|
89
|
+
isActive() {
|
|
90
|
+
return this.isProtectionActive;
|
|
91
|
+
}
|
|
92
|
+
getProtectionReason(metrics) {
|
|
93
|
+
const reasons = [];
|
|
94
|
+
if (metrics.eventLoopDelay.mean > this.config.loadShedding.eventLoopThreshold) {
|
|
95
|
+
reasons.push(`Event loop delay: ${metrics.eventLoopDelay.mean.toFixed(2)}ms`);
|
|
96
|
+
}
|
|
97
|
+
if (metrics.memory.heapUsed / metrics.memory.heapTotal >
|
|
98
|
+
this.config.loadShedding.memoryThreshold) {
|
|
99
|
+
reasons.push(`Memory usage: ${((metrics.memory.heapUsed / metrics.memory.heapTotal) * 100).toFixed(2)}%`);
|
|
100
|
+
}
|
|
101
|
+
return reasons.join(', ');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.ProtectionLayer = ProtectionLayer;
|
|
105
|
+
//# sourceMappingURL=ProtectionLayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProtectionLayer.js","sourceRoot":"","sources":["../../src/core/ProtectionLayer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { ThreadPoolConfig, ThreadPoolMetrics } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Monitors thread pool saturation by inferring from async operations latency
|
|
6
|
+
*/
|
|
7
|
+
export declare class ThreadPoolMonitor extends EventEmitter {
|
|
8
|
+
private interval;
|
|
9
|
+
private config;
|
|
10
|
+
private isRunning;
|
|
11
|
+
private latencyHistory;
|
|
12
|
+
private readonly maxHistorySize;
|
|
13
|
+
private readonly testInterval;
|
|
14
|
+
constructor(config?: ThreadPoolConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Start monitoring thread pool
|
|
17
|
+
*/
|
|
18
|
+
start(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Stop monitoring
|
|
21
|
+
*/
|
|
22
|
+
stop(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Get current thread pool metrics (inferred)
|
|
25
|
+
*/
|
|
26
|
+
getMetrics(): ThreadPoolMetrics;
|
|
27
|
+
private measureLatency;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ThreadPoolMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThreadPoolMonitor.d.ts","sourceRoot":"","sources":["../../src/core/ThreadPoolMonitor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EAMlB,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAO;gBAExB,MAAM,GAAE,gBAAqB;IAQzC;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;OAEG;IACH,IAAI,IAAI,IAAI;IAUZ;;OAEG;IACH,UAAU,IAAI,iBAAiB;YAmCjB,cAAc;CA8E7B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ThreadPoolMonitor = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
/**
|
|
7
|
+
* Monitors thread pool saturation by inferring from async operations latency
|
|
8
|
+
*/
|
|
9
|
+
class ThreadPoolMonitor extends events_1.EventEmitter {
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
super();
|
|
12
|
+
this.interval = null;
|
|
13
|
+
this.isRunning = false;
|
|
14
|
+
this.latencyHistory = [];
|
|
15
|
+
this.maxHistorySize = 30;
|
|
16
|
+
this.testInterval = 100; // Test every 100ms
|
|
17
|
+
this.config = {
|
|
18
|
+
enabled: config.enabled ?? true,
|
|
19
|
+
saturationThreshold: config.saturationThreshold ?? 0.8, // 80% saturation
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Start monitoring thread pool
|
|
24
|
+
*/
|
|
25
|
+
start() {
|
|
26
|
+
if (!this.config.enabled || this.isRunning) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.interval = setInterval(() => {
|
|
30
|
+
this.measureLatency();
|
|
31
|
+
}, this.testInterval);
|
|
32
|
+
this.isRunning = true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Stop monitoring
|
|
36
|
+
*/
|
|
37
|
+
stop() {
|
|
38
|
+
if (this.interval) {
|
|
39
|
+
clearInterval(this.interval);
|
|
40
|
+
this.interval = null;
|
|
41
|
+
}
|
|
42
|
+
this.isRunning = false;
|
|
43
|
+
this.latencyHistory = [];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get current thread pool metrics (inferred)
|
|
47
|
+
*/
|
|
48
|
+
getMetrics() {
|
|
49
|
+
if (this.latencyHistory.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
saturationLevel: 0,
|
|
52
|
+
estimatedQueueSize: 0,
|
|
53
|
+
avgLatency: 0,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const avgLatency = this.latencyHistory.reduce((a, b) => a + b, 0) /
|
|
57
|
+
this.latencyHistory.length;
|
|
58
|
+
// Baseline latency for crypto operations (typically < 1ms when not saturated)
|
|
59
|
+
const baselineLatency = 0.5;
|
|
60
|
+
const latencyRatio = Math.min(avgLatency / baselineLatency, 10); // Cap at 10x
|
|
61
|
+
// Estimate saturation based on latency increase
|
|
62
|
+
// Thread pool has 4 threads by default, so saturation occurs when queue builds up
|
|
63
|
+
const saturationLevel = Math.min((latencyRatio - 1) / 9, // Normalize to 0-1 scale
|
|
64
|
+
1);
|
|
65
|
+
// Estimate queue size based on latency (rough heuristic)
|
|
66
|
+
// Higher latency suggests more queued operations
|
|
67
|
+
const estimatedQueueSize = Math.max(0, (latencyRatio - 1) * 4);
|
|
68
|
+
return {
|
|
69
|
+
saturationLevel,
|
|
70
|
+
estimatedQueueSize,
|
|
71
|
+
avgLatency,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async measureLatency() {
|
|
75
|
+
const start = process.hrtime.bigint();
|
|
76
|
+
// Perform a lightweight crypto operation to measure thread pool latency
|
|
77
|
+
try {
|
|
78
|
+
await new Promise((resolve) => {
|
|
79
|
+
(0, crypto_1.createHash)('sha256').update('test').digest('hex');
|
|
80
|
+
// Use setImmediate to ensure async execution
|
|
81
|
+
setImmediate(() => {
|
|
82
|
+
resolve();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
const end = process.hrtime.bigint();
|
|
86
|
+
const latencyMs = Number(end - start) / 1e6; // Convert to milliseconds
|
|
87
|
+
this.latencyHistory.push(latencyMs);
|
|
88
|
+
if (this.latencyHistory.length > this.maxHistorySize) {
|
|
89
|
+
this.latencyHistory.shift();
|
|
90
|
+
}
|
|
91
|
+
const metrics = this.getMetrics();
|
|
92
|
+
if (metrics.saturationLevel > this.config.saturationThreshold) {
|
|
93
|
+
const emptyEventLoop = {
|
|
94
|
+
mean: 0,
|
|
95
|
+
max: 0,
|
|
96
|
+
min: 0,
|
|
97
|
+
p50: 0,
|
|
98
|
+
p95: 0,
|
|
99
|
+
p99: 0,
|
|
100
|
+
};
|
|
101
|
+
const emptyMemory = {
|
|
102
|
+
heapUsed: 0,
|
|
103
|
+
heapTotal: 0,
|
|
104
|
+
rss: 0,
|
|
105
|
+
external: 0,
|
|
106
|
+
arrayBuffers: 0,
|
|
107
|
+
};
|
|
108
|
+
const emptyGC = {
|
|
109
|
+
estimatedCycles: 0,
|
|
110
|
+
minorGCCount: 0,
|
|
111
|
+
majorGCCount: 0,
|
|
112
|
+
gcPressure: 0,
|
|
113
|
+
};
|
|
114
|
+
const emptyCPU = {
|
|
115
|
+
user: 0,
|
|
116
|
+
system: 0,
|
|
117
|
+
};
|
|
118
|
+
const warning = {
|
|
119
|
+
type: 'threadPoolSaturated',
|
|
120
|
+
message: `Thread pool saturation detected: ${(metrics.saturationLevel * 100).toFixed(2)}% (estimated queue: ${metrics.estimatedQueueSize.toFixed(1)})`,
|
|
121
|
+
severity: metrics.saturationLevel > 0.9 ? 'high' : 'medium',
|
|
122
|
+
metrics: {
|
|
123
|
+
eventLoopDelay: emptyEventLoop,
|
|
124
|
+
memory: emptyMemory,
|
|
125
|
+
gc: emptyGC,
|
|
126
|
+
threadPool: metrics,
|
|
127
|
+
cpu: emptyCPU,
|
|
128
|
+
activeRequests: 0,
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
},
|
|
131
|
+
timestamp: Date.now(),
|
|
132
|
+
};
|
|
133
|
+
this.emit('warning', warning);
|
|
134
|
+
this.emit('threadPoolSaturated', metrics);
|
|
135
|
+
}
|
|
136
|
+
this.emit('metric', metrics);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
// Silently handle errors in measurement
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.ThreadPoolMonitor = ThreadPoolMonitor;
|
|
144
|
+
//# sourceMappingURL=ThreadPoolMonitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThreadPoolMonitor.js","sourceRoot":"","sources":["../../src/core/ThreadPoolMonitor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Runtime Guardian
|
|
3
|
+
* Production-grade runtime health and protection engine for Node.js applications
|
|
4
|
+
*/
|
|
5
|
+
export { Guardian } from './core/Guardian';
|
|
6
|
+
export { EventLoopMonitor } from './core/EventLoopMonitor';
|
|
7
|
+
export { MemoryMonitor } from './core/MemoryMonitor';
|
|
8
|
+
export { ThreadPoolMonitor } from './core/ThreadPoolMonitor';
|
|
9
|
+
export { GCMonitor } from './core/GCMonitor';
|
|
10
|
+
export { HeuristicEngine } from './core/HeuristicEngine';
|
|
11
|
+
export { ProtectionLayer } from './core/ProtectionLayer';
|
|
12
|
+
export { GuardianPlugin, PluginRegistry } from './plugins';
|
|
13
|
+
export { WorkerPool } from './worker/WorkerPool';
|
|
14
|
+
export { MetricsServer } from './server/MetricsServer';
|
|
15
|
+
export * from './types';
|
|
16
|
+
import { Guardian } from './core/Guardian';
|
|
17
|
+
export default Guardian;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,eAAe,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Node Runtime Guardian
|
|
4
|
+
* Production-grade runtime health and protection engine for Node.js applications
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.MetricsServer = exports.WorkerPool = exports.PluginRegistry = exports.ProtectionLayer = exports.HeuristicEngine = exports.GCMonitor = exports.ThreadPoolMonitor = exports.MemoryMonitor = exports.EventLoopMonitor = exports.Guardian = void 0;
|
|
22
|
+
// Main Guardian class
|
|
23
|
+
var Guardian_1 = require("./core/Guardian");
|
|
24
|
+
Object.defineProperty(exports, "Guardian", { enumerable: true, get: function () { return Guardian_1.Guardian; } });
|
|
25
|
+
// Core monitors
|
|
26
|
+
var EventLoopMonitor_1 = require("./core/EventLoopMonitor");
|
|
27
|
+
Object.defineProperty(exports, "EventLoopMonitor", { enumerable: true, get: function () { return EventLoopMonitor_1.EventLoopMonitor; } });
|
|
28
|
+
var MemoryMonitor_1 = require("./core/MemoryMonitor");
|
|
29
|
+
Object.defineProperty(exports, "MemoryMonitor", { enumerable: true, get: function () { return MemoryMonitor_1.MemoryMonitor; } });
|
|
30
|
+
var ThreadPoolMonitor_1 = require("./core/ThreadPoolMonitor");
|
|
31
|
+
Object.defineProperty(exports, "ThreadPoolMonitor", { enumerable: true, get: function () { return ThreadPoolMonitor_1.ThreadPoolMonitor; } });
|
|
32
|
+
var GCMonitor_1 = require("./core/GCMonitor");
|
|
33
|
+
Object.defineProperty(exports, "GCMonitor", { enumerable: true, get: function () { return GCMonitor_1.GCMonitor; } });
|
|
34
|
+
// Heuristic and protection
|
|
35
|
+
var HeuristicEngine_1 = require("./core/HeuristicEngine");
|
|
36
|
+
Object.defineProperty(exports, "HeuristicEngine", { enumerable: true, get: function () { return HeuristicEngine_1.HeuristicEngine; } });
|
|
37
|
+
var ProtectionLayer_1 = require("./core/ProtectionLayer");
|
|
38
|
+
Object.defineProperty(exports, "ProtectionLayer", { enumerable: true, get: function () { return ProtectionLayer_1.ProtectionLayer; } });
|
|
39
|
+
// Plugin system
|
|
40
|
+
var plugins_1 = require("./plugins");
|
|
41
|
+
Object.defineProperty(exports, "PluginRegistry", { enumerable: true, get: function () { return plugins_1.PluginRegistry; } });
|
|
42
|
+
// Worker pool
|
|
43
|
+
var WorkerPool_1 = require("./worker/WorkerPool");
|
|
44
|
+
Object.defineProperty(exports, "WorkerPool", { enumerable: true, get: function () { return WorkerPool_1.WorkerPool; } });
|
|
45
|
+
// Metrics server
|
|
46
|
+
var MetricsServer_1 = require("./server/MetricsServer");
|
|
47
|
+
Object.defineProperty(exports, "MetricsServer", { enumerable: true, get: function () { return MetricsServer_1.MetricsServer; } });
|
|
48
|
+
// Types
|
|
49
|
+
__exportStar(require("./types"), exports);
|
|
50
|
+
// Default export for convenience
|
|
51
|
+
const Guardian_2 = require("./core/Guardian");
|
|
52
|
+
exports.default = Guardian_2.Guardian;
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,sBAAsB;AACtB,4CAA2C;AAAlC,oGAAA,QAAQ,OAAA;AAEjB,gBAAgB;AAChB,4DAA2D;AAAlD,oHAAA,gBAAgB,OAAA;AACzB,sDAAqD;AAA5C,8GAAA,aAAa,OAAA;AACtB,8DAA6D;AAApD,sHAAA,iBAAiB,OAAA;AAC1B,8CAA6C;AAApC,sGAAA,SAAS,OAAA;AAElB,2BAA2B;AAC3B,0DAAyD;AAAhD,kHAAA,eAAe,OAAA;AACxB,0DAAyD;AAAhD,kHAAA,eAAe,OAAA;AAExB,gBAAgB;AAChB,qCAA2D;AAAlC,yGAAA,cAAc,OAAA;AAEvC,cAAc;AACd,kDAAiD;AAAxC,wGAAA,UAAU,OAAA;AAEnB,iBAAiB;AACjB,wDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAEtB,QAAQ;AACR,0CAAwB;AAExB,iCAAiC;AACjC,8CAA2C;AAC3C,kBAAe,mBAAQ,CAAC"}
|