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
JavaScript
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;
}
}