diff --git a/utilities/server.js b/utilities/server.js index 661ef081c..225db88f4 100644 --- a/utilities/server.js +++ b/utilities/server.js @@ -1,14 +1,15 @@ -var sourcemapsReaderServer = require('./servers/sourcemaps-server'); -var {peerRouter, peerConnection, peerDisconnect, peerError} = require('./servers/peerjs-server'); -var express = require('express'); +const dumps = require('./utils/dump'); +const sourcemapsReaderServer = require('./servers/sourcemaps-server'); +const {peerRouter, peerConnection, peerDisconnect, peerError} = require('./servers/peerjs-server'); +const express = require('express'); const {ExpressPeerServer} = require('peer'); const socket = require("./servers/websocket"); const HOST = '0.0.0.0'; const PORT = 9000; -var app = express(); -var wsapp = express(); +const app = express(); +const wsapp = express(); let debug = process.env.debug === "1" || false; const request_logger = (identity) => { return (req, res, next) => { @@ -29,6 +30,13 @@ app.use('/sourcemaps', sourcemapsReaderServer); app.use('/assist', peerRouter); wsapp.use('/assist', socket.wsRouter); +app.get('/heapdump', dumps.sendHeapSnapshot); +app.get('/heapdump/save', dumps.saveHeapSnapshot); +wsapp.get('/heapdump', dumps.sendHeapSnapshot); +wsapp.get('/heapdump/save', dumps.saveHeapSnapshot); + +console.log(`Heapdump enabled. Send a request to "/heapdump" to download a heapdump,\nor "/heapdump/save" to only generate a heapdump.`); + const server = app.listen(PORT, HOST, () => { console.log(`App listening on http://${HOST}:${PORT}`); console.log('Press Ctrl+C to quit.'); diff --git a/utilities/utils/dump.js b/utilities/utils/dump.js new file mode 100644 index 000000000..c22cffc3d --- /dev/null +++ b/utilities/utils/dump.js @@ -0,0 +1,50 @@ +const fs = require('fs'); +const v8 = require('v8'); + +const location = '/tmp/'; + +async function createHeapSnapshot() { + const fileName = `${Date.now()}.heapsnapshot`; + await fs.promises.writeFile( + location + fileName, + v8.getHeapSnapshot() + ); + return fileName; +} + + +async function sendHeapSnapshot(req, res) { + const fileName = await createHeapSnapshot(); + const file = fs.readFileSync(location + fileName, 'binary'); + const stat = fs.statSync(location + fileName); + + res.setHeader('Content-Length', stat.size); + res.setHeader('Content-Type', 'audio/mpeg'); + res.setHeader('Content-Disposition', 'attachment; filename=' + fileName); + res.write(file, 'binary'); + res.end(); + try { + fs.unlinkSync(location + fileName) + } catch (err) { + console.error("error while deleting heapsnapshot file"); + console.error(err); + } +} + +process.on('USR2', () => { + console.info('USR2 signal received.'); +}); + +async function saveHeapSnapshot(req, res) { + const fileName = await createHeapSnapshot(); + const path = location + fileName; + console.log(`Heapdump saved to ${path}`) + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({path})); +} + +process.on('USR2', () => { + console.info('USR2 signal received.'); +}); +module.exports = {sendHeapSnapshot, saveHeapSnapshot} \ No newline at end of file