UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

277 lines (276 loc) 10.4 kB
import logger from '../logger.js'; export class InitializationMonitor { static instance = null; services = new Map(); globalStartTime; globalEndTime; config = { slowInitThreshold: 5000, criticalSlowThreshold: 15000, enableDetailedLogging: true, trackDependencies: true, maxTrackedServices: 100 }; constructor(config) { if (config) { this.config = { ...this.config, ...config }; } } static getInstance(config) { if (!InitializationMonitor.instance) { InitializationMonitor.instance = new InitializationMonitor(config); } return InitializationMonitor.instance; } startGlobalInitialization() { this.globalStartTime = Date.now(); if (this.config.enableDetailedLogging) { logger.info('Global initialization monitoring started'); } } endGlobalInitialization() { this.globalEndTime = Date.now(); if (this.globalStartTime && this.config.enableDetailedLogging) { const totalTime = this.globalEndTime - this.globalStartTime; logger.info({ totalInitTime: totalTime, servicesInitialized: this.services.size }, 'Global initialization completed'); this.logInitializationSummary(); } } startServiceInitialization(serviceName, dependencies = [], metadata) { if (this.services.size >= this.config.maxTrackedServices) { logger.warn({ serviceName, maxServices: this.config.maxTrackedServices }, 'Maximum tracked services reached, not tracking this service'); return; } const startTime = Date.now(); const serviceInit = { serviceName, startTime, status: 'pending', phases: [], dependencies: [...dependencies], metadata }; this.services.set(serviceName, serviceInit); if (this.config.enableDetailedLogging) { logger.debug({ serviceName, dependencies, metadata }, 'Started tracking service initialization'); } } endServiceInitialization(serviceName, error) { const service = this.services.get(serviceName); if (!service) { logger.warn({ serviceName }, 'Attempted to end tracking for unknown service'); return; } const endTime = Date.now(); const duration = endTime - service.startTime; service.endTime = endTime; service.duration = duration; service.status = error ? 'failed' : 'completed'; service.error = error; this.checkSlowInitialization(serviceName, duration); if (this.config.enableDetailedLogging) { const logLevel = error ? 'error' : 'debug'; logger[logLevel]({ serviceName, duration, status: service.status, error: error?.message }, `Service initialization ${service.status}`); } } startPhase(serviceName, phaseName, metadata) { const service = this.services.get(serviceName); if (!service) { logger.warn({ serviceName, phaseName }, 'Attempted to start phase for unknown service'); return; } const phase = { name: phaseName, startTime: Date.now(), status: 'pending', metadata }; service.phases.push(phase); if (this.config.enableDetailedLogging) { logger.debug({ serviceName, phaseName, metadata }, 'Started initialization phase'); } } endPhase(serviceName, phaseName, error) { const service = this.services.get(serviceName); if (!service) { logger.warn({ serviceName, phaseName }, 'Attempted to end phase for unknown service'); return; } const phase = service.phases.find(p => p.name === phaseName && !p.endTime); if (!phase) { logger.warn({ serviceName, phaseName }, 'Attempted to end unknown or already ended phase'); return; } const endTime = Date.now(); phase.endTime = endTime; phase.duration = endTime - phase.startTime; phase.status = error ? 'failed' : 'completed'; phase.error = error; if (this.config.enableDetailedLogging) { const logLevel = error ? 'warn' : 'debug'; logger[logLevel]({ serviceName, phaseName, duration: phase.duration, status: phase.status, error: error?.message }, `Initialization phase ${phase.status}`); } } checkSlowInitialization(serviceName, duration) { if (duration > this.config.criticalSlowThreshold) { logger.error({ serviceName, duration, threshold: this.config.criticalSlowThreshold }, 'Critical slow initialization detected'); } else if (duration > this.config.slowInitThreshold) { logger.warn({ serviceName, duration, threshold: this.config.slowInitThreshold }, 'Slow initialization detected'); } } getStatistics() { const services = Array.from(this.services.values()); const completedServices = services.filter(s => s.status === 'completed'); const failedServices = services.filter(s => s.status === 'failed'); const pendingServices = services.filter(s => s.status === 'pending'); const completedDurations = completedServices .map(s => s.duration) .filter(d => d !== undefined); const averageInitTime = completedDurations.length > 0 ? completedDurations.reduce((sum, d) => sum + d, 0) / completedDurations.length : 0; let slowestService; let fastestService; if (completedServices.length > 0) { const sortedByDuration = completedServices .filter(s => s.duration !== undefined) .sort((a, b) => b.duration - a.duration); if (sortedByDuration.length > 0) { slowestService = { name: sortedByDuration[0].serviceName, duration: sortedByDuration[0].duration }; fastestService = { name: sortedByDuration[sortedByDuration.length - 1].serviceName, duration: sortedByDuration[sortedByDuration.length - 1].duration }; } } const totalInitTime = this.globalStartTime && this.globalEndTime ? this.globalEndTime - this.globalStartTime : 0; const criticalPath = this.calculateCriticalPath(); return { totalServices: services.length, completedServices: completedServices.length, failedServices: failedServices.length, pendingServices: pendingServices.length, averageInitTime, slowestService, fastestService, totalInitTime, criticalPath }; } calculateCriticalPath() { if (!this.config.trackDependencies) { return []; } const services = Array.from(this.services.values()); const visited = new Set(); const rootServices = services.filter(s => s.dependencies.length === 0); let longestChain = []; for (const root of rootServices) { const chain = this.findLongestChain(root.serviceName, visited, services); if (chain.length > longestChain.length) { longestChain = chain; } } return longestChain; } findLongestChain(serviceName, visited, services) { if (visited.has(serviceName)) { return []; } visited.add(serviceName); const service = services.find(s => s.serviceName === serviceName); if (!service) { return [serviceName]; } let longestSubChain = []; for (const dep of service.dependencies) { const subChain = this.findLongestChain(dep, new Set(visited), services); if (subChain.length > longestSubChain.length) { longestSubChain = subChain; } } return [serviceName, ...longestSubChain]; } logInitializationSummary() { const stats = this.getStatistics(); logger.info({ totalServices: stats.totalServices, completed: stats.completedServices, failed: stats.failedServices, pending: stats.pendingServices, averageInitTime: Math.round(stats.averageInitTime), totalInitTime: stats.totalInitTime, slowestService: stats.slowestService, fastestService: stats.fastestService }, 'Initialization summary'); if (stats.failedServices > 0) { const failedServices = Array.from(this.services.values()) .filter(s => s.status === 'failed') .map(s => ({ name: s.serviceName, error: s.error?.message })); logger.warn({ failedServices }, 'Some services failed to initialize'); } } getServiceDetails(serviceName) { return this.services.get(serviceName); } getAllServices() { return Array.from(this.services.values()); } clear() { this.services.clear(); this.globalStartTime = undefined; this.globalEndTime = undefined; if (this.config.enableDetailedLogging) { logger.debug('Initialization monitoring data cleared'); } } static reset() { if (InitializationMonitor.instance) { InitializationMonitor.instance.clear(); } InitializationMonitor.instance = null; } static createInstance(config) { InitializationMonitor.instance = new InitializationMonitor(config); return InitializationMonitor.instance; } }