From d9d9f01b37f94a8feb7dae1becf07cc9e8adb98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Thu, 8 Dec 2022 11:25:39 +0100 Subject: [PATCH] feat: add capability to write heap snapshot. (#2611) Is protected behind a config option called `enableHeapSnapshotEnpoint`. When API endpoint is triggered it will write a heapSnapshot to disk. Steps to create heap snapshot: 1. Add env variable `ENABLE_HEAP_SNAPSHOT_ENPOINT=true`. 2. Call this endpoint: `/internal-backstage/heapSnapshot` 3. Download the created heapdump from the server. The snapshot can be loaded in the chrome dev-tool to analysis. --- src/lib/__snapshots__/create-config.test.ts.snap | 1 + src/lib/create-config.ts | 4 ++++ src/lib/routes/backstage.ts | 9 +++++++++ src/lib/types/option.ts | 1 + src/server-dev.ts | 1 + 5 files changed, 16 insertions(+) diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index 1217e70830..3b70a4c0fb 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -126,6 +126,7 @@ exports[`should create default config 1`] = ` "server": { "baseUriPath": "", "cdnPrefix": undefined, + "enableHeapSnapshotEnpoint": false, "enableRequestLogger": false, "gracefulShutdownEnable": true, "gracefulShutdownTimeout": 1000, diff --git a/src/lib/create-config.ts b/src/lib/create-config.ts index 5bfc23fcb7..f891b6a00e 100644 --- a/src/lib/create-config.ts +++ b/src/lib/create-config.ts @@ -165,6 +165,10 @@ const defaultServerOption: IServerOption = { cdnPrefix: process.env.CDN_PREFIX, unleashUrl: process.env.UNLEASH_URL || 'http://localhost:4242', serverMetrics: true, + enableHeapSnapshotEnpoint: parseEnvVarBoolean( + process.env.ENABLE_HEAP_SNAPSHOT_ENPOINT, + false, + ), keepAliveTimeout: minutesToMilliseconds(1), headersTimeout: secondsToMilliseconds(61), enableRequestLogger: false, diff --git a/src/lib/routes/backstage.ts b/src/lib/routes/backstage.ts index 158349a12f..f4b4251d35 100644 --- a/src/lib/routes/backstage.ts +++ b/src/lib/routes/backstage.ts @@ -1,3 +1,4 @@ +import { writeHeapSnapshot } from 'v8'; import { register as prometheusRegister } from 'prom-client'; import Controller from './controller'; import { IUnleashConfig } from '../types/option'; @@ -16,6 +17,14 @@ class BackstageController extends Controller { res.end(await prometheusRegister.metrics()); }); } + + if (config.server.enableHeapSnapshotEnpoint) { + this.get('/heap-snapshot', async (req, res) => { + writeHeapSnapshot(); + res.status(200); + res.end('Snapshot written'); + }); + } } } diff --git a/src/lib/types/option.ts b/src/lib/types/option.ts index 5fae61338b..918286f4d3 100644 --- a/src/lib/types/option.ts +++ b/src/lib/types/option.ts @@ -79,6 +79,7 @@ export interface IServerOption { cdnPrefix?: string; unleashUrl: string; serverMetrics: boolean; + enableHeapSnapshotEnpoint: boolean; enableRequestLogger: boolean; gracefulShutdownEnable: boolean; gracefulShutdownTimeout: number; diff --git a/src/server-dev.ts b/src/server-dev.ts index c621d72064..0309571e2c 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -23,6 +23,7 @@ process.nextTick(async () => { // keepAliveTimeout: 1, gracefulShutdownEnable: true, // cdnPrefix: 'https://cdn.getunleash.io/unleash/v4.4.1', + enableHeapSnapshotEnpoint: true, }, logLevel: LogLevel.debug, enableOAS: true,