UNPKG

@joystick.js/db-canary

Version:

JoystickDB - A minimalist database server for the Joystick framework

186 lines (147 loc) 5.85 kB
import test from 'ava'; import { PerformanceMonitor } from '../../../src/server/lib/performance_monitor.js'; test('PerformanceMonitor - should initialize with empty metrics', t => { const monitor = new PerformanceMonitor(); const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 0); t.is(stats.total_errors, 0); t.is(stats.ops_per_second, 0); t.is(stats.avg_response_time_ms, 0); t.is(stats.error_rate_percent, 0); }); test('PerformanceMonitor - should track successful operations', t => { const monitor = new PerformanceMonitor(); monitor.track_operation('find_one', 50, 'success'); monitor.track_operation('insert_one', 100, 'success'); const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 2); t.is(stats.total_errors, 0); t.is(stats.error_rate_percent, 0); t.true(stats.ops_per_second >= 0); t.true(stats.avg_response_time_ms > 0); }); test('PerformanceMonitor - should track failed operations', t => { const monitor = new PerformanceMonitor(); monitor.track_operation('find_one', 25, 'error', 'Document not found'); monitor.track_operation('insert_one', 75, 'success'); const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 2); t.is(stats.total_errors, 1); t.is(stats.error_rate_percent, 50); t.is(stats.top_errors.length, 1); t.is(stats.top_errors[0].error, 'Document not found'); t.is(stats.top_errors[0].count, 1); }); test('PerformanceMonitor - should track operation breakdown', t => { const monitor = new PerformanceMonitor(); monitor.track_operation('find_one', 50, 'success'); monitor.track_operation('find_one', 100, 'error', 'Timeout'); monitor.track_operation('insert_one', 75, 'success'); const stats = monitor.get_performance_stats(); t.truthy(stats.operations.find_one); t.is(stats.operations.find_one.count, 2); t.is(stats.operations.find_one.error_count, 1); t.is(stats.operations.find_one.error_rate, 50); t.is(stats.operations.find_one.avg_duration_ms, 75); t.truthy(stats.operations.insert_one); t.is(stats.operations.insert_one.count, 1); t.is(stats.operations.insert_one.error_count, 0); t.is(stats.operations.insert_one.error_rate, 0); t.is(stats.operations.insert_one.avg_duration_ms, 75); }); test('PerformanceMonitor - should get memory stats', t => { const monitor = new PerformanceMonitor(); const memory_stats = monitor.get_memory_stats(); t.true(typeof memory_stats.rss_mb === 'number'); t.true(typeof memory_stats.heap_total_mb === 'number'); t.true(typeof memory_stats.heap_used_mb === 'number'); t.true(typeof memory_stats.heap_used_percent === 'number'); t.true(typeof memory_stats.external_mb === 'number'); t.true(memory_stats.rss_mb > 0); t.true(memory_stats.heap_total_mb > 0); t.true(memory_stats.heap_used_mb > 0); t.true(memory_stats.heap_used_percent >= 0 && memory_stats.heap_used_percent <= 100); }); test('PerformanceMonitor - should get system stats', t => { const monitor = new PerformanceMonitor(); const system_stats = monitor.get_system_stats(); t.true(typeof system_stats.node_version === 'string'); t.true(typeof system_stats.platform === 'string'); t.true(typeof system_stats.arch === 'string'); t.true(typeof system_stats.pid === 'number'); t.true(typeof system_stats.cpu_user_ms === 'number'); t.true(typeof system_stats.cpu_system_ms === 'number'); t.true(system_stats.pid > 0); t.true(system_stats.cpu_user_ms >= 0); t.true(system_stats.cpu_system_ms >= 0); }); test('PerformanceMonitor - should log structured operations', t => { const monitor = new PerformanceMonitor(); // This should not throw t.notThrows(() => { monitor.log_structured_operation( 'client_123', 'find_one', 'users', 45, 'success', null, 1024, 2048 ); }); const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 1); t.is(stats.total_errors, 0); }); test('PerformanceMonitor - should log structured operations with errors', t => { const monitor = new PerformanceMonitor(); monitor.log_structured_operation( 'client_456', 'insert_one', 'users', 100, 'error', 'Validation failed', 512, 0 ); const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 1); t.is(stats.total_errors, 1); t.is(stats.error_rate_percent, 100); }); test('PerformanceMonitor - should reset metrics', t => { const monitor = new PerformanceMonitor(); monitor.track_operation('find_one', 50, 'success'); monitor.track_operation('insert_one', 100, 'error', 'Test error'); let stats = monitor.get_performance_stats(); t.is(stats.total_requests, 2); t.is(stats.total_errors, 1); monitor.reset_metrics(); stats = monitor.get_performance_stats(); t.is(stats.total_requests, 0); t.is(stats.total_errors, 0); t.is(stats.ops_per_second, 0); t.is(stats.avg_response_time_ms, 0); t.is(stats.error_rate_percent, 0); }); test('PerformanceMonitor - should limit response times array size', t => { const monitor = new PerformanceMonitor(); // Add more than max_response_times (1000) operations for (let i = 0; i < 1200; i++) { monitor.track_operation('test_op', 10, 'success'); } const stats = monitor.get_performance_stats(); t.is(stats.total_requests, 1200); // Response times array should be limited t.true(monitor.metrics.response_times.length <= monitor.max_response_times); }); test('PerformanceMonitor - should handle database stats gracefully', t => { const monitor = new PerformanceMonitor(); // This should not throw even if database is not available t.notThrows(() => { const db_stats = monitor.get_database_stats(); t.true(typeof db_stats === 'object'); }); });