diff --git a/packages/hydrooj/src/handler/misc.ts b/packages/hydrooj/src/handler/misc.ts index 14899654e..327ac4dfb 100644 --- a/packages/hydrooj/src/handler/misc.ts +++ b/packages/hydrooj/src/handler/misc.ts @@ -1,3 +1,4 @@ +import { writeHeapSnapshot } from 'v8'; import { pick } from 'lodash'; import { lookup } from 'mime-types'; import { Context } from '../context'; @@ -139,10 +140,28 @@ export class SwitchAccountHandler extends Handler { } } +class HeapSnapshotHandler extends Handler { + @param('worker', Types.Int) + async post({ }, worker: number) { + this.checkPriv(PRIV.PRIV_EDIT_SYSTEM); + if (worker && process.env.NODE_APP_INSTANCE !== worker.toString()) { + this.response.body = { error: 'Not current worker' }; + return; + } + this.response.body = { + worker: process.env.NODE_APP_INSTANCE, + filename: writeHeapSnapshot(), + }; + } +} + export async function apply(ctx: Context) { ctx.Route('switch_language', '/language/:lang', SwitchLanguageHandler); ctx.Route('home_files', '/file', FilesHandler); ctx.Route('fs_download', '/file/:uid/:filename', FSDownloadHandler); ctx.Route('storage', '/storage', StorageHandler); ctx.Route('switch_account', '/account/:uid', SwitchAccountHandler, PRIV.PRIV_EDIT_SYSTEM); + if (process.argv.includes('--enable-heap-snapshot')) { + ctx.Route('heap_snapshot', '/heap-snapshot', HeapSnapshotHandler, PRIV.PRIV_EDIT_SYSTEM); + } } diff --git a/packages/hydrooj/src/service/check.ts b/packages/hydrooj/src/service/check.ts index 119c98ae2..002eacffc 100644 --- a/packages/hydrooj/src/service/check.ts +++ b/packages/hydrooj/src/service/check.ts @@ -2,6 +2,7 @@ import os from 'os'; import { DisposableList } from 'cordis'; +import inspector from 'inspector'; import { randomstring } from '@hydrooj/utils'; import { Context, Service } from '../context'; import * as system from '../model/system'; @@ -49,6 +50,10 @@ export default class CheckService extends Service { const header = system.get('server.xff'); if (header && !c.request.ip) warn('IP header seems incorrect.\nCheck dashboard>settings>server.'); }); + this.addChecker('Inspector', async (c, log, warn) => { + const url = inspector.url(); + if (url) warn(`Inspector is enabled at ${url}.`); + }); } addChecker(type: string, checkFunc: CheckItem) {