qmemory
Version:
A comprehensive production-ready Node.js utility library with MongoDB document operations, user ownership enforcement, Express.js HTTP utilities, environment-aware logging, and in-memory storage. Features 96%+ test coverage with comprehensive error handli
367 lines (299 loc) • 15.1 kB
JavaScript
/**
* Performance Monitoring Demo
* Practical examples showing comprehensive performance tracking integration
*
* This demo shows real-world usage patterns for the performance monitoring utilities
* integrated with the qmemory library's existing storage and HTTP utilities.
*/
const qmemory = require('../index');
// Create a performance monitor instance for comprehensive tracking
const perfMonitor = new qmemory.PerformanceMonitor({
database: { slowQueryThreshold: 75 }, // Custom threshold for demo
system: { collectionInterval: 5000 } // 5 second collection for demo
});
// Simulate Express-like objects for demonstration
function createMockExpressObjects(method = 'GET', path = '/users', statusCode = 200) {
const req = {
method,
path,
route: { path },
get: (header) => header === 'User-Agent' ? 'Demo-Client/1.0' : null
};
const res = {
statusCode,
eventHandlers: {},
on: function(event, handler) {
this.eventHandlers[event] = handler;
},
finish: function() {
if (this.eventHandlers.finish) {
this.eventHandlers.finish();
}
}
};
return { req, res };
}
// Demo 1: Database Performance Tracking
async function demo1_databasePerformance() {
console.log('\n=== Demo 1: Database Performance Tracking ===');
// Simulate various database operations with different performance characteristics
console.log('Simulating database operations...');
// Fast query simulation
perfMonitor.database.recordQuery('getUserById', 25, true, { userId: 123 });
perfMonitor.database.recordQuery('getUserById', 30, true, { userId: 456 });
perfMonitor.database.recordQuery('getUserById', 28, true, { userId: 789 });
// Medium performance queries
perfMonitor.database.recordQuery('getUsersByRole', 65, true, { role: 'admin' });
perfMonitor.database.recordQuery('getUsersByRole', 70, true, { role: 'user' });
// Slow query simulation (will trigger alert)
perfMonitor.database.recordQuery('complexReport', 120, true, { reportType: 'monthly' });
// Failed query simulation
perfMonitor.database.recordQuery('brokenQuery', 85, false, { error: 'timeout' });
// Update connection pool metrics
perfMonitor.database.updateConnectionMetrics(8, 12, 150, 142);
// Generate database metrics report
const dbMetrics = perfMonitor.database.getMetrics();
console.log('\nDatabase Performance Summary:');
console.log(`- Total queries: ${dbMetrics.totalQueries}`);
console.log(`- Slow queries detected: ${dbMetrics.slowQueries}`);
console.log(`- Connection pool: ${dbMetrics.connectionPool.active} active, ${dbMetrics.connectionPool.available} available`);
console.log('\nQuery Performance Breakdown:');
Object.entries(dbMetrics.queryStats).forEach(([queryName, stats]) => {
console.log(` ${queryName}:`);
console.log(` - Average: ${stats.avgDuration}ms`);
console.log(` - Range: ${stats.minDuration}ms - ${stats.maxDuration}ms`);
console.log(` - Failure rate: ${stats.failureRate}%`);
console.log(` - Queries/sec: ${stats.queriesPerSecond}`);
});
}
// Demo 2: HTTP Request Performance Tracking
async function demo2_httpPerformance() {
console.log('\n=== Demo 2: HTTP Request Performance Tracking ===');
// Create request middleware for automatic tracking
const middleware = perfMonitor.createRequestMiddleware();
console.log('Created request tracking middleware');
// Simulate various HTTP requests
console.log('Simulating HTTP requests...');
const requests = [
{ method: 'GET', path: '/users', status: 200, duration: 45 },
{ method: 'GET', path: '/users', status: 200, duration: 38 },
{ method: 'GET', path: '/users', status: 404, duration: 25 },
{ method: 'POST', path: '/users', status: 201, duration: 95 },
{ method: 'PUT', path: '/users/123', status: 200, duration: 75 },
{ method: 'DELETE', path: '/users/456', status: 204, duration: 55 },
{ method: 'GET', path: '/posts', status: 500, duration: 150 }
];
// Process each simulated request
for (const { method, path, status, duration } of requests) {
const { req, res } = createMockExpressObjects(method, path, status);
// Use middleware to track the request
const next = () => {};
middleware(req, res, next);
// Simulate request processing time
await new Promise(resolve => setTimeout(resolve, 10));
// Simulate response completion
res.finish();
}
// Wait for middleware processing
await new Promise(resolve => setTimeout(resolve, 50));
// Generate HTTP metrics report
const reqMetrics = perfMonitor.requests.getMetrics();
console.log('\nHTTP Performance Summary:');
console.log(`- Total requests: ${reqMetrics.totalRequests}`);
console.log(`- Requests per second: ${reqMetrics.requestsPerSecond}`);
console.log(`- Uptime: ${reqMetrics.uptime} seconds`);
console.log('\nEndpoint Performance Breakdown:');
Object.entries(reqMetrics.endpoints).forEach(([endpoint, stats]) => {
console.log(` ${endpoint}:`);
console.log(` - Requests: ${stats.requests}`);
console.log(` - Average: ${stats.avgDuration}ms`);
console.log(` - Range: ${stats.minDuration}ms - ${stats.maxDuration}ms`);
console.log(` - Error rate: ${stats.errorRate}%`);
console.log(` - Status codes:`, stats.statusCodes);
});
}
// Demo 3: System Resource Monitoring
async function demo3_systemMonitoring() {
console.log('\n=== Demo 3: System Resource Monitoring ===');
console.log('Collecting system metrics...');
// Wait for system metrics collection
await new Promise(resolve => setTimeout(resolve, 6000));
const sysMetrics = perfMonitor.system.getMetrics();
console.log('\nSystem Performance Summary:');
console.log(`- Process uptime: ${sysMetrics.uptime} seconds`);
console.log(`- Node.js version: ${sysMetrics.nodeVersion}`);
console.log('\nMemory Usage:');
console.log(` - RSS: ${sysMetrics.memory.current.rss} MB`);
console.log(` - Heap Used: ${sysMetrics.memory.current.heapUsed} MB`);
console.log(` - Heap Total: ${sysMetrics.memory.current.heapTotal} MB`);
console.log(` - External: ${sysMetrics.memory.current.external} MB`);
console.log('\nCPU Usage:');
console.log(` - Current: ${sysMetrics.cpu.current}%`);
console.log(` - History points: ${sysMetrics.cpu.history.length}`);
if (sysMetrics.memory.history.length > 0) {
console.log(`\nMetrics History: ${sysMetrics.memory.history.length} data points collected`);
}
}
// Demo 4: Database Operation Wrapper
async function demo4_databaseWrapper() {
console.log('\n=== Demo 4: Database Operation Wrapper ===');
// Simulate database operations that we want to monitor
const mockDatabaseOperations = {
async getUserById(id) {
await new Promise(resolve => setTimeout(resolve, Math.random() * 50 + 20));
if (id === 'invalid') throw new Error('User not found');
return { id, name: `User ${id}`, email: `user${id}@example.com` };
},
async createUser(userData) {
await new Promise(resolve => setTimeout(resolve, Math.random() * 100 + 50));
return { id: Date.now(), ...userData };
},
async updateUser(id, data) {
await new Promise(resolve => setTimeout(resolve, Math.random() * 80 + 30));
if (Math.random() < 0.1) throw new Error('Database timeout');
return { id, ...data, updatedAt: new Date() };
}
};
// Wrap operations for performance monitoring
const monitoredDb = {
getUserById: perfMonitor.wrapDatabaseOperation(mockDatabaseOperations.getUserById, 'getUserById'),
createUser: perfMonitor.wrapDatabaseOperation(mockDatabaseOperations.createUser, 'createUser'),
updateUser: perfMonitor.wrapDatabaseOperation(mockDatabaseOperations.updateUser, 'updateUser')
};
console.log('Testing wrapped database operations...');
// Test successful operations
try {
const user1 = await monitoredDb.getUserById('123');
console.log('✓ Retrieved user:', user1.name);
const newUser = await monitoredDb.createUser({ name: 'John Doe', email: 'john@example.com' });
console.log('✓ Created user:', newUser.name);
const updatedUser = await monitoredDb.updateUser('123', { name: 'Jane Doe' });
console.log('✓ Updated user:', updatedUser.name);
} catch (error) {
console.log('✗ Operation failed (as expected for demo):', error.message);
}
// Test failed operations
try {
await monitoredDb.getUserById('invalid');
} catch (error) {
console.log('✗ Failed operation tracked:', error.message);
}
// Attempt operation that might timeout
try {
await monitoredDb.updateUser('456', { name: 'Test User' });
} catch (error) {
console.log('✗ Timeout operation tracked:', error.message);
}
console.log('\nAll database operations are now being automatically tracked!');
}
// Demo 5: Comprehensive Monitoring Report
async function demo5_comprehensiveReport() {
console.log('\n=== Demo 5: Comprehensive Performance Report ===');
const report = perfMonitor.getComprehensiveMetrics();
console.log('Full Performance Report:');
console.log('=======================');
console.log(`Report generated at: ${report.timestamp}`);
console.log('\n📊 Database Performance:');
console.log(` - Total queries: ${report.database.totalQueries}`);
console.log(` - Slow queries: ${report.database.slowQueries}`);
console.log(` - Connection pool utilization: ${report.database.connectionPool.active}/${report.database.connectionPool.active + report.database.connectionPool.available}`);
console.log('\n🌐 HTTP Performance:');
console.log(` - Total requests: ${report.requests.totalRequests}`);
console.log(` - Throughput: ${report.requests.requestsPerSecond} req/sec`);
console.log(` - Tracked endpoints: ${Object.keys(report.requests.endpoints).length}`);
console.log('\n💻 System Resources:');
console.log(` - Memory usage: ${report.system.memory.current.heapUsed} MB heap`);
console.log(` - CPU usage: ${report.system.cpu.current}%`);
console.log(` - Process uptime: ${report.system.uptime} seconds`);
// Generate health check
console.log('\n🏥 Health Check:');
const health = perfMonitor.getHealthCheck();
console.log(` - Overall status: ${health.status.toUpperCase()}`);
console.log(` - Database: ${health.checks.database.status}`);
console.log(` - Requests: ${health.checks.requests.status}`);
console.log(` - Memory: ${health.checks.memory.status}`);
if (health.status !== 'healthy') {
console.log('\n⚠️ Performance Issues Detected:');
Object.entries(health.checks).forEach(([component, check]) => {
if (check.status !== 'healthy') {
console.log(` - ${component}: ${check.status}`);
}
});
}
}
// Demo 6: Integration with Existing Storage
async function demo6_storageIntegration() {
console.log('\n=== Demo 6: Integration with Existing Storage ===');
// Clear existing storage
await qmemory.storage.clear();
// Wrap storage operations for monitoring
const monitoredStorage = {
createUser: perfMonitor.wrapDatabaseOperation(qmemory.storage.createUser.bind(qmemory.storage), 'storage.createUser'),
getUserByUsername: perfMonitor.wrapDatabaseOperation(qmemory.storage.getUserByUsername.bind(qmemory.storage), 'storage.getUserByUsername'),
getAllUsers: perfMonitor.wrapDatabaseOperation(qmemory.storage.getAllUsers.bind(qmemory.storage), 'storage.getAllUsers')
};
console.log('Creating users with performance monitoring...');
// Create several users to generate performance data
const users = [
{ username: 'alice', displayName: 'Alice Johnson' },
{ username: 'bob', displayName: 'Bob Smith' },
{ username: 'charlie', displayName: 'Charlie Brown' }
];
for (const userData of users) {
try {
const user = await monitoredStorage.createUser(userData);
console.log(`✓ Created user: ${user.displayName}`);
} catch (error) {
console.log(`✗ Failed to create user: ${error.message}`);
}
}
// Test retrieval operations
console.log('\nTesting retrieval operations...');
const alice = await monitoredStorage.getUserByUsername('alice');
console.log(`✓ Retrieved user: ${alice?.displayName || 'Not found'}`);
const allUsers = await monitoredStorage.getAllUsers();
console.log(`✓ Retrieved ${allUsers.length} users total`);
// Show storage operation performance
const storageMetrics = perfMonitor.database.getMetrics();
console.log('\nStorage Operation Performance:');
Object.entries(storageMetrics.queryStats)
.filter(([name]) => name.startsWith('storage.'))
.forEach(([operation, stats]) => {
console.log(` ${operation}: ${stats.avgDuration}ms avg (${stats.count} ops)`);
});
}
// Run all demos
async function runAllDemos() {
console.log('🚀 Performance Monitoring Demo');
console.log('=====================================');
try {
await demo1_databasePerformance();
await demo2_httpPerformance();
await demo3_systemMonitoring();
await demo4_databaseWrapper();
await demo5_comprehensiveReport();
await demo6_storageIntegration();
console.log('\n✅ All performance monitoring demos completed successfully!');
console.log('\nThe performance monitoring utilities provide:');
console.log('- Real-time database query performance tracking');
console.log('- HTTP request monitoring with Express middleware');
console.log('- System resource utilization monitoring');
console.log('- Automatic slow query detection and alerting');
console.log('- Comprehensive health checks for monitoring systems');
console.log('- Easy integration with existing applications');
} catch (error) {
console.error('❌ Demo failed:', error);
} finally {
// Clean up monitoring resources
perfMonitor.stop();
console.log('\n🧹 Performance monitoring stopped and cleaned up');
}
}
// Run demos if this file is executed directly
if (require.main === module) {
runAllDemos();
}
module.exports = {
perfMonitor,
runAllDemos
};