diff --git a/public/language/en-GB/admin/development/info.json b/public/language/en-GB/admin/development/info.json index 9834719daf..40e8fded15 100644 --- a/public/language/en-GB/admin/development/info.json +++ b/public/language/en-GB/admin/development/info.json @@ -22,5 +22,6 @@ "connection-count": "Connection Count", "guests": "Guests", - "info": "Info" + "info": "Info", + "heap-dump": "Heap Dump" } \ No newline at end of file diff --git a/public/openapi/read.yaml b/public/openapi/read.yaml index 3ec355bd95..9228ba9c7d 100644 --- a/public/openapi/read.yaml +++ b/public/openapi/read.yaml @@ -174,6 +174,8 @@ paths: $ref: 'read/admin/advanced/cache.yaml' /api/admin/advanced/cache/dump: $ref: 'read/admin/advanced/cache/dump.yaml' + /api/admin/advanced/heap/dump: + $ref: 'read/admin/advanced/heap/dump.yaml' /api/admin/development/logger: $ref: 'read/admin/development/logger.yaml' /api/admin/development/info: diff --git a/public/openapi/read/admin/advanced/heap/dump.yaml b/public/openapi/read/admin/advanced/heap/dump.yaml new file mode 100644 index 0000000000..2c0465eed4 --- /dev/null +++ b/public/openapi/read/admin/advanced/heap/dump.yaml @@ -0,0 +1,18 @@ +get: + tags: + - admin + summary: Get nodejs heap snapshot + description: Downloads a Node.js heap snapshot for memory analysis. + parameters: [] + responses: + "200": + description: Heap snapshot file (in .heapsnapshot format) + content: + application/octet-stream: + schema: + type: string + format: binary + examples: + heapSnapshot: + summary: Example Heap Snapshot Download + description: A binary heap snapshot file. diff --git a/src/controllers/admin/info.js b/src/controllers/admin/info.js index 6f63faf8a9..d50af63ebf 100644 --- a/src/controllers/admin/info.js +++ b/src/controllers/admin/info.js @@ -143,3 +143,21 @@ async function getGitInfo() { ]); return { hash: hash, hashShort: hash.slice(0, 6), branch: branch }; } + +infoController.getHeapdump = async function (req, res) { + const v8 = require('v8'); + const path = require('path'); + const fs = require('fs'); + const filename = path.join(nconf.get('upload_path'), `heapdump-${Date.now()}.heapsnapshot`); + const stored = v8.writeHeapSnapshot(filename, {}); + res.download(stored, 'heapdump.heapsnapshot', (err) => { + if (err) { + winston.error(err.stack); + } + fs.unlink(stored, (unlinkErr) => { + if (unlinkErr) { + winston.error(unlinkErr.stack); + } + }); + }); +}; \ No newline at end of file diff --git a/src/routes/admin.js b/src/routes/admin.js index b7e751695c..94ba8e9e02 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -81,6 +81,7 @@ function apiRoutes(router, name, middleware, controllers) { router.get(`/api/${name}/groups/:groupname/csv`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.groups.getCSV)); router.get(`/api/${name}/analytics`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.getAnalytics)); router.get(`/api/${name}/advanced/cache/dump`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.cache.dump)); + router.get(`/api/${name}/advanced/heap/dump`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.info.getHeapdump)); const multer = require('multer'); const storage = multer.diskStorage({}); diff --git a/src/views/admin/development/info.tpl b/src/views/admin/development/info.tpl index 493e16ac93..49301f3543 100644 --- a/src/views/admin/development/info.tpl +++ b/src/views/admin/development/info.tpl @@ -5,7 +5,12 @@