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.
189 lines (188 loc) • 7.95 kB
JavaScript
;
/**
* @fileoverview Performance Decorator - Automatic Performance Tracking
* @version 1.0.0
* @since 2025-07-30
* @lastUpdated 2025-07-30
* @module PerformanceDecorator
* @description Decorators for automatic performance monitoring of Clean Architecture handlers
* @contributors Claude Code Agent
* @dependencies PerformanceMonitor
* @requirements REQ-PERF-002 (Automatic Performance Tracking)
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackPerformance = TrackPerformance;
exports.TrackDatabaseOperation = TrackDatabaseOperation;
exports.TrackCacheOperation = TrackCacheOperation;
exports.TrackEventOperation = TrackEventOperation;
exports.TrackClass = TrackClass;
exports.withPerformanceTracking = withPerformanceTracking;
const PerformanceMonitor_1 = require("../../infrastructure/monitoring/PerformanceMonitor");
/**
* Decorator for automatic performance tracking of command handlers
*/
function TrackPerformance(operationType) {
return function (target, propertyName, descriptor) {
const method = descriptor.value;
const finalOperationType = operationType || `${target.constructor.name}.${propertyName}`;
descriptor.value = async function (...args) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(finalOperationType);
try {
console.log(`⚡ Starting ${finalOperationType}`);
const result = await method.apply(this, args);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
console.log(`✅ Completed ${finalOperationType} in ${metrics.duration}ms`);
return result;
}
catch (error) {
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
console.error(`❌ Failed ${finalOperationType} in ${metrics.duration}ms:`, error.message || error);
throw error;
}
};
return descriptor;
};
}
/**
* Decorator for tracking database operations
*/
function TrackDatabaseOperation(operationType) {
return function (target, propertyName, descriptor) {
const method = descriptor.value;
const finalOperationType = operationType || `DB.${target.constructor.name}.${propertyName}`;
descriptor.value = async function (...args) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(finalOperationType);
tracker.recordDatabaseQuery();
try {
const result = await method.apply(this, args);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
return result;
}
catch (error) {
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
throw error;
}
};
return descriptor;
};
}
/**
* Decorator for tracking cache operations
*/
function TrackCacheOperation(operationType) {
return function (target, propertyName, descriptor) {
const method = descriptor.value;
const finalOperationType = operationType || `Cache.${target.constructor.name}.${propertyName}`;
descriptor.value = async function (...args) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(finalOperationType);
try {
const result = await method.apply(this, args);
// Determine if it was a cache hit based on method name or result
const isCacheHit = propertyName.includes('get') && result !== null && result !== undefined;
tracker.recordCacheHit(isCacheHit);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
return result;
}
catch (error) {
tracker.recordCacheHit(false);
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
throw error;
}
};
return descriptor;
};
}
/**
* Decorator for tracking event publishing
*/
function TrackEventOperation(operationType) {
return function (target, propertyName, descriptor) {
const method = descriptor.value;
const finalOperationType = operationType || `Event.${target.constructor.name}.${propertyName}`;
descriptor.value = async function (...args) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(finalOperationType);
tracker.recordEvent();
try {
const result = await method.apply(this, args);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
return result;
}
catch (error) {
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
throw error;
}
};
return descriptor;
};
}
/**
* Class decorator for automatic performance tracking of all methods
*/
function TrackClass(operationPrefix) {
return function (constructor) {
const prefix = operationPrefix || constructor.name;
// Get all method names
const methodNames = Object.getOwnPropertyNames(constructor.prototype).filter(name => name !== 'constructor' && typeof constructor.prototype[name] === 'function');
// Wrap each method with performance tracking
methodNames.forEach(methodName => {
const originalMethod = constructor.prototype[methodName];
const operationType = `${prefix}.${methodName}`;
constructor.prototype[methodName] = async function (...args) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(operationType);
try {
const result = await originalMethod.apply(this, args);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
return result;
}
catch (error) {
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
throw error;
}
};
});
return constructor;
};
}
/**
* Helper function for manual performance tracking with context
*/
async function withPerformanceTracking(operationType, operation, context) {
const tracker = PerformanceMonitor_1.performanceMonitor.startOperation(operationType);
// Apply context if provided
if (context) {
if (context.databaseQueries) {
for (let i = 0; i < context.databaseQueries; i++) {
tracker.recordDatabaseQuery();
}
}
if (context.eventCount) {
for (let i = 0; i < context.eventCount; i++) {
tracker.recordEvent();
}
}
if (context.cacheHit !== undefined) {
tracker.recordCacheHit(context.cacheHit);
}
}
try {
const result = await operation(tracker);
const metrics = tracker.complete(true);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
return result;
}
catch (error) {
const metrics = tracker.complete(false);
PerformanceMonitor_1.performanceMonitor.recordMetrics(metrics);
throw error;
}
}