UNPKG

@ai-capabilities-suite/mcp-debugger-core

Version:

Core debugging engine for Node.js and TypeScript applications. Provides Inspector Protocol integration, breakpoint management, variable inspection, execution control, profiling, hang detection, and source map support.

226 lines 7.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HealthChecker = exports.HealthStatus = void 0; exports.createSimpleDependencyChecker = createSimpleDependencyChecker; /** * Health status enumeration */ var HealthStatus; (function (HealthStatus) { HealthStatus["HEALTHY"] = "healthy"; HealthStatus["UNHEALTHY"] = "unhealthy"; HealthStatus["DEGRADED"] = "degraded"; })(HealthStatus || (exports.HealthStatus = HealthStatus = {})); /** * Health checker for production readiness * Provides health, readiness, and liveness endpoints */ class HealthChecker { constructor() { this.dependencyCheckers = new Map(); this.startTime = Date.now(); } /** * Register a dependency health checker */ registerDependencyChecker(name, checker) { this.dependencyCheckers.set(name, checker); } /** * Unregister a dependency health checker */ unregisterDependencyChecker(name) { this.dependencyCheckers.delete(name); } /** * Get uptime in milliseconds */ getUptime() { return Date.now() - this.startTime; } /** * Check health of a single dependency */ async checkDependency(name, checker) { const startTime = Date.now(); let timeoutId = null; try { const result = await Promise.race([ checker(), new Promise((_, reject) => { timeoutId = setTimeout(() => reject(new Error('Health check timeout')), 5000); }), ]); if (timeoutId) clearTimeout(timeoutId); return { ...result, latency: Date.now() - startTime, }; } catch (error) { if (timeoutId) clearTimeout(timeoutId); return { name, status: HealthStatus.UNHEALTHY, message: error instanceof Error ? error.message : String(error), latency: Date.now() - startTime, }; } } /** * Perform health check * Checks all registered dependencies and returns overall health status */ async checkHealth() { const dependencies = []; // Check all dependencies for (const [name, checker] of this.dependencyCheckers.entries()) { const health = await this.checkDependency(name, checker); dependencies.push(health); } // Determine overall status let overallStatus = HealthStatus.HEALTHY; const unhealthyCount = dependencies.filter((d) => d.status === HealthStatus.UNHEALTHY).length; const degradedCount = dependencies.filter((d) => d.status === HealthStatus.DEGRADED).length; if (unhealthyCount > 0) { overallStatus = HealthStatus.UNHEALTHY; } else if (degradedCount > 0) { overallStatus = HealthStatus.DEGRADED; } const result = { status: overallStatus, timestamp: new Date().toISOString(), uptime: this.getUptime(), dependencies, }; this.lastHealthCheck = result; return result; } /** * Get last health check result (cached) */ getLastHealthCheck() { return this.lastHealthCheck; } /** * Perform readiness check * Checks if the service is ready to accept requests */ async checkReadiness() { const checks = []; // Check if dependencies are healthy for (const [name, checker] of this.dependencyCheckers.entries()) { const health = await this.checkDependency(name, checker); checks.push({ name, ready: health.status !== HealthStatus.UNHEALTHY, message: health.message, }); } // Service is ready if all dependencies are not unhealthy const ready = checks.every((check) => check.ready); return { ready, timestamp: new Date().toISOString(), checks, }; } /** * Perform liveness check * Checks if the service is alive and responsive */ async checkLiveness() { // Basic liveness check - if we can execute this, we're alive // In a real implementation, you might check for deadlocks, etc. try { // Simple check: can we get the current time? const now = Date.now(); return { alive: true, timestamp: new Date(now).toISOString(), }; } catch (error) { return { alive: false, timestamp: new Date().toISOString(), message: error instanceof Error ? error.message : String(error), }; } } /** * Start periodic health checks */ startPeriodicHealthChecks(intervalMs = 30000) { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); } this.healthCheckInterval = setInterval(async () => { await this.checkHealth(); }, intervalMs); } /** * Stop periodic health checks */ stopPeriodicHealthChecks() { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); this.healthCheckInterval = undefined; } } /** * Get health endpoint data (for HTTP endpoint) */ async getHealthEndpointData() { const health = await this.checkHealth(); return JSON.stringify(health, null, 2); } /** * Get readiness endpoint data (for HTTP endpoint) */ async getReadinessEndpointData() { const readiness = await this.checkReadiness(); return JSON.stringify(readiness, null, 2); } /** * Get liveness endpoint data (for HTTP endpoint) */ async getLivenessEndpointData() { const liveness = await this.checkLiveness(); return JSON.stringify(liveness, null, 2); } /** * Cleanup resources */ cleanup() { this.stopPeriodicHealthChecks(); this.dependencyCheckers.clear(); } } exports.HealthChecker = HealthChecker; /** * Create a simple dependency checker for testing */ function createSimpleDependencyChecker(name, checkFn) { return async () => { try { const isHealthy = await checkFn(); return { name, status: isHealthy ? HealthStatus.HEALTHY : HealthStatus.UNHEALTHY, message: isHealthy ? 'OK' : 'Check failed', }; } catch (error) { return { name, status: HealthStatus.UNHEALTHY, message: error instanceof Error ? error.message : String(error), }; } }; } //# sourceMappingURL=health-checker.js.map