mastercontroller 1.2.11 → 1.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,188 @@
1
+ // version 1.0.0
2
+ // MasterController Memory Monitor - Memory Leak Detection
3
+
4
+ /**
5
+ * Memory monitor for detecting memory leaks
6
+ * - Heap usage tracking
7
+ * - Memory leak detection
8
+ * - Garbage collection monitoring
9
+ * - Memory alerts
10
+ */
11
+
12
+ const { logger } = require('./MasterErrorLogger');
13
+
14
+ class MasterMemoryMonitor {
15
+ constructor(options = {}) {
16
+ this.enabled = options.enabled !== false;
17
+ this.checkInterval = options.checkInterval || 30000; // 30 seconds
18
+ this.leakThreshold = options.leakThreshold || 50; // 50MB growth
19
+ this.alertThreshold = options.alertThreshold || 500; // 500MB
20
+
21
+ this.snapshots = [];
22
+ this.maxSnapshots = 100;
23
+ this.intervalId = null;
24
+ }
25
+
26
+ /**
27
+ * Start monitoring
28
+ */
29
+ start() {
30
+ if (!this.enabled || this.intervalId) return;
31
+
32
+ this.takeSnapshot();
33
+
34
+ this.intervalId = setInterval(() => {
35
+ this.takeSnapshot();
36
+ this.checkForLeaks();
37
+ }, this.checkInterval);
38
+
39
+ logger.info({
40
+ code: 'MC_MEMORY_MONITOR_START',
41
+ message: 'Memory monitoring started',
42
+ interval: `${this.checkInterval}ms`
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Stop monitoring
48
+ */
49
+ stop() {
50
+ if (this.intervalId) {
51
+ clearInterval(this.intervalId);
52
+ this.intervalId = null;
53
+
54
+ logger.info({
55
+ code: 'MC_MEMORY_MONITOR_STOP',
56
+ message: 'Memory monitoring stopped'
57
+ });
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Take memory snapshot
63
+ */
64
+ takeSnapshot() {
65
+ const usage = process.memoryUsage();
66
+
67
+ const snapshot = {
68
+ timestamp: Date.now(),
69
+ heapUsed: usage.heapUsed,
70
+ heapTotal: usage.heapTotal,
71
+ external: usage.external,
72
+ rss: usage.rss
73
+ };
74
+
75
+ this.snapshots.push(snapshot);
76
+
77
+ // Keep only last N snapshots
78
+ if (this.snapshots.length > this.maxSnapshots) {
79
+ this.snapshots.shift();
80
+ }
81
+
82
+ // Alert if memory usage is high
83
+ const heapUsedMB = usage.heapUsed / 1024 / 1024;
84
+ if (heapUsedMB > this.alertThreshold) {
85
+ logger.warn({
86
+ code: 'MC_MEMORY_HIGH',
87
+ message: 'High memory usage detected',
88
+ heapUsed: `${heapUsedMB.toFixed(2)} MB`,
89
+ threshold: `${this.alertThreshold} MB`
90
+ });
91
+ }
92
+
93
+ return snapshot;
94
+ }
95
+
96
+ /**
97
+ * Check for memory leaks
98
+ */
99
+ checkForLeaks() {
100
+ if (this.snapshots.length < 10) return;
101
+
102
+ // Compare first 5 and last 5 snapshots
103
+ const oldSnapshots = this.snapshots.slice(0, 5);
104
+ const newSnapshots = this.snapshots.slice(-5);
105
+
106
+ const oldAvg = oldSnapshots.reduce((sum, s) => sum + s.heapUsed, 0) / oldSnapshots.length;
107
+ const newAvg = newSnapshots.reduce((sum, s) => sum + s.heapUsed, 0) / newSnapshots.length;
108
+
109
+ const growthBytes = newAvg - oldAvg;
110
+ const growthMB = growthBytes / 1024 / 1024;
111
+
112
+ if (growthMB > this.leakThreshold) {
113
+ logger.warn({
114
+ code: 'MC_MEMORY_LEAK_DETECTED',
115
+ message: 'Potential memory leak detected',
116
+ growth: `${growthMB.toFixed(2)} MB`,
117
+ oldAvg: `${(oldAvg / 1024 / 1024).toFixed(2)} MB`,
118
+ newAvg: `${(newAvg / 1024 / 1024).toFixed(2)} MB`,
119
+ suggestion: 'Review component lifecycle and event listener cleanup'
120
+ });
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Get current memory usage
126
+ */
127
+ getCurrentUsage() {
128
+ const usage = process.memoryUsage();
129
+
130
+ return {
131
+ heapUsed: `${(usage.heapUsed / 1024 / 1024).toFixed(2)} MB`,
132
+ heapTotal: `${(usage.heapTotal / 1024 / 1024).toFixed(2)} MB`,
133
+ external: `${(usage.external / 1024 / 1024).toFixed(2)} MB`,
134
+ rss: `${(usage.rss / 1024 / 1024).toFixed(2)} MB`
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Print memory report
140
+ */
141
+ printReport() {
142
+ if (this.snapshots.length === 0) {
143
+ console.log('No memory snapshots available');
144
+ return;
145
+ }
146
+
147
+ const current = this.snapshots[this.snapshots.length - 1];
148
+ const first = this.snapshots[0];
149
+
150
+ const growth = current.heapUsed - first.heapUsed;
151
+ const growthPercent = (growth / first.heapUsed * 100).toFixed(2);
152
+
153
+ console.log('\n═══════════════════════════════════════════════════');
154
+ console.log('💾 MasterController Memory Report');
155
+ console.log('═══════════════════════════════════════════════════');
156
+
157
+ console.log('\nCurrent Usage:');
158
+ console.log(` Heap Used: ${(current.heapUsed / 1024 / 1024).toFixed(2)} MB`);
159
+ console.log(` Heap Total: ${(current.heapTotal / 1024 / 1024).toFixed(2)} MB`);
160
+ console.log(` External: ${(current.external / 1024 / 1024).toFixed(2)} MB`);
161
+ console.log(` RSS: ${(current.rss / 1024 / 1024).toFixed(2)} MB`);
162
+
163
+ console.log('\nMemory Growth:');
164
+ console.log(` Initial: ${(first.heapUsed / 1024 / 1024).toFixed(2)} MB`);
165
+ console.log(` Current: ${(current.heapUsed / 1024 / 1024).toFixed(2)} MB`);
166
+ console.log(` Growth: ${(growth / 1024 / 1024).toFixed(2)} MB (${growthPercent}%)`);
167
+
168
+ console.log(`\nSnapshots: ${this.snapshots.length}`);
169
+ console.log(`Duration: ${((current.timestamp - first.timestamp) / 1000 / 60).toFixed(2)} minutes`);
170
+
171
+ console.log('═══════════════════════════════════════════════════\n');
172
+ }
173
+ }
174
+
175
+ // Create singleton
176
+ const memoryMonitor = new MasterMemoryMonitor({
177
+ enabled: process.env.MC_MEMORY_MONITOR === 'true',
178
+ checkInterval: 30000,
179
+ leakThreshold: 50,
180
+ alertThreshold: 500
181
+ });
182
+
183
+ // Auto-start in development
184
+ if (process.env.NODE_ENV === 'development') {
185
+ memoryMonitor.start();
186
+ }
187
+
188
+ module.exports = { MasterMemoryMonitor, memoryMonitor };
@@ -0,0 +1,409 @@
1
+ // version 1.0.0
2
+ // MasterController Performance Profiler - Component and Request Profiling
3
+
4
+ /**
5
+ * Performance profiler for MasterController
6
+ * - Component render time tracking
7
+ * - Slow component detection
8
+ * - Request profiling
9
+ * - Performance bottleneck identification
10
+ * - Detailed performance reports
11
+ */
12
+
13
+ const { logger } = require('./MasterErrorLogger');
14
+
15
+ class MasterProfiler {
16
+ constructor(options = {}) {
17
+ this.enabled = options.enabled !== false;
18
+ this.slowThreshold = options.slowThreshold || 100; // 100ms
19
+ this.verySlowThreshold = options.verySlowThreshold || 500; // 500ms
20
+
21
+ // Performance data
22
+ this.componentMetrics = new Map();
23
+ this.requestMetrics = [];
24
+ this.currentRequest = null;
25
+
26
+ // Marks
27
+ this.marks = new Map();
28
+
29
+ // Statistics
30
+ this.totalComponents = 0;
31
+ this.slowComponents = 0;
32
+ this.verySlowComponents = 0;
33
+ }
34
+
35
+ /**
36
+ * Start profiling a component render
37
+ */
38
+ startComponentRender(componentName, props = {}) {
39
+ if (!this.enabled) return null;
40
+
41
+ const id = `${componentName}-${Date.now()}-${Math.random()}`;
42
+
43
+ this.mark(`${id}:start`);
44
+
45
+ return {
46
+ id,
47
+ componentName,
48
+ props,
49
+ startTime: Date.now()
50
+ };
51
+ }
52
+
53
+ /**
54
+ * End profiling a component render
55
+ */
56
+ endComponentRender(profile) {
57
+ if (!this.enabled || !profile) return;
58
+
59
+ this.mark(`${profile.id}:end`);
60
+
61
+ const duration = this.measure(
62
+ `${profile.id}:render`,
63
+ `${profile.id}:start`,
64
+ `${profile.id}:end`
65
+ );
66
+
67
+ // Store metrics
68
+ if (!this.componentMetrics.has(profile.componentName)) {
69
+ this.componentMetrics.set(profile.componentName, {
70
+ componentName: profile.componentName,
71
+ renders: [],
72
+ totalRenders: 0,
73
+ totalTime: 0,
74
+ avgTime: 0,
75
+ minTime: Infinity,
76
+ maxTime: 0,
77
+ slowRenders: 0,
78
+ verySlowRenders: 0
79
+ });
80
+ }
81
+
82
+ const metrics = this.componentMetrics.get(profile.componentName);
83
+ metrics.renders.push({
84
+ duration,
85
+ timestamp: profile.startTime,
86
+ props: profile.props
87
+ });
88
+
89
+ metrics.totalRenders++;
90
+ metrics.totalTime += duration;
91
+ metrics.avgTime = metrics.totalTime / metrics.totalRenders;
92
+ metrics.minTime = Math.min(metrics.minTime, duration);
93
+ metrics.maxTime = Math.max(metrics.maxTime, duration);
94
+
95
+ if (duration > this.slowThreshold) {
96
+ metrics.slowRenders++;
97
+ this.slowComponents++;
98
+
99
+ if (duration > this.verySlowThreshold) {
100
+ metrics.verySlowRenders++;
101
+ this.verySlowComponents++;
102
+
103
+ logger.warn({
104
+ code: 'MC_PERF_VERY_SLOW_COMPONENT',
105
+ message: `Very slow component render detected: ${profile.componentName}`,
106
+ duration: `${duration}ms`,
107
+ threshold: `${this.verySlowThreshold}ms`
108
+ });
109
+ }
110
+ }
111
+
112
+ this.totalComponents++;
113
+
114
+ // Keep only last 100 renders per component
115
+ if (metrics.renders.length > 100) {
116
+ metrics.renders.shift();
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Start profiling a request
122
+ */
123
+ startRequest(path, method = 'GET') {
124
+ if (!this.enabled) return null;
125
+
126
+ const id = `request-${Date.now()}-${Math.random()}`;
127
+
128
+ this.mark(`${id}:start`);
129
+
130
+ this.currentRequest = {
131
+ id,
132
+ path,
133
+ method,
134
+ startTime: Date.now(),
135
+ components: []
136
+ };
137
+
138
+ return this.currentRequest;
139
+ }
140
+
141
+ /**
142
+ * End profiling a request
143
+ */
144
+ endRequest(requestProfile) {
145
+ if (!this.enabled || !requestProfile) return;
146
+
147
+ this.mark(`${requestProfile.id}:end`);
148
+
149
+ const duration = this.measure(
150
+ `${requestProfile.id}:request`,
151
+ `${requestProfile.id}:start`,
152
+ `${requestProfile.id}:end`
153
+ );
154
+
155
+ requestProfile.duration = duration;
156
+ requestProfile.endTime = Date.now();
157
+
158
+ this.requestMetrics.push(requestProfile);
159
+
160
+ // Keep only last 1000 requests
161
+ if (this.requestMetrics.length > 1000) {
162
+ this.requestMetrics.shift();
163
+ }
164
+
165
+ // Log slow requests
166
+ if (duration > 1000) {
167
+ logger.warn({
168
+ code: 'MC_PERF_SLOW_REQUEST',
169
+ message: `Slow request detected: ${requestProfile.method} ${requestProfile.path}`,
170
+ duration: `${duration}ms`
171
+ });
172
+ }
173
+
174
+ this.currentRequest = null;
175
+ }
176
+
177
+ /**
178
+ * Create a performance mark
179
+ */
180
+ mark(name) {
181
+ if (!this.enabled) return;
182
+
183
+ this.marks.set(name, {
184
+ name,
185
+ timestamp: Date.now()
186
+ });
187
+ }
188
+
189
+ /**
190
+ * Measure duration between two marks
191
+ */
192
+ measure(name, startMark, endMark) {
193
+ if (!this.enabled) return 0;
194
+
195
+ const start = this.marks.get(startMark);
196
+ const end = this.marks.get(endMark);
197
+
198
+ if (!start || !end) {
199
+ return 0;
200
+ }
201
+
202
+ return end.timestamp - start.timestamp;
203
+ }
204
+
205
+ /**
206
+ * Get component performance metrics
207
+ */
208
+ getComponentMetrics(componentName = null) {
209
+ if (componentName) {
210
+ return this.componentMetrics.get(componentName) || null;
211
+ }
212
+
213
+ return Array.from(this.componentMetrics.values());
214
+ }
215
+
216
+ /**
217
+ * Get request performance metrics
218
+ */
219
+ getRequestMetrics(limit = 100) {
220
+ return this.requestMetrics.slice(-limit);
221
+ }
222
+
223
+ /**
224
+ * Get slow components
225
+ */
226
+ getSlowComponents(threshold = null) {
227
+ threshold = threshold || this.slowThreshold;
228
+
229
+ return Array.from(this.componentMetrics.values())
230
+ .filter(m => m.avgTime > threshold)
231
+ .sort((a, b) => b.avgTime - a.avgTime);
232
+ }
233
+
234
+ /**
235
+ * Get slow requests
236
+ */
237
+ getSlowRequests(threshold = 1000, limit = 100) {
238
+ return this.requestMetrics
239
+ .filter(r => r.duration > threshold)
240
+ .slice(-limit)
241
+ .sort((a, b) => b.duration - a.duration);
242
+ }
243
+
244
+ /**
245
+ * Generate performance report
246
+ */
247
+ generateReport() {
248
+ const components = this.getComponentMetrics();
249
+ const slowComponents = this.getSlowComponents();
250
+ const requests = this.getRequestMetrics();
251
+ const slowRequests = this.getSlowRequests();
252
+
253
+ // Calculate statistics
254
+ const totalRenderTime = components.reduce((sum, c) => sum + c.totalTime, 0);
255
+ const avgRenderTime = components.length > 0
256
+ ? totalRenderTime / components.reduce((sum, c) => sum + c.totalRenders, 0)
257
+ : 0;
258
+
259
+ const totalRequestTime = requests.reduce((sum, r) => sum + r.duration, 0);
260
+ const avgRequestTime = requests.length > 0 ? totalRequestTime / requests.length : 0;
261
+
262
+ return {
263
+ summary: {
264
+ totalComponents: this.totalComponents,
265
+ uniqueComponents: components.length,
266
+ slowComponents: this.slowComponents,
267
+ verySlowComponents: this.verySlowComponents,
268
+ totalRequests: requests.length,
269
+ slowRequests: slowRequests.length,
270
+ avgRenderTime: Math.round(avgRenderTime),
271
+ avgRequestTime: Math.round(avgRequestTime)
272
+ },
273
+ components: {
274
+ all: components,
275
+ slow: slowComponents.slice(0, 10)
276
+ },
277
+ requests: {
278
+ recent: requests.slice(-10),
279
+ slow: slowRequests.slice(0, 10)
280
+ }
281
+ };
282
+ }
283
+
284
+ /**
285
+ * Print performance report
286
+ */
287
+ printReport() {
288
+ const report = this.generateReport();
289
+
290
+ console.log('\n═══════════════════════════════════════════════════');
291
+ console.log('⚡ MasterController Performance Report');
292
+ console.log('═══════════════════════════════════════════════════');
293
+
294
+ console.log('\n📊 Summary:');
295
+ console.log(` Total Component Renders: ${report.summary.totalComponents}`);
296
+ console.log(` Unique Components: ${report.summary.uniqueComponents}`);
297
+ console.log(` Slow Components (>${this.slowThreshold}ms): ${report.summary.slowComponents}`);
298
+ console.log(` Very Slow Components (>${this.verySlowThreshold}ms): ${report.summary.verySlowComponents}`);
299
+ console.log(` Average Render Time: ${report.summary.avgRenderTime}ms`);
300
+ console.log(` Total Requests: ${report.summary.totalRequests}`);
301
+ console.log(` Slow Requests (>1000ms): ${report.summary.slowRequests}`);
302
+ console.log(` Average Request Time: ${report.summary.avgRequestTime}ms`);
303
+
304
+ if (report.components.slow.length > 0) {
305
+ console.log('\n🐌 Slowest Components:');
306
+ report.components.slow.forEach((comp, i) => {
307
+ console.log(` ${i + 1}. ${comp.componentName}`);
308
+ console.log(` Avg: ${Math.round(comp.avgTime)}ms | Max: ${Math.round(comp.maxTime)}ms | Renders: ${comp.totalRenders}`);
309
+ console.log(` Slow Renders: ${comp.slowRenders} | Very Slow: ${comp.verySlowRenders}`);
310
+ });
311
+ }
312
+
313
+ if (report.requests.slow.length > 0) {
314
+ console.log('\n🐌 Slowest Requests:');
315
+ report.requests.slow.forEach((req, i) => {
316
+ console.log(` ${i + 1}. ${req.method} ${req.path}`);
317
+ console.log(` Duration: ${Math.round(req.duration)}ms`);
318
+ });
319
+ }
320
+
321
+ console.log('\n💡 Recommendations:');
322
+ if (report.summary.verySlowComponents > 0) {
323
+ console.log(' ⚠️ Some components are very slow (>500ms)');
324
+ console.log(' - Consider code splitting');
325
+ console.log(' - Optimize expensive operations');
326
+ console.log(' - Use memoization for computed values');
327
+ }
328
+
329
+ if (report.summary.slowComponents > 10) {
330
+ console.log(' ⚠️ Many slow components detected');
331
+ console.log(' - Review component implementations');
332
+ console.log(' - Enable render caching');
333
+ console.log(' - Consider lazy loading');
334
+ }
335
+
336
+ if (report.summary.slowRequests > 5) {
337
+ console.log(' ⚠️ Multiple slow requests detected');
338
+ console.log(' - Review database queries');
339
+ console.log(' - Add caching');
340
+ console.log(' - Optimize expensive operations');
341
+ }
342
+
343
+ console.log('═══════════════════════════════════════════════════\n');
344
+
345
+ return report;
346
+ }
347
+
348
+ /**
349
+ * Reset profiler
350
+ */
351
+ reset() {
352
+ this.componentMetrics.clear();
353
+ this.requestMetrics = [];
354
+ this.marks.clear();
355
+ this.totalComponents = 0;
356
+ this.slowComponents = 0;
357
+ this.verySlowComponents = 0;
358
+ this.currentRequest = null;
359
+
360
+ logger.info({
361
+ code: 'MC_PERF_RESET',
362
+ message: 'Profiler reset'
363
+ });
364
+ }
365
+
366
+ /**
367
+ * Enable profiler
368
+ */
369
+ enable() {
370
+ this.enabled = true;
371
+ logger.info({
372
+ code: 'MC_PERF_ENABLED',
373
+ message: 'Profiler enabled'
374
+ });
375
+ }
376
+
377
+ /**
378
+ * Disable profiler
379
+ */
380
+ disable() {
381
+ this.enabled = false;
382
+ logger.info({
383
+ code: 'MC_PERF_DISABLED',
384
+ message: 'Profiler disabled'
385
+ });
386
+ }
387
+ }
388
+
389
+ // Create singleton instance
390
+ const profiler = new MasterProfiler({
391
+ enabled: process.env.NODE_ENV === 'development' || process.env.MC_PROFILER_ENABLED === 'true',
392
+ slowThreshold: parseInt(process.env.MC_SLOW_THRESHOLD) || 100,
393
+ verySlowThreshold: parseInt(process.env.MC_VERY_SLOW_THRESHOLD) || 500
394
+ });
395
+
396
+ // Auto-print report every 5 minutes in development
397
+ if (process.env.NODE_ENV === 'development') {
398
+ setInterval(() => {
399
+ const report = profiler.generateReport();
400
+ if (report.summary.totalComponents > 0) {
401
+ profiler.printReport();
402
+ }
403
+ }, 300000); // 5 minutes
404
+ }
405
+
406
+ module.exports = {
407
+ MasterProfiler,
408
+ profiler
409
+ };