UNPKG

mcp-quiz-server

Version:

🧠 AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.

274 lines (273 loc) • 10.1 kB
"use strict"; /** * @fileoverview Performance Monitoring HTTP Routes * @version 1.0.0 * @since 2025-07-30 * @lastUpdated 2025-07-30 * @module PerformanceRoutes * @description HTTP endpoints for accessing performance metrics and monitoring data * @contributors Claude Code Agent * @dependencies PerformanceMonitor * @requirements REQ-PERF-003 (Performance Metrics API) */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.performanceRoutes = void 0; const express = __importStar(require("express")); const PerformanceMonitor_1 = require("../../monitoring/PerformanceMonitor"); exports.performanceRoutes = express.Router(); /** * Get performance statistics * GET /performance/stats?timeWindow=3600000 */ exports.performanceRoutes.get('/stats', (req, res) => { try { const timeWindow = req.query.timeWindow ? parseInt(req.query.timeWindow) : undefined; const statistics = PerformanceMonitor_1.performanceMonitor.getStatistics(timeWindow); res.json({ success: true, statistics, timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: 'Failed to get performance statistics', message: error instanceof Error ? error.message : 'Unknown error', }); } }); /** * Get slowest operations * GET /performance/slowest?limit=10 */ exports.performanceRoutes.get('/slowest', (req, res) => { try { const limit = req.query.limit ? parseInt(req.query.limit) : 10; const slowestOperations = PerformanceMonitor_1.performanceMonitor.getSlowestOperations(limit); res.json({ success: true, slowestOperations, count: slowestOperations.length, timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: 'Failed to get slowest operations', message: error instanceof Error ? error.message : 'Unknown error', }); } }); /** * Get memory-intensive operations * GET /performance/memory-intensive?limit=10 */ exports.performanceRoutes.get('/memory-intensive', (req, res) => { try { const limit = req.query.limit ? parseInt(req.query.limit) : 10; const memoryIntensiveOperations = PerformanceMonitor_1.performanceMonitor.getMemoryIntensiveOperations(limit); res.json({ success: true, memoryIntensiveOperations, count: memoryIntensiveOperations.length, timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: 'Failed to get memory-intensive operations', message: error instanceof Error ? error.message : 'Unknown error', }); } }); /** * Export all performance data * GET /performance/export */ exports.performanceRoutes.get('/export', (req, res) => { try { const exportData = PerformanceMonitor_1.performanceMonitor.exportMetrics(); // Set headers for file download res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Disposition', `attachment; filename="performance-metrics-${Date.now()}.json"`); res.json(exportData); } catch (error) { res.status(500).json({ error: 'Failed to export performance data', message: error instanceof Error ? error.message : 'Unknown error', }); } }); /** * Clear performance metrics (admin only) * DELETE /performance/metrics */ exports.performanceRoutes.delete('/metrics', (req, res) => { try { // In production, add authentication/authorization check here const authHeader = req.headers.authorization; if (!authHeader || !authHeader.includes('admin')) { return res.status(403).json({ error: 'Access denied', message: 'Admin privileges required to clear metrics', }); } PerformanceMonitor_1.performanceMonitor.clearMetrics(); res.json({ success: true, message: 'Performance metrics cleared successfully', timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: 'Failed to clear performance metrics', message: error instanceof Error ? error.message : 'Unknown error', }); } }); /** * Health check endpoint with performance summary * GET /performance/health */ exports.performanceRoutes.get('/health', (req, res) => { try { const stats = PerformanceMonitor_1.performanceMonitor.getStatistics(300000); // Last 5 minutes const currentMemory = process.memoryUsage(); const uptime = process.uptime(); // Determine health status const healthStatus = { status: 'healthy', issues: [], }; if (stats.averageDuration > 5000) { healthStatus.status = 'warning'; healthStatus.issues.push('High average response time'); } if (stats.successRate < 0.95) { healthStatus.status = 'warning'; healthStatus.issues.push('Low success rate'); } if (currentMemory.heapUsed > 512 * 1024 * 1024) { // 512MB healthStatus.status = 'warning'; healthStatus.issues.push('High memory usage'); } if (stats.performanceIssues.length > 0) { healthStatus.status = 'warning'; healthStatus.issues.push(...stats.performanceIssues); } res.json({ success: true, health: healthStatus, performance: { averageDuration: stats.averageDuration, successRate: stats.successRate, cacheHitRate: stats.cacheHitRate, totalOperations: stats.totalOperations, operationBreakdown: stats.operationBreakdown, performanceIssues: stats.performanceIssues, }, system: { uptime: Math.round(uptime), memoryUsage: { heapUsed: Math.round(currentMemory.heapUsed / 1024 / 1024), // MB heapTotal: Math.round(currentMemory.heapTotal / 1024 / 1024), // MB external: Math.round(currentMemory.external / 1024 / 1024), // MB rss: Math.round(currentMemory.rss / 1024 / 1024), // MB }, cpuUsage: process.cpuUsage(), }, timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ success: false, health: { status: 'error', issues: ['Failed to check health'] }, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }); } }); /** * Real-time performance metrics (Server-Sent Events) * GET /performance/stream */ exports.performanceRoutes.get('/stream', (req, res) => { // Set SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.setHeader('Access-Control-Allow-Origin', '*'); // Send initial connection message res.write(`data: ${JSON.stringify({ type: 'connection', message: 'Connected to performance metrics stream', timestamp: new Date().toISOString(), })}\n\n`); // Send performance updates every 5 seconds const interval = setInterval(() => { try { const stats = PerformanceMonitor_1.performanceMonitor.getStatistics(60000); // Last minute const data = { type: 'metrics', data: { averageDuration: stats.averageDuration, successRate: stats.successRate, cacheHitRate: stats.cacheHitRate, totalOperations: stats.totalOperations, memoryUsage: process.memoryUsage(), timestamp: new Date().toISOString(), }, }; res.write(`data: ${JSON.stringify(data)}\n\n`); } catch (error) { res.write(`data: ${JSON.stringify({ type: 'error', error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), })}\n\n`); } }, 5000); // Clean up on client disconnect req.on('close', () => { clearInterval(interval); }); }); exports.default = exports.performanceRoutes;