Skip to main content
Glama
monitoring-tools.ts13.6 kB
/** * Monitoring Tools Module * Real-time deployment monitoring and dashboard features * Part of Jaxon Digital Optimizely DXP MCP Server */ import ResponseBuilder from '../response-builder'; import ErrorHandler from '../error-handler'; // import EventEmitter - unused /** * Deployment object (minimal structure) */ interface Deployment { Id: string; Status: string; Created: string; CompletedTime?: string; SourceEnvironment?: string; TargetEnvironment?: string; } /** * Environment status */ interface EnvironmentStatus { status: string; lastDeployment: { id: string; status: string; created: string; } | null; } /** * Deployment analysis summary */ interface AnalysisSummary { total: number; inProgress: number; awaitingVerification: number; recentCompleted: number; recentFailed: number; } /** * Deployment patterns */ interface DeploymentPatterns { mostCommonRoute: string | null; averageDuration: string | null; successRate: number; } /** * Deployment analysis result */ interface DeploymentAnalysis { summary: AnalysisSummary; environments: { Integration: EnvironmentStatus; Preproduction: EnvironmentStatus; Production: EnvironmentStatus; }; activeDeployments: Deployment[]; recentDeployments: Deployment[]; patterns: DeploymentPatterns; recommendations: string[]; } /** * Background monitor info */ interface BackgroundMonitor { startTime: number; environment: string; databaseName: string; } /** * Monitoring parameters */ interface MonitoringParams { [key: string]: any; } class MonitoringTools { /** * NOTE: getDeploymentDashboard and monitorDeployment methods have been removed * as part of DXP-101 (PowerShell to REST API migration). * * Use these alternatives instead: * - list_deployments tool for deployment listing * - DeploymentTools.handleMonitorDeployment() for real-time monitoring */ /* REMOVED METHODS (DXP-101 - PowerShell to REST API migration): * - getDeploymentDashboard() - Replaced by list_deployments tool * - monitorDeployment() - Replaced by DeploymentTools.handleMonitorDeployment() */ /** * Analyze deployments and generate insights */ static analyzeDeployments(deployments: Deployment[], _project: any): DeploymentAnalysis { const now = new Date(); const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); const analysis: DeploymentAnalysis = { summary: { total: deployments.length, inProgress: 0, awaitingVerification: 0, recentCompleted: 0, recentFailed: 0 }, environments: { Integration: { status: 'idle', lastDeployment: null }, Preproduction: { status: 'idle', lastDeployment: null }, Production: { status: 'idle', lastDeployment: null } }, activeDeployments: [], recentDeployments: [], patterns: { mostCommonRoute: null, averageDuration: null, successRate: 0 }, recommendations: [] }; // Route frequency counter const routeFrequency: Record<string, number> = {}; let totalDuration = 0; let completedCount = 0; let weeklySuccess = 0; let weeklyTotal = 0; for (const dep of deployments) { const created = new Date(dep.Created); const isRecent = created > oneDayAgo; const isThisWeek = created > oneWeekAgo; // Update summary if (dep.Status === 'InProgress') { analysis.summary.inProgress++; analysis.activeDeployments.push(dep); } else if (dep.Status === 'AwaitingVerification') { analysis.summary.awaitingVerification++; analysis.activeDeployments.push(dep); } else if (isRecent) { if (dep.Status === 'Succeeded') { analysis.summary.recentCompleted++; } else if (dep.Status === 'Failed') { analysis.summary.recentFailed++; } } // Track recent deployments if (isRecent) { analysis.recentDeployments.push(dep); } // Update environment status if (dep.TargetEnvironment && analysis.environments[dep.TargetEnvironment as keyof typeof analysis.environments]) { if (dep.Status === 'InProgress' || dep.Status === 'AwaitingVerification') { analysis.environments[dep.TargetEnvironment as keyof typeof analysis.environments].status = dep.Status.toLowerCase(); } // Track last deployment const envStatus = analysis.environments[dep.TargetEnvironment as keyof typeof analysis.environments]; if (!envStatus.lastDeployment || created > new Date(envStatus.lastDeployment.created)) { envStatus.lastDeployment = { id: dep.Id, status: dep.Status, created: created.toISOString() }; } } // Track patterns const route = `${dep.SourceEnvironment}→${dep.TargetEnvironment}`; routeFrequency[route] = (routeFrequency[route] || 0) + 1; if (dep.Status === 'Succeeded' && dep.CompletedTime) { const duration = new Date(dep.CompletedTime).getTime() - created.getTime(); totalDuration += duration; completedCount++; } if (isThisWeek) { weeklyTotal++; if (dep.Status === 'Succeeded') { weeklySuccess++; } } } // Calculate patterns if (Object.keys(routeFrequency).length > 0) { analysis.patterns.mostCommonRoute = Object.entries(routeFrequency) .sort((a, b) => b[1] - a[1])[0][0]; } if (completedCount > 0) { const avgMs = totalDuration / completedCount; const avgMinutes = Math.round(avgMs / 60000); analysis.patterns.averageDuration = `${avgMinutes} minutes`; } if (weeklyTotal > 0) { analysis.patterns.successRate = Math.round((weeklySuccess / weeklyTotal) * 100); } // Generate recommendations if (analysis.summary.awaitingVerification > 0) { analysis.recommendations.push( `⚠️ ${analysis.summary.awaitingVerification} deployment(s) awaiting verification` ); } if (analysis.summary.recentFailed > 2) { analysis.recommendations.push( '⚠️ Multiple failed deployments in last 24h - review logs' ); } if (analysis.patterns.successRate < 80 && weeklyTotal > 5) { analysis.recommendations.push( `⚠️ Low success rate (${analysis.patterns.successRate}%) - consider reviewing deployment process` ); } return analysis; } /** * Helper methods */ static getStatusIcon(status: string): string { const icons: Record<string, string> = { 'Succeeded': '✅', 'Failed': '❌', 'InProgress': '⏳', 'AwaitingVerification': '🔍', 'Resetting': '🔄', 'Reset': '↩️' }; return icons[status] || '❓'; } static getEnvironmentIcon(status: EnvironmentStatus): string { if (status.status === 'inprogress') return '⏳'; if (status.status === 'awaitingverification') return '🔍'; return '✅'; } static calculateProgress(deployment: Deployment | null): string { if (!deployment) return ''; if (deployment.Status === 'Succeeded') return '(100%)'; if (deployment.Status === 'Failed') return '(Failed)'; if (deployment.Status === 'AwaitingVerification') return '(90% - Needs verification)'; if (deployment.Status === 'InProgress') { // Estimate based on time elapsed const created = new Date(deployment.Created); const elapsed = Date.now() - created.getTime(); const estimatedDuration = 10 * 60 * 1000; // 10 minutes average const progress = Math.min(85, Math.round((elapsed / estimatedDuration) * 85)); return `(~${progress}%)`; } return ''; } static isDeploymentComplete(status: string): boolean { return ['Succeeded', 'Failed', 'Reset'].includes(status); } static formatTime(timestamp: string | null): string { if (!timestamp) return 'Unknown'; const date = new Date(timestamp); const now = new Date(); const diff = now.getTime() - date.getTime(); if (diff < 60000) return 'Just now'; if (diff < 3600000) return `${Math.round(diff / 60000)} min ago`; if (diff < 86400000) return `${Math.round(diff / 3600000)} hours ago`; return date.toLocaleDateString(); } static getVerificationUrl(deployment: Deployment, projectId: string): string { const baseUrl = 'https://dxp.episerver.com'; return `${baseUrl}/projects/${projectId}/deployments/${deployment.Id}/verify`; } /** * Get monitoring statistics */ static async getMonitoringStats(_params: MonitoringParams = {}): Promise<any> { try { // Check for active database export monitors const DatabaseSimpleTools = require('./database-simple-tools'); const activeMonitors: Map<string, BackgroundMonitor> = DatabaseSimpleTools.backgroundMonitors; const response: string[] = []; response.push('## 📊 Monitoring Statistics\n'); if (activeMonitors && activeMonitors.size > 0) { response.push(`**Active Database Export Monitors:** ${activeMonitors.size}`); for (const [exportId, monitor] of activeMonitors) { const runtime = Math.round((Date.now() - monitor.startTime) / 60000); // Show 13 chars to get past first dash (e.g., "c88fa98f-9d3c...") response.push(`• Export ${exportId.substring(0, 13)}... (${monitor.environment}/${monitor.databaseName}) - Running ${runtime}m`); } } else { response.push('**Active Database Export Monitors:** 0'); } response.push('\n**System Status:**'); response.push('• Background monitoring: ✅ Available'); response.push('• Auto-download: ✅ Available'); response.push('• Progress tracking: ✅ Available'); return ResponseBuilder.success(response.join('\n')); } catch (error: any) { return ResponseBuilder.error('MONITORING_ERROR', error.message); } } /** * List active deployment monitors and monitoring statistics */ static async listMonitors(_params: MonitoringParams = {}): Promise<any> { try { // Check for active database export monitors const DatabaseSimpleTools = require('./database-simple-tools'); const activeMonitors: Map<string, BackgroundMonitor> = DatabaseSimpleTools.backgroundMonitors; const response: string[] = []; response.push('## 📡 Deployment Monitoring Status\n'); if (activeMonitors && activeMonitors.size > 0) { response.push(`**Active Monitors:** ${activeMonitors.size} background monitor(s) running`); for (const [exportId, monitor] of activeMonitors) { const runtime = Math.round((Date.now() - monitor.startTime) / 60000); // Show 13 chars to get past first dash (e.g., "c88fa98f-9d3c...") response.push(`• Database Export: ${exportId.substring(0, 13)}... (${monitor.environment}/${monitor.databaseName}) - ${runtime}m`); } } else { response.push('**Active Monitors:** Currently no background monitors running'); } response.push('**Monitoring Features:**'); response.push('• Real-time deployment tracking'); response.push('• Progress monitoring with ETA calculation'); response.push('• Automatic completion detection'); response.push('• Background monitoring support\n'); response.push('**Available Commands:**'); response.push('• `update_monitoring_interval` - Change monitoring frequency'); response.push('• `stop_monitoring` - Stop active monitors'); response.push('• `get_monitoring_stats` - View detailed statistics\n'); response.push('💡 **Tip:** Monitoring is automatically started when using deployment tools'); return ResponseBuilder.success( response.join('\n') ); } catch (error: any) { return ErrorHandler.handleError(error, { operation: 'list_monitors' }); } } } export default MonitoringTools;

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JaxonDigital/optimizely-dxp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server