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
JavaScript
;
/**
* @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;