performance-monitor.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // GrabZilla 2.1 - Performance Monitoring
  2. // Tracks CPU, memory, download, and conversion metrics
  3. const os = require('os');
  4. /**
  5. * Performance monitoring system for tracking system resources and download statistics
  6. */
  7. class PerformanceMonitor {
  8. constructor() {
  9. this.metrics = {
  10. downloads: [],
  11. conversions: [],
  12. cpuSamples: [],
  13. memorySamples: []
  14. };
  15. this.startTime = Date.now();
  16. this.monitorInterval = null;
  17. this.startMonitoring();
  18. }
  19. /**
  20. * Start monitoring system metrics every 2 seconds
  21. */
  22. startMonitoring() {
  23. this.monitorInterval = setInterval(() => {
  24. this.sampleSystemMetrics();
  25. }, 2000); // Every 2 seconds
  26. }
  27. /**
  28. * Sample current CPU and memory usage
  29. */
  30. sampleSystemMetrics() {
  31. // Calculate CPU usage
  32. const cpus = os.cpus();
  33. const totalIdle = cpus.reduce((acc, cpu) => acc + cpu.times.idle, 0);
  34. const totalTick = cpus.reduce((acc, cpu) => {
  35. return acc + Object.values(cpu.times).reduce((a, b) => a + b, 0);
  36. }, 0);
  37. const cpuUsage = 100 - (100 * totalIdle / totalTick);
  38. this.metrics.cpuSamples.push({
  39. timestamp: Date.now(),
  40. usage: cpuUsage,
  41. cores: cpus.length
  42. });
  43. // Memory usage
  44. const memUsage = process.memoryUsage();
  45. this.metrics.memorySamples.push({
  46. timestamp: Date.now(),
  47. heapUsed: memUsage.heapUsed,
  48. heapTotal: memUsage.heapTotal
  49. });
  50. // Keep only last 100 samples (~ 3 minutes of history)
  51. if (this.metrics.cpuSamples.length > 100) {
  52. this.metrics.cpuSamples.shift();
  53. this.metrics.memorySamples.shift();
  54. }
  55. }
  56. /**
  57. * Record a completed download
  58. * @param {Object} downloadData - Download information
  59. * @param {string} downloadData.videoId - Video ID
  60. * @param {number} downloadData.duration - Download duration in ms
  61. * @param {string} downloadData.status - Download status
  62. */
  63. recordDownload(downloadData) {
  64. this.metrics.downloads.push({
  65. videoId: downloadData.videoId,
  66. duration: downloadData.duration,
  67. success: downloadData.status === 'completed',
  68. timestamp: Date.now()
  69. });
  70. // Keep only last 1000 download records
  71. if (this.metrics.downloads.length > 1000) {
  72. this.metrics.downloads.shift();
  73. }
  74. }
  75. /**
  76. * Record a completed conversion
  77. * @param {Object} conversionData - Conversion information
  78. * @param {string} conversionData.videoId - Video ID
  79. * @param {number} conversionData.duration - Conversion duration in ms
  80. * @param {boolean} conversionData.usedGPU - Whether GPU was used
  81. */
  82. recordConversion(conversionData) {
  83. this.metrics.conversions.push({
  84. videoId: conversionData.videoId,
  85. duration: conversionData.duration,
  86. usedGPU: conversionData.usedGPU,
  87. timestamp: Date.now()
  88. });
  89. // Keep only last 1000 conversion records
  90. if (this.metrics.conversions.length > 1000) {
  91. this.metrics.conversions.shift();
  92. }
  93. }
  94. /**
  95. * Get current statistics
  96. * @returns {Object} Performance statistics
  97. */
  98. getStats() {
  99. return {
  100. downloads: {
  101. total: this.metrics.downloads.length,
  102. successful: this.metrics.downloads.filter(d => d.success).length,
  103. failed: this.metrics.downloads.filter(d => !d.success).length
  104. },
  105. conversions: {
  106. total: this.metrics.conversions.length,
  107. gpu: this.metrics.conversions.filter(c => c.usedGPU).length,
  108. cpu: this.metrics.conversions.filter(c => !c.usedGPU).length
  109. },
  110. system: {
  111. currentCPU: this.getCurrentCPU(),
  112. currentMemory: this.getCurrentMemory(),
  113. uptime: Date.now() - this.startTime
  114. }
  115. };
  116. }
  117. /**
  118. * Get current CPU usage percentage
  119. * @returns {string} CPU usage as formatted string
  120. */
  121. getCurrentCPU() {
  122. const latest = this.metrics.cpuSamples[this.metrics.cpuSamples.length - 1];
  123. return latest ? latest.usage.toFixed(1) : '0.0';
  124. }
  125. /**
  126. * Get current memory usage
  127. * @returns {Object} Memory usage in MB
  128. */
  129. getCurrentMemory() {
  130. const latest = this.metrics.memorySamples[this.metrics.memorySamples.length - 1];
  131. if (!latest) return { used: '0.0', total: '0.0' };
  132. return {
  133. used: (latest.heapUsed / 1024 / 1024).toFixed(1),
  134. total: (latest.heapTotal / 1024 / 1024).toFixed(1)
  135. };
  136. }
  137. /**
  138. * Get average CPU usage over recent samples
  139. * @param {number} samples - Number of recent samples to average (default 10)
  140. * @returns {number} Average CPU usage
  141. */
  142. getAverageCPU(samples = 10) {
  143. const recentSamples = this.metrics.cpuSamples.slice(-samples);
  144. if (recentSamples.length === 0) return 0;
  145. const sum = recentSamples.reduce((acc, sample) => acc + sample.usage, 0);
  146. return sum / recentSamples.length;
  147. }
  148. /**
  149. * Reset all metrics
  150. */
  151. reset() {
  152. this.metrics = {
  153. downloads: [],
  154. conversions: [],
  155. cpuSamples: [],
  156. memorySamples: []
  157. };
  158. this.startTime = Date.now();
  159. }
  160. /**
  161. * Stop monitoring and clean up resources
  162. */
  163. stop() {
  164. if (this.monitorInterval) {
  165. clearInterval(this.monitorInterval);
  166. this.monitorInterval = null;
  167. }
  168. }
  169. }
  170. module.exports = PerformanceMonitor;