@wundr.io/mcp-registry 1.0.3
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 +890 -0
- package/dist/aggregator.d.ts +330 -0
- package/dist/aggregator.d.ts.map +1 -0
- package/dist/aggregator.js +708 -0
- package/dist/aggregator.js.map +1 -0
- package/dist/discovery.d.ts +274 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +536 -0
- package/dist/discovery.js.map +1 -0
- package/dist/health-monitor.d.ts +304 -0
- package/dist/health-monitor.d.ts.map +1 -0
- package/dist/health-monitor.js +626 -0
- package/dist/health-monitor.js.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +185 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +323 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +647 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +663 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +120 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @wundr.io/mcp-registry - Health Monitor
|
|
4
|
+
*
|
|
5
|
+
* Server health tracking, monitoring, and automatic recovery.
|
|
6
|
+
* Provides continuous health checks and status reporting.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ServerHealthMonitor = exports.HealthCheckError = void 0;
|
|
12
|
+
exports.createServerHealthMonitor = createServerHealthMonitor;
|
|
13
|
+
const eventemitter3_1 = require("eventemitter3");
|
|
14
|
+
const types_1 = require("./types");
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Health Monitor Error Types
|
|
17
|
+
// =============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when health check fails
|
|
20
|
+
*/
|
|
21
|
+
class HealthCheckError extends Error {
|
|
22
|
+
serverId;
|
|
23
|
+
checkName;
|
|
24
|
+
constructor(serverId, checkName, message) {
|
|
25
|
+
super(message ?? `Health check "${checkName}" failed for server: ${serverId}`);
|
|
26
|
+
this.serverId = serverId;
|
|
27
|
+
this.checkName = checkName;
|
|
28
|
+
this.name = 'HealthCheckError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.HealthCheckError = HealthCheckError;
|
|
32
|
+
// =============================================================================
|
|
33
|
+
// ServerHealthMonitor Class
|
|
34
|
+
// =============================================================================
|
|
35
|
+
/**
|
|
36
|
+
* Server Health Monitor
|
|
37
|
+
*
|
|
38
|
+
* Provides continuous health monitoring for registered MCP servers.
|
|
39
|
+
* Tracks connection status, latency, and custom health checks.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const monitor = new ServerHealthMonitor(registry, {
|
|
44
|
+
* checkInterval: 10000,
|
|
45
|
+
* pingTimeout: 5000,
|
|
46
|
+
* failureThreshold: 3,
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* // Register custom health check
|
|
50
|
+
* monitor.registerCheck({
|
|
51
|
+
* name: 'memory-usage',
|
|
52
|
+
* check: async (server) => ({
|
|
53
|
+
* name: 'memory-usage',
|
|
54
|
+
* status: 'healthy',
|
|
55
|
+
* durationMs: 10,
|
|
56
|
+
* timestamp: new Date(),
|
|
57
|
+
* }),
|
|
58
|
+
* critical: false,
|
|
59
|
+
* timeout: 5000,
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Start monitoring
|
|
63
|
+
* await monitor.start();
|
|
64
|
+
*
|
|
65
|
+
* // Get server health
|
|
66
|
+
* const health = monitor.getHealth('server-id');
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
class ServerHealthMonitor extends eventemitter3_1.EventEmitter {
|
|
70
|
+
registry;
|
|
71
|
+
/** Configuration */
|
|
72
|
+
config;
|
|
73
|
+
/** Registered health checks */
|
|
74
|
+
healthChecks;
|
|
75
|
+
/** Latency history by server ID */
|
|
76
|
+
latencyHistory;
|
|
77
|
+
/** Consecutive failure counts by server ID */
|
|
78
|
+
failureCounts;
|
|
79
|
+
/** Consecutive success counts by server ID */
|
|
80
|
+
successCounts;
|
|
81
|
+
/** Monitoring interval handle */
|
|
82
|
+
monitoringInterval;
|
|
83
|
+
/** Whether monitoring is active */
|
|
84
|
+
isMonitoring;
|
|
85
|
+
/** Request counts by server ID */
|
|
86
|
+
requestCounts;
|
|
87
|
+
/**
|
|
88
|
+
* Creates a new ServerHealthMonitor
|
|
89
|
+
*
|
|
90
|
+
* @param registry - The server registry
|
|
91
|
+
* @param config - Health monitor configuration
|
|
92
|
+
*/
|
|
93
|
+
constructor(registry, config = {}) {
|
|
94
|
+
super();
|
|
95
|
+
this.registry = registry;
|
|
96
|
+
// Validate and merge config with defaults
|
|
97
|
+
const validation = types_1.HealthMonitorConfigSchema.safeParse(config);
|
|
98
|
+
if (!validation.success) {
|
|
99
|
+
throw new Error(`Invalid health monitor config: ${validation.error.message}`);
|
|
100
|
+
}
|
|
101
|
+
this.config = {
|
|
102
|
+
checkInterval: config.checkInterval ?? 30000,
|
|
103
|
+
pingTimeout: config.pingTimeout ?? 5000,
|
|
104
|
+
failureThreshold: config.failureThreshold ?? 3,
|
|
105
|
+
recoveryThreshold: config.recoveryThreshold ?? 2,
|
|
106
|
+
degradedLatencyThreshold: config.degradedLatencyThreshold ?? 1000,
|
|
107
|
+
autoReconnect: config.autoReconnect ?? true,
|
|
108
|
+
maxReconnectAttempts: config.maxReconnectAttempts ?? 5,
|
|
109
|
+
};
|
|
110
|
+
this.healthChecks = new Map();
|
|
111
|
+
this.latencyHistory = new Map();
|
|
112
|
+
this.failureCounts = new Map();
|
|
113
|
+
this.successCounts = new Map();
|
|
114
|
+
this.requestCounts = new Map();
|
|
115
|
+
this.isMonitoring = false;
|
|
116
|
+
// Register default ping check
|
|
117
|
+
this.registerCheck({
|
|
118
|
+
name: 'ping',
|
|
119
|
+
check: this.createPingCheck(),
|
|
120
|
+
critical: true,
|
|
121
|
+
timeout: this.config.pingTimeout,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// ===========================================================================
|
|
125
|
+
// Lifecycle Methods
|
|
126
|
+
// ===========================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Start health monitoring
|
|
129
|
+
*/
|
|
130
|
+
async start() {
|
|
131
|
+
if (this.isMonitoring) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.isMonitoring = true;
|
|
135
|
+
// Perform initial health check on all servers
|
|
136
|
+
await this.checkAllServers();
|
|
137
|
+
// Start periodic monitoring
|
|
138
|
+
this.monitoringInterval = setInterval(() => {
|
|
139
|
+
this.checkAllServers().catch(error => {
|
|
140
|
+
console.error('Health check cycle failed:', error);
|
|
141
|
+
});
|
|
142
|
+
}, this.config.checkInterval);
|
|
143
|
+
this.emit('monitor:started');
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Stop health monitoring
|
|
147
|
+
*/
|
|
148
|
+
async stop() {
|
|
149
|
+
if (!this.isMonitoring) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
this.isMonitoring = false;
|
|
153
|
+
if (this.monitoringInterval) {
|
|
154
|
+
clearInterval(this.monitoringInterval);
|
|
155
|
+
this.monitoringInterval = undefined;
|
|
156
|
+
}
|
|
157
|
+
this.emit('monitor:stopped');
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Check if monitoring is active
|
|
161
|
+
*
|
|
162
|
+
* @returns True if monitoring is active
|
|
163
|
+
*/
|
|
164
|
+
isActive() {
|
|
165
|
+
return this.isMonitoring;
|
|
166
|
+
}
|
|
167
|
+
// ===========================================================================
|
|
168
|
+
// Health Check Registration
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
/**
|
|
171
|
+
* Register a custom health check
|
|
172
|
+
*
|
|
173
|
+
* @param check - Health check to register
|
|
174
|
+
*/
|
|
175
|
+
registerCheck(check) {
|
|
176
|
+
this.healthChecks.set(check.name, check);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Unregister a health check
|
|
180
|
+
*
|
|
181
|
+
* @param name - Check name to unregister
|
|
182
|
+
*/
|
|
183
|
+
unregisterCheck(name) {
|
|
184
|
+
this.healthChecks.delete(name);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get all registered checks
|
|
188
|
+
*
|
|
189
|
+
* @returns Array of registered health checks
|
|
190
|
+
*/
|
|
191
|
+
getRegisteredChecks() {
|
|
192
|
+
return Array.from(this.healthChecks.values());
|
|
193
|
+
}
|
|
194
|
+
// ===========================================================================
|
|
195
|
+
// Health Status Methods
|
|
196
|
+
// ===========================================================================
|
|
197
|
+
/**
|
|
198
|
+
* Get health status for a server
|
|
199
|
+
*
|
|
200
|
+
* @param serverId - Server ID
|
|
201
|
+
* @returns Health status or undefined
|
|
202
|
+
*/
|
|
203
|
+
getHealth(serverId) {
|
|
204
|
+
return this.registry.getHealthStatus(serverId);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get health statuses for all servers
|
|
208
|
+
*
|
|
209
|
+
* @returns Map of server ID to health status
|
|
210
|
+
*/
|
|
211
|
+
getAllHealth() {
|
|
212
|
+
const statuses = new Map();
|
|
213
|
+
for (const server of this.registry.getAll()) {
|
|
214
|
+
const health = this.registry.getHealthStatus(server.id);
|
|
215
|
+
if (health) {
|
|
216
|
+
statuses.set(server.id, health);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return statuses;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Force a health check for a specific server
|
|
223
|
+
*
|
|
224
|
+
* @param serverId - Server ID
|
|
225
|
+
* @returns Health status after check
|
|
226
|
+
*/
|
|
227
|
+
async checkServer(serverId) {
|
|
228
|
+
const server = this.registry.get(serverId);
|
|
229
|
+
if (!server) {
|
|
230
|
+
throw new Error(`Server not found: ${serverId}`);
|
|
231
|
+
}
|
|
232
|
+
return this.performHealthCheck(server);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Check health of all servers
|
|
236
|
+
*/
|
|
237
|
+
async checkAllServers() {
|
|
238
|
+
const servers = this.registry.getAll();
|
|
239
|
+
await Promise.all(servers.map(server => this.performHealthCheck(server).catch(error => {
|
|
240
|
+
console.error(`Health check failed for server ${server.id}:`, error);
|
|
241
|
+
})));
|
|
242
|
+
}
|
|
243
|
+
// ===========================================================================
|
|
244
|
+
// Request Tracking Methods
|
|
245
|
+
// ===========================================================================
|
|
246
|
+
/**
|
|
247
|
+
* Record a request for a server
|
|
248
|
+
*
|
|
249
|
+
* @param serverId - Server ID
|
|
250
|
+
* @param success - Whether request was successful
|
|
251
|
+
* @param latencyMs - Request latency in milliseconds
|
|
252
|
+
*/
|
|
253
|
+
recordRequest(serverId, success, latencyMs) {
|
|
254
|
+
// Update request counts
|
|
255
|
+
const counts = this.requestCounts.get(serverId) ?? {
|
|
256
|
+
total: 0,
|
|
257
|
+
successful: 0,
|
|
258
|
+
};
|
|
259
|
+
counts.total++;
|
|
260
|
+
if (success) {
|
|
261
|
+
counts.successful++;
|
|
262
|
+
}
|
|
263
|
+
this.requestCounts.set(serverId, counts);
|
|
264
|
+
// Update latency history
|
|
265
|
+
if (latencyMs !== undefined) {
|
|
266
|
+
this.recordLatency(serverId, latencyMs);
|
|
267
|
+
}
|
|
268
|
+
// Update consecutive counts
|
|
269
|
+
if (success) {
|
|
270
|
+
this.incrementSuccessCount(serverId);
|
|
271
|
+
this.resetFailureCount(serverId);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
this.incrementFailureCount(serverId);
|
|
275
|
+
this.resetSuccessCount(serverId);
|
|
276
|
+
}
|
|
277
|
+
// Update health status
|
|
278
|
+
this.updateHealthFromCounts(serverId);
|
|
279
|
+
}
|
|
280
|
+
// ===========================================================================
|
|
281
|
+
// Private Health Check Methods
|
|
282
|
+
// ===========================================================================
|
|
283
|
+
/**
|
|
284
|
+
* Perform health check on a server
|
|
285
|
+
*/
|
|
286
|
+
async performHealthCheck(server) {
|
|
287
|
+
const startTime = Date.now();
|
|
288
|
+
const checkResults = [];
|
|
289
|
+
let allPassed = true;
|
|
290
|
+
let hasCriticalFailure = false;
|
|
291
|
+
// Run all registered health checks
|
|
292
|
+
for (const [name, check] of this.healthChecks) {
|
|
293
|
+
try {
|
|
294
|
+
const result = await this.runCheckWithTimeout(check, server);
|
|
295
|
+
checkResults.push(result);
|
|
296
|
+
if (result.status === 'unhealthy') {
|
|
297
|
+
allPassed = false;
|
|
298
|
+
if (check.critical) {
|
|
299
|
+
hasCriticalFailure = true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (result.status === 'degraded') {
|
|
303
|
+
allPassed = false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
const result = {
|
|
308
|
+
name,
|
|
309
|
+
status: 'unhealthy',
|
|
310
|
+
message: error instanceof Error ? error.message : String(error),
|
|
311
|
+
durationMs: Date.now() - startTime,
|
|
312
|
+
timestamp: new Date(),
|
|
313
|
+
};
|
|
314
|
+
checkResults.push(result);
|
|
315
|
+
allPassed = false;
|
|
316
|
+
if (check.critical) {
|
|
317
|
+
hasCriticalFailure = true;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Calculate overall status
|
|
322
|
+
const previousStatus = this.registry.getHealthStatus(server.id);
|
|
323
|
+
const previousLevel = previousStatus?.status ?? 'unknown';
|
|
324
|
+
let newStatus;
|
|
325
|
+
if (hasCriticalFailure) {
|
|
326
|
+
newStatus = 'unhealthy';
|
|
327
|
+
}
|
|
328
|
+
else if (!allPassed) {
|
|
329
|
+
newStatus = 'degraded';
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
newStatus = 'healthy';
|
|
333
|
+
}
|
|
334
|
+
// Get latency metrics
|
|
335
|
+
const latencyMs = Date.now() - startTime;
|
|
336
|
+
this.recordLatency(server.id, latencyMs);
|
|
337
|
+
const avgLatencyMs = this.calculateAverageLatency(server.id);
|
|
338
|
+
// Check for latency-based degradation
|
|
339
|
+
if (newStatus === 'healthy' &&
|
|
340
|
+
avgLatencyMs > this.config.degradedLatencyThreshold) {
|
|
341
|
+
newStatus = 'degraded';
|
|
342
|
+
}
|
|
343
|
+
// Get request stats
|
|
344
|
+
const requestStats = this.requestCounts.get(server.id) ?? {
|
|
345
|
+
total: 0,
|
|
346
|
+
successful: 0,
|
|
347
|
+
};
|
|
348
|
+
const errorRate = requestStats.total > 0
|
|
349
|
+
? 1 - requestStats.successful / requestStats.total
|
|
350
|
+
: 0;
|
|
351
|
+
// Build health status
|
|
352
|
+
const healthStatus = {
|
|
353
|
+
serverId: server.id,
|
|
354
|
+
status: newStatus,
|
|
355
|
+
connected: newStatus !== 'unhealthy',
|
|
356
|
+
lastPing: new Date(),
|
|
357
|
+
latencyMs,
|
|
358
|
+
avgLatencyMs,
|
|
359
|
+
consecutiveFailures: this.failureCounts.get(server.id) ?? 0,
|
|
360
|
+
totalRequests: requestStats.total,
|
|
361
|
+
successfulRequests: requestStats.successful,
|
|
362
|
+
errorRate,
|
|
363
|
+
checks: checkResults,
|
|
364
|
+
updatedAt: new Date(),
|
|
365
|
+
};
|
|
366
|
+
// Update registry
|
|
367
|
+
this.registry.updateHealthStatus(server.id, healthStatus);
|
|
368
|
+
// Emit events
|
|
369
|
+
this.emitHealthCheckEvent(server.id, healthStatus, checkResults);
|
|
370
|
+
if (previousLevel !== newStatus) {
|
|
371
|
+
this.emitHealthChangeEvent(server.id, previousLevel, newStatus);
|
|
372
|
+
}
|
|
373
|
+
return healthStatus;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Run a health check with timeout
|
|
377
|
+
*/
|
|
378
|
+
async runCheckWithTimeout(check, server) {
|
|
379
|
+
return new Promise((resolve, reject) => {
|
|
380
|
+
const timer = setTimeout(() => {
|
|
381
|
+
reject(new HealthCheckError(server.id, check.name, 'Health check timed out'));
|
|
382
|
+
}, check.timeout);
|
|
383
|
+
check
|
|
384
|
+
.check(server)
|
|
385
|
+
.then(result => {
|
|
386
|
+
clearTimeout(timer);
|
|
387
|
+
resolve(result);
|
|
388
|
+
})
|
|
389
|
+
.catch(error => {
|
|
390
|
+
clearTimeout(timer);
|
|
391
|
+
reject(error);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Create the default ping check
|
|
397
|
+
*/
|
|
398
|
+
createPingCheck() {
|
|
399
|
+
return async (server) => {
|
|
400
|
+
const startTime = Date.now();
|
|
401
|
+
// Simulate a ping check (in real implementation, would ping the server)
|
|
402
|
+
// For now, check if server is in registry and has valid transport config
|
|
403
|
+
const isValid = server.transport.type !== undefined &&
|
|
404
|
+
(server.transport.command !== undefined ||
|
|
405
|
+
server.transport.url !== undefined);
|
|
406
|
+
return {
|
|
407
|
+
name: 'ping',
|
|
408
|
+
status: isValid ? 'healthy' : 'unhealthy',
|
|
409
|
+
message: isValid
|
|
410
|
+
? 'Server is reachable'
|
|
411
|
+
: 'Server configuration invalid',
|
|
412
|
+
durationMs: Date.now() - startTime,
|
|
413
|
+
timestamp: new Date(),
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
// ===========================================================================
|
|
418
|
+
// Private Helper Methods
|
|
419
|
+
// ===========================================================================
|
|
420
|
+
/**
|
|
421
|
+
* Record latency for a server
|
|
422
|
+
*/
|
|
423
|
+
recordLatency(serverId, latencyMs) {
|
|
424
|
+
let history = this.latencyHistory.get(serverId);
|
|
425
|
+
if (!history) {
|
|
426
|
+
history = [];
|
|
427
|
+
this.latencyHistory.set(serverId, history);
|
|
428
|
+
}
|
|
429
|
+
// Keep last 100 latency measurements
|
|
430
|
+
history.push(latencyMs);
|
|
431
|
+
if (history.length > 100) {
|
|
432
|
+
history.shift();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Calculate average latency for a server
|
|
437
|
+
*/
|
|
438
|
+
calculateAverageLatency(serverId) {
|
|
439
|
+
const history = this.latencyHistory.get(serverId);
|
|
440
|
+
if (!history || history.length === 0) {
|
|
441
|
+
return 0;
|
|
442
|
+
}
|
|
443
|
+
const sum = history.reduce((acc, val) => acc + val, 0);
|
|
444
|
+
return sum / history.length;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Increment failure count for a server
|
|
448
|
+
*/
|
|
449
|
+
incrementFailureCount(serverId) {
|
|
450
|
+
const count = this.failureCounts.get(serverId) ?? 0;
|
|
451
|
+
this.failureCounts.set(serverId, count + 1);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Reset failure count for a server
|
|
455
|
+
*/
|
|
456
|
+
resetFailureCount(serverId) {
|
|
457
|
+
this.failureCounts.set(serverId, 0);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Increment success count for a server
|
|
461
|
+
*/
|
|
462
|
+
incrementSuccessCount(serverId) {
|
|
463
|
+
const count = this.successCounts.get(serverId) ?? 0;
|
|
464
|
+
this.successCounts.set(serverId, count + 1);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Reset success count for a server
|
|
468
|
+
*/
|
|
469
|
+
resetSuccessCount(serverId) {
|
|
470
|
+
this.successCounts.set(serverId, 0);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Update health status from consecutive counts
|
|
474
|
+
*/
|
|
475
|
+
updateHealthFromCounts(serverId) {
|
|
476
|
+
const failureCount = this.failureCounts.get(serverId) ?? 0;
|
|
477
|
+
const successCount = this.successCounts.get(serverId) ?? 0;
|
|
478
|
+
const currentHealth = this.registry.getHealthStatus(serverId);
|
|
479
|
+
const previousStatus = currentHealth?.status ?? 'unknown';
|
|
480
|
+
let newStatus = previousStatus;
|
|
481
|
+
if (failureCount >= this.config.failureThreshold) {
|
|
482
|
+
newStatus = 'unhealthy';
|
|
483
|
+
}
|
|
484
|
+
else if (previousStatus === 'unhealthy' &&
|
|
485
|
+
successCount >= this.config.recoveryThreshold) {
|
|
486
|
+
newStatus = 'healthy';
|
|
487
|
+
}
|
|
488
|
+
else if (failureCount > 0 && previousStatus === 'healthy') {
|
|
489
|
+
newStatus = 'degraded';
|
|
490
|
+
}
|
|
491
|
+
if (previousStatus !== newStatus) {
|
|
492
|
+
this.registry.updateHealthStatus(serverId, { status: newStatus });
|
|
493
|
+
this.emitHealthChangeEvent(serverId, previousStatus, newStatus);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Emit health check event
|
|
498
|
+
*/
|
|
499
|
+
emitHealthCheckEvent(serverId, status, checks) {
|
|
500
|
+
const event = {
|
|
501
|
+
serverId,
|
|
502
|
+
status,
|
|
503
|
+
checks,
|
|
504
|
+
timestamp: new Date(),
|
|
505
|
+
};
|
|
506
|
+
this.emit('health:checked', event);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Emit health change event
|
|
510
|
+
*/
|
|
511
|
+
emitHealthChangeEvent(serverId, previousStatus, newStatus) {
|
|
512
|
+
const event = {
|
|
513
|
+
serverId,
|
|
514
|
+
previousStatus,
|
|
515
|
+
newStatus,
|
|
516
|
+
timestamp: new Date(),
|
|
517
|
+
};
|
|
518
|
+
this.emit('health:changed', event);
|
|
519
|
+
// Emit specific events
|
|
520
|
+
if (newStatus === 'degraded' && previousStatus === 'healthy') {
|
|
521
|
+
this.emit('health:degraded', event);
|
|
522
|
+
}
|
|
523
|
+
else if (newStatus === 'healthy' && previousStatus !== 'healthy') {
|
|
524
|
+
this.emit('health:recovered', event);
|
|
525
|
+
}
|
|
526
|
+
else if (newStatus === 'unhealthy') {
|
|
527
|
+
this.emit('health:failed', event);
|
|
528
|
+
}
|
|
529
|
+
// Emit connection events
|
|
530
|
+
if (previousStatus !== 'unhealthy' && newStatus === 'unhealthy') {
|
|
531
|
+
this.emit('server:disconnected', {
|
|
532
|
+
serverId,
|
|
533
|
+
connected: false,
|
|
534
|
+
timestamp: new Date(),
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
else if (previousStatus === 'unhealthy' && newStatus !== 'unhealthy') {
|
|
538
|
+
this.emit('server:connected', {
|
|
539
|
+
serverId,
|
|
540
|
+
connected: true,
|
|
541
|
+
timestamp: new Date(),
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
// ===========================================================================
|
|
546
|
+
// Utility Methods
|
|
547
|
+
// ===========================================================================
|
|
548
|
+
/**
|
|
549
|
+
* Get monitoring statistics
|
|
550
|
+
*
|
|
551
|
+
* @returns Health monitor statistics
|
|
552
|
+
*/
|
|
553
|
+
getStats() {
|
|
554
|
+
const allHealth = this.getAllHealth();
|
|
555
|
+
let healthy = 0;
|
|
556
|
+
let degraded = 0;
|
|
557
|
+
let unhealthy = 0;
|
|
558
|
+
let unknown = 0;
|
|
559
|
+
for (const status of allHealth.values()) {
|
|
560
|
+
switch (status.status) {
|
|
561
|
+
case 'healthy':
|
|
562
|
+
healthy++;
|
|
563
|
+
break;
|
|
564
|
+
case 'degraded':
|
|
565
|
+
degraded++;
|
|
566
|
+
break;
|
|
567
|
+
case 'unhealthy':
|
|
568
|
+
unhealthy++;
|
|
569
|
+
break;
|
|
570
|
+
default:
|
|
571
|
+
unknown++;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return {
|
|
575
|
+
isMonitoring: this.isMonitoring,
|
|
576
|
+
checkInterval: this.config.checkInterval,
|
|
577
|
+
totalServers: allHealth.size,
|
|
578
|
+
healthyServers: healthy,
|
|
579
|
+
degradedServers: degraded,
|
|
580
|
+
unhealthyServers: unhealthy,
|
|
581
|
+
unknownServers: unknown,
|
|
582
|
+
registeredChecks: this.healthChecks.size,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Reset all monitoring state
|
|
587
|
+
*/
|
|
588
|
+
reset() {
|
|
589
|
+
this.latencyHistory.clear();
|
|
590
|
+
this.failureCounts.clear();
|
|
591
|
+
this.successCounts.clear();
|
|
592
|
+
this.requestCounts.clear();
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Get configuration
|
|
596
|
+
*
|
|
597
|
+
* @returns Current configuration
|
|
598
|
+
*/
|
|
599
|
+
getConfig() {
|
|
600
|
+
return { ...this.config };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
exports.ServerHealthMonitor = ServerHealthMonitor;
|
|
604
|
+
// =============================================================================
|
|
605
|
+
// Factory Function
|
|
606
|
+
// =============================================================================
|
|
607
|
+
/**
|
|
608
|
+
* Create a new ServerHealthMonitor
|
|
609
|
+
*
|
|
610
|
+
* @param registry - The server registry
|
|
611
|
+
* @param config - Optional health monitor configuration
|
|
612
|
+
* @returns New health monitor instance
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```typescript
|
|
616
|
+
* const monitor = createServerHealthMonitor(registry, {
|
|
617
|
+
* checkInterval: 10000,
|
|
618
|
+
* pingTimeout: 5000,
|
|
619
|
+
* });
|
|
620
|
+
* await monitor.start();
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
function createServerHealthMonitor(registry, config) {
|
|
624
|
+
return new ServerHealthMonitor(registry, config);
|
|
625
|
+
}
|
|
626
|
+
//# sourceMappingURL=health-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-monitor.js","sourceRoot":"","sources":["../src/health-monitor.ts"],"names":[],"mappings":"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"}
|