diff --git a/meshcentral.js b/meshcentral.js index 368df183..b3319b0a 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -2459,6 +2459,10 @@ function mainStart() { if (allsspi == false) { modules.push('otplib@10.2.3'); } // Google Authenticator support (v10 supports older NodeJS versions). } + // Setup heapdump support if needed, useful for memory leak debugging + // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ + if (config.settings.heapdump === true) { modules.push('heapdump'); } + // Install any missing modules and launch the server InstallModules(modules, function () { meshserver = CreateMeshCentralServer(config, args); meshserver.Start(); }); diff --git a/meshuser.js b/meshuser.js index 8fc7b61e..9baffa45 100644 --- a/meshuser.js +++ b/meshuser.js @@ -690,6 +690,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use switch (cmd) { case 'help': { var fin = '', f = '', availcommands = 'help,info,versions,args,resetserver,showconfig,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats'; + if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } @@ -699,6 +700,20 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use r = 'Available commands: \r\n' + fin + '.'; break; } + case 'heapdump': { + // Heapdump support, see example at: + // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ + if (parent.parent.config.settings.heapdump === true) { + var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`); + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { } + require('heapdump').writeSnapshot(dumpFileName, (err, filename) => { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { } + }); + } else { + r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json."; + } + break; + } case 'le': { if (parent.parent.letsencrypt == null) { r = "Let's Encrypt not in use.";