UNPKG

memory-watch

Version:

Advanced Node.js memory monitoring with stack trace analysis, user code detection, and memory leak identification

178 lines (157 loc) • 5.24 kB
const { MemoryWatch, generateDiagnosticReport } = require("../dist/index"); // Simulate a real application scenario class UserService { constructor() { this.users = []; this.cache = new Map(); } async loadUsers() { console.log("šŸ“„ Loading users..."); // Simulate loading lots of users (this will show in stack trace) for (let i = 0; i < 1000; i++) { const user = { id: i, name: `User ${i}`, email: `user${i}@example.com`, profile: { bio: `This is a long biography for user ${i}`.repeat(10), preferences: new Array(50).fill(`pref-${i}`), history: new Array(100).fill({ action: `action-${i}`, timestamp: new Date(), data: new Array(20).fill(`data-${i}`), }), }, }; this.users.push(user); // Also cache the user (double memory usage!) this.cache.set(user.id, JSON.parse(JSON.stringify(user))); } console.log(`āœ… Loaded ${this.users.length} users`); return this.users; } processUserData() { console.log("āš™ļø Processing user data..."); // This function will appear in stack trace when memory spikes const processedData = this.users.map((user) => { return { ...user, processedProfile: { ...user.profile, extraData: new Array(100).fill(`processed-${user.id}`), analytics: { score: Math.random(), details: new Array(50).fill(`analytics-${user.id}`), }, }, }; }); console.log("šŸ“Š User data processed"); return processedData; } } class APIController { constructor() { this.userService = new UserService(); } async handleUserRequest() { console.log("🌐 API: Handling user request..."); // This will show up as the source of memory usage await this.userService.loadUsers(); const processed = this.userService.processUserData(); console.log("āœ… API: Request completed"); return processed; } } // Setup memory monitoring with low threshold const watch = new MemoryWatch({ threshold: 0.4, // 40% threshold interval: 2000, // Check every 2 seconds actions: [ (data) => { console.log("\n" + "🚨".repeat(20)); console.log("MEMORY ALERT - Real Application Scenario"); console.log("🚨".repeat(20)); console.log( `šŸ“Š Memory: ${(data.percentage * 100).toFixed(1)}% (${Math.round( data.usedBytes / 1024 / 1024 )}MB)` ); // Show user code in stack trace if (data.context?.stackTrace) { console.log("\nšŸ” STACK TRACE (Your Code):"); data.context.stackTrace.forEach((trace, index) => { // Highlight user code vs system code if ( trace.fileName && !trace.fileName.includes("node:") && !trace.fileName.includes("internal") ) { console.log( ` ${index + 1}. šŸŽÆ ${trace.functionName} → ${trace.fileName}:${ trace.lineNumber } ⭐` ); } else if (!trace.fileName?.includes("node:")) { console.log(` ${index + 1}. ${trace.functionName}`); } }); } console.log("\nšŸ’” ANALYSIS:"); if ( data.context?.stackTrace?.some((t) => t.functionName?.includes("loadUsers") ) ) { console.log(" • Memory spike detected in loadUsers function"); console.log(" • Possible cause: Loading too many users at once"); } if ( data.context?.stackTrace?.some((t) => t.functionName?.includes("processUserData") ) ) { console.log(" • Memory spike in processUserData function"); console.log(" • Possible cause: Creating too many processed objects"); } if ( data.context?.stackTrace?.some((t) => t.functionName?.includes("handleUserRequest") ) ) { console.log(" • Memory spike in API handler"); console.log(" • Possible cause: API processing large datasets"); } console.log("\nšŸ“‹ RECOMMENDATIONS:"); console.log(" • Implement pagination for user loading"); console.log(" • Use streaming for large datasets"); console.log(" • Clear cache periodically"); console.log(" • Consider database connection pooling"); console.log("🚨".repeat(20) + "\n"); }, ], }); async function runTest() { console.log("šŸš€ Starting Real Application Memory Test..."); console.log(" Simulating: User Service + API Controller"); console.log(" Threshold: 40%"); console.log(""); watch.start(); // Simulate real application flow const controller = new APIController(); // Start the memory-intensive operation setTimeout(async () => { try { await controller.handleUserRequest(); } catch (error) { console.error("Error in API:", error); } }, 1000); // Stop monitoring after 15 seconds setTimeout(() => { watch.stop(); console.log("āœ… Test completed - Memory monitoring stopped"); process.exit(0); }, 15000); } runTest();