mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	chore: startup investigation
This commit is contained in:
		
							parent
							
								
									c7cb5465ff
								
							
						
					
					
						commit
						c76e67720a
					
				@ -40,7 +40,7 @@
 | 
			
		||||
    "build:frontend:if-needed": "./scripts/build-frontend-if-needed.sh",
 | 
			
		||||
    "build": "yarn run clean && concurrently \"yarn:copy-templates\" \"yarn:build:frontend\" \"yarn:build:backend\"",
 | 
			
		||||
    "dev:vite": "TZ=UTC NODE_ENV=development vite-node src/server-dev.ts",
 | 
			
		||||
    "dev:backend": "TZ=UTC NODE_ENV=${NODE_ENV:-development} tsc-watch --onEmit \"copyfiles -u 2 src/migrations/package.json dist/migrations\" --onSuccess \"node dist/server-dev.js\"",
 | 
			
		||||
    "dev:backend": "TZ=UTC NODE_ENV=${NODE_ENV:-development} NODE_OPTIONS=\"--enable-source-maps --import file:///${PWD}/dist/startup-profiler.js\" tsc-watch --onEmit \"copyfiles -u 2 src/migrations/package.json dist/migrations\" --onSuccess \"node dist/server-dev.js\"",
 | 
			
		||||
    "dev:frontend": "wait-on tcp:4242 && yarn --cwd ./frontend run dev",
 | 
			
		||||
    "dev:frontend:cloud": "UNLEASH_BASE_PATH=/demo/ yarn run dev:frontend",
 | 
			
		||||
    "dev": "concurrently \"yarn:dev:backend\" \"yarn:dev:frontend\"",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										669
									
								
								src/startup-profiler.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										669
									
								
								src/startup-profiler.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,669 @@
 | 
			
		||||
// ESM Startup Profiler (TypeScript)
 | 
			
		||||
// Run with: NODE_OPTIONS="--import file://$PWD/dist/profiling/startup-profiler.mjs" node dist/server.js
 | 
			
		||||
import fs from 'node:fs';
 | 
			
		||||
import path from 'node:path';
 | 
			
		||||
import http from 'node:http';
 | 
			
		||||
import https from 'node:https';
 | 
			
		||||
import { performance } from 'node:perf_hooks';
 | 
			
		||||
import async_hooks from 'node:async_hooks';
 | 
			
		||||
import inspector from 'node:inspector';
 | 
			
		||||
import Module from 'node:module';
 | 
			
		||||
 | 
			
		||||
// -------------------- config --------------------
 | 
			
		||||
const THRESHOLD_MS = Number(process.env.STARTUP_PROFILER_SLOW ?? 15);
 | 
			
		||||
const REPORT_TXT = path.resolve(
 | 
			
		||||
    process.cwd(),
 | 
			
		||||
    process.env.STARTUP_PROFILER_TXT ?? 'startup-report.txt',
 | 
			
		||||
);
 | 
			
		||||
const TRACE_JSON = path.resolve(
 | 
			
		||||
    process.cwd(),
 | 
			
		||||
    process.env.STARTUP_PROFILER_TRACE ?? 'startup-trace.json',
 | 
			
		||||
);
 | 
			
		||||
const CPU_PROFILE = path.resolve(
 | 
			
		||||
    process.cwd(),
 | 
			
		||||
    process.env.STARTUP_CPU_PROFILE ?? 'startup-cpu.cpuprofile',
 | 
			
		||||
);
 | 
			
		||||
const STACK_FRAMES = Number(process.env.STARTUP_STACK_FRAMES ?? 6);
 | 
			
		||||
// Additional tuning knobs
 | 
			
		||||
const MODULE_LOAD_THRESHOLD = Number(process.env.STARTUP_MODULE_THRESHOLD ?? 5); // ms for reporting slow module loads
 | 
			
		||||
const ENABLE_PROMISE_STACK_GROUPING = Boolean(
 | 
			
		||||
    (process.env.STARTUP_GROUP_PROMISE_STACK ?? '1') !== '0',
 | 
			
		||||
);
 | 
			
		||||
const MAX_PROMISE_STACKS = Number(process.env.STARTUP_MAX_PROMISE_STACKS ?? 30);
 | 
			
		||||
const CAPTURE_MODULE_STACK = Boolean(
 | 
			
		||||
    (process.env.STARTUP_MODULE_STACK ?? '1') !== '0',
 | 
			
		||||
);
 | 
			
		||||
const MIGRATIONS_KEYWORD =
 | 
			
		||||
    process.env.STARTUP_MIGRATIONS_KEYWORD ?? '/migrations';
 | 
			
		||||
 | 
			
		||||
// -------------------- trace helpers (Chrome trace) --------------------
 | 
			
		||||
Error.stackTraceLimit = 50;
 | 
			
		||||
type TraceEvt =
 | 
			
		||||
    | {
 | 
			
		||||
          name: string;
 | 
			
		||||
          cat: string;
 | 
			
		||||
          ph: 'B' | 'E';
 | 
			
		||||
          ts: number;
 | 
			
		||||
          pid: number;
 | 
			
		||||
          tid: number;
 | 
			
		||||
          args?: Record<string, unknown>;
 | 
			
		||||
      }
 | 
			
		||||
    | {
 | 
			
		||||
          name: string;
 | 
			
		||||
          cat: string;
 | 
			
		||||
          ph: 'i';
 | 
			
		||||
          s: 't';
 | 
			
		||||
          ts: number;
 | 
			
		||||
          pid: number;
 | 
			
		||||
          tid: number;
 | 
			
		||||
          args?: Record<string, unknown>;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
const traceEvents: TraceEvt[] = [];
 | 
			
		||||
function tsNowUs() {
 | 
			
		||||
    return (performance.timeOrigin + performance.now()) * 1000;
 | 
			
		||||
}
 | 
			
		||||
function traceBegin(
 | 
			
		||||
    name: string,
 | 
			
		||||
    cat = 'startup',
 | 
			
		||||
    args: Record<string, unknown> = {},
 | 
			
		||||
) {
 | 
			
		||||
    traceEvents.push({
 | 
			
		||||
        name,
 | 
			
		||||
        cat,
 | 
			
		||||
        ph: 'B',
 | 
			
		||||
        ts: tsNowUs(),
 | 
			
		||||
        pid: process.pid,
 | 
			
		||||
        tid: 0,
 | 
			
		||||
        args,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
function traceEnd(
 | 
			
		||||
    name: string,
 | 
			
		||||
    cat = 'startup',
 | 
			
		||||
    args: Record<string, unknown> = {},
 | 
			
		||||
) {
 | 
			
		||||
    traceEvents.push({
 | 
			
		||||
        name,
 | 
			
		||||
        cat,
 | 
			
		||||
        ph: 'E',
 | 
			
		||||
        ts: tsNowUs(),
 | 
			
		||||
        pid: process.pid,
 | 
			
		||||
        tid: 0,
 | 
			
		||||
        args,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
function traceInstant(
 | 
			
		||||
    name: string,
 | 
			
		||||
    cat = 'startup',
 | 
			
		||||
    args: Record<string, unknown> = {},
 | 
			
		||||
) {
 | 
			
		||||
    traceEvents.push({
 | 
			
		||||
        name,
 | 
			
		||||
        cat,
 | 
			
		||||
        ph: 'i',
 | 
			
		||||
        s: 't',
 | 
			
		||||
        ts: tsNowUs(),
 | 
			
		||||
        pid: process.pid,
 | 
			
		||||
        tid: 0,
 | 
			
		||||
        args,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
traceInstant('process_start');
 | 
			
		||||
 | 
			
		||||
// -------------------- label context --------------------
 | 
			
		||||
// We attribute async work to *who scheduled it* via a label carried on the async tree.
 | 
			
		||||
type Ctx = { label: string; stack?: string[] };
 | 
			
		||||
const ctxLabel = new Map<number, Ctx>(); // executionAsyncId -> ctx
 | 
			
		||||
const parentOf = new Map<number, number>(); // child asyncId -> parent asyncId
 | 
			
		||||
 | 
			
		||||
function cleanStack(max = STACK_FRAMES): string[] | undefined {
 | 
			
		||||
    const raw = (new Error().stack ?? '').split('\n').slice(2);
 | 
			
		||||
    const user = raw
 | 
			
		||||
        .map((l) => l.trim())
 | 
			
		||||
        .filter(
 | 
			
		||||
            (l) =>
 | 
			
		||||
                !/(node:internal|\/async_hooks|\/perf_hooks|\/inspector|startup-profiler)/.test(
 | 
			
		||||
                    l,
 | 
			
		||||
                ),
 | 
			
		||||
        )
 | 
			
		||||
        .map((l) => l.replace(`${process.cwd()}/`, ''))
 | 
			
		||||
        .slice(0, max);
 | 
			
		||||
    return user.length ? user : undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function stackSignature(stack?: string[]): string | undefined {
 | 
			
		||||
    if (!stack || !stack.length) return undefined;
 | 
			
		||||
    return stack
 | 
			
		||||
        .slice(0, 4)
 | 
			
		||||
        .map((f) => f.replace(/:\d+:\d+\)?$/, ')').replace(/\s+/g, ' '))
 | 
			
		||||
        .join(' | ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setLabelForCurrent(label: string) {
 | 
			
		||||
    const id = async_hooks.executionAsyncId();
 | 
			
		||||
    ctxLabel.set(id, { label, stack: cleanStack() });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resolveLabelFrom(triggerId?: number): Ctx | undefined {
 | 
			
		||||
    let t = triggerId;
 | 
			
		||||
    let hops = 0;
 | 
			
		||||
    while (typeof t === 'number' && hops < 100) {
 | 
			
		||||
        const ctx = ctxLabel.get(t);
 | 
			
		||||
        if (ctx) return ctx;
 | 
			
		||||
        t = parentOf.get(t);
 | 
			
		||||
        hops++;
 | 
			
		||||
    }
 | 
			
		||||
    return undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------------- wrap listen() to mark startup end --------------------
 | 
			
		||||
const START = performance.now();
 | 
			
		||||
let END: number | null = null;
 | 
			
		||||
let listenTarget: {
 | 
			
		||||
    proto: 'http' | 'https';
 | 
			
		||||
    address: string | null;
 | 
			
		||||
    port: number | null;
 | 
			
		||||
} | null = null;
 | 
			
		||||
 | 
			
		||||
function wrapListen(
 | 
			
		||||
    proto: 'http' | 'https',
 | 
			
		||||
    Cls: typeof http.Server | typeof https.Server,
 | 
			
		||||
) {
 | 
			
		||||
    const orig = (Cls as any).prototype.listen as http.Server['listen'];
 | 
			
		||||
    (Cls as any).prototype.listen = function (...args: any[]) {
 | 
			
		||||
        const res = orig.apply(this, args as any);
 | 
			
		||||
        const onListening = () => {
 | 
			
		||||
            if (END) return;
 | 
			
		||||
            END = performance.now();
 | 
			
		||||
            try {
 | 
			
		||||
                this.removeListener('listening', onListening);
 | 
			
		||||
            } catch {}
 | 
			
		||||
            const addr = this.address() as any;
 | 
			
		||||
            listenTarget = {
 | 
			
		||||
                proto,
 | 
			
		||||
                address:
 | 
			
		||||
                    typeof addr === 'string' ? addr : (addr?.address ?? null),
 | 
			
		||||
                port: typeof addr === 'string' ? null : (addr?.port ?? null),
 | 
			
		||||
            };
 | 
			
		||||
            finalize();
 | 
			
		||||
        };
 | 
			
		||||
        this.on('listening', onListening);
 | 
			
		||||
        traceInstant(`listen_called:${proto}`, 'listen', {
 | 
			
		||||
            args: summarizeListenArgs(args),
 | 
			
		||||
        });
 | 
			
		||||
        return res;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
function summarizeListenArgs(args: any[]) {
 | 
			
		||||
    const out: Record<string, unknown> = {};
 | 
			
		||||
    for (const a of args) {
 | 
			
		||||
        if (typeof a === 'number') out.port = a;
 | 
			
		||||
        else if (typeof a === 'string') out.hostOrPath = a;
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
wrapListen('http', http.Server);
 | 
			
		||||
wrapListen('https', https.Server);
 | 
			
		||||
 | 
			
		||||
// Safety net when no server listens (CLIs, failed boots)
 | 
			
		||||
process.on('beforeExit', () => {
 | 
			
		||||
    if (!END) {
 | 
			
		||||
        END = performance.now();
 | 
			
		||||
        finalize(true);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// -------------------- patch common async APIs (so we can label) --------------------
 | 
			
		||||
const g: any = globalThis;
 | 
			
		||||
 | 
			
		||||
// fetch (undici)
 | 
			
		||||
if (typeof g.fetch === 'function') {
 | 
			
		||||
    const origFetch = g.fetch.bind(g);
 | 
			
		||||
    g.fetch = async (...args: any[]) => {
 | 
			
		||||
        const url =
 | 
			
		||||
            typeof args[0] === 'string' ? args[0] : (args[0]?.url ?? '');
 | 
			
		||||
        setLabelForCurrent(`fetch ${url}`);
 | 
			
		||||
        traceBegin(`fetch:${url}`, 'net');
 | 
			
		||||
        try {
 | 
			
		||||
            return await origFetch(...args);
 | 
			
		||||
        } finally {
 | 
			
		||||
            traceEnd(`fetch:${url}`, 'net');
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// timers
 | 
			
		||||
for (const name of ['setTimeout', 'setImmediate'] as const) {
 | 
			
		||||
    const orig = (g as any)[name].bind(g);
 | 
			
		||||
    (g as any)[name] = (fn: Function, ...rest: any[]) => {
 | 
			
		||||
        setLabelForCurrent(name);
 | 
			
		||||
        return orig(fn, ...rest);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// (Optional) add wrappers for SDK init you suspect:
 | 
			
		||||
// e.g. before prisma.connect() / otel.start() / redis.connect(), call setLabelForCurrent('prisma.connect').
 | 
			
		||||
 | 
			
		||||
// -------------------- async_hooks: timing + label inheritance --------------------
 | 
			
		||||
type Rec = { type: string; start: number; ctx?: Ctx };
 | 
			
		||||
const asyncMap = new Map<number, Rec>();
 | 
			
		||||
 | 
			
		||||
const metrics = {
 | 
			
		||||
    async: { total: 0, time: 0, byType: new Map<string, number>() },
 | 
			
		||||
};
 | 
			
		||||
const slow: Array<{
 | 
			
		||||
    type: string;
 | 
			
		||||
    ms: number;
 | 
			
		||||
    id: number;
 | 
			
		||||
    label?: string;
 | 
			
		||||
    stack?: string[];
 | 
			
		||||
}> = [];
 | 
			
		||||
 | 
			
		||||
// Promise stack aggregation
 | 
			
		||||
interface PromiseStackAgg {
 | 
			
		||||
    time: number;
 | 
			
		||||
    count: number;
 | 
			
		||||
    stack?: string[];
 | 
			
		||||
    label?: string;
 | 
			
		||||
}
 | 
			
		||||
const promiseStacks = new Map<string, PromiseStackAgg>();
 | 
			
		||||
 | 
			
		||||
// Module load timing records
 | 
			
		||||
interface ModuleLoadRec {
 | 
			
		||||
    request: string;
 | 
			
		||||
    parent?: string;
 | 
			
		||||
    ms: number;
 | 
			
		||||
    stack?: string[];
 | 
			
		||||
}
 | 
			
		||||
const moduleLoads: ModuleLoadRec[] = [];
 | 
			
		||||
 | 
			
		||||
const _load = (Module as any)._load as (
 | 
			
		||||
    req: string,
 | 
			
		||||
    parent: any,
 | 
			
		||||
    isMain: boolean,
 | 
			
		||||
) => any;
 | 
			
		||||
(Module as any)._load = function (req: string, parent: any, isMain: boolean) {
 | 
			
		||||
    const modStart = performance.now();
 | 
			
		||||
    const stack = CAPTURE_MODULE_STACK ? cleanStack(6) : undefined;
 | 
			
		||||
    // biome-ignore lint/style/noArguments: preserve args
 | 
			
		||||
    const mod = _load.apply(this, arguments as any);
 | 
			
		||||
    const dt = performance.now() - modStart;
 | 
			
		||||
    if (!END && dt >= MODULE_LOAD_THRESHOLD) {
 | 
			
		||||
        moduleLoads.push({
 | 
			
		||||
            request: req,
 | 
			
		||||
            parent: parent?.filename,
 | 
			
		||||
            ms: dt,
 | 
			
		||||
            stack,
 | 
			
		||||
        });
 | 
			
		||||
        traceInstant('module_load', 'module', { req, ms: dt });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (req === 'db-migrate' && mod && !(mod as any).__startupPatched) {
 | 
			
		||||
        (mod as any).__startupPatched = true;
 | 
			
		||||
        const origGetInstance = (mod as any).getInstance?.bind(mod);
 | 
			
		||||
        if (origGetInstance) {
 | 
			
		||||
            (mod as any).getInstance = (...args: any[]) => {
 | 
			
		||||
                const inst = origGetInstance(...args);
 | 
			
		||||
                for (const m of [
 | 
			
		||||
                    'up',
 | 
			
		||||
                    'down',
 | 
			
		||||
                    'reset',
 | 
			
		||||
                    'sync',
 | 
			
		||||
                    'connect',
 | 
			
		||||
                ] as const) {
 | 
			
		||||
                    const fn = (inst as any)[m];
 | 
			
		||||
                    if (typeof fn === 'function') {
 | 
			
		||||
                        (inst as any)[m] = async function (...fa: any[]) {
 | 
			
		||||
                            setLabelForCurrent(`db-migrate ${m}`);
 | 
			
		||||
                            traceBegin(`db-migrate:${m}`, 'db');
 | 
			
		||||
                            try {
 | 
			
		||||
                                return await fn.apply(this, fa);
 | 
			
		||||
                            } finally {
 | 
			
		||||
                                traceEnd(`db-migrate:${m}`, 'db');
 | 
			
		||||
                            }
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return inst;
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (req === 'pg' && mod && !(mod as any).__startupPatched) {
 | 
			
		||||
        (mod as any).__startupPatched = true;
 | 
			
		||||
        try {
 | 
			
		||||
            const { Client, Pool } = mod as any;
 | 
			
		||||
            if (Client?.prototype?.connect) {
 | 
			
		||||
                const orig = Client.prototype.connect;
 | 
			
		||||
                Client.prototype.connect = function (...fa: any[]) {
 | 
			
		||||
                    setLabelForCurrent('pg.connect');
 | 
			
		||||
                    return orig.apply(this, fa);
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            if (Pool?.prototype?.connect) {
 | 
			
		||||
                const origP = Pool.prototype.connect;
 | 
			
		||||
                Pool.prototype.connect = function (...fa: any[]) {
 | 
			
		||||
                    setLabelForCurrent('pg.pool.connect');
 | 
			
		||||
                    return origP.apply(this, fa);
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        } catch {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return mod;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Patch CJS compilation to surface big parse/transform cost
 | 
			
		||||
const exts = Module as any;
 | 
			
		||||
if (exts?._extensions) {
 | 
			
		||||
    for (const [ext, loader] of Object.entries<any>(exts._extensions)) {
 | 
			
		||||
        if (typeof loader !== 'function') continue;
 | 
			
		||||
        if ((loader as any).__startupPatched) continue;
 | 
			
		||||
        exts._extensions[ext] = (m: any, filename: string) => {
 | 
			
		||||
            const start = performance.now();
 | 
			
		||||
            try {
 | 
			
		||||
                return loader(m, filename);
 | 
			
		||||
            } finally {
 | 
			
		||||
                const dt2 = performance.now() - start;
 | 
			
		||||
                if (!END && dt2 >= MODULE_LOAD_THRESHOLD) {
 | 
			
		||||
                    moduleLoads.push({
 | 
			
		||||
                        request: filename.replace(`${process.cwd()}/`, ''),
 | 
			
		||||
                        parent: 'compile',
 | 
			
		||||
                        ms: dt2,
 | 
			
		||||
                        stack: CAPTURE_MODULE_STACK ? cleanStack(4) : undefined,
 | 
			
		||||
                    });
 | 
			
		||||
                    traceInstant('module_compile', 'module', {
 | 
			
		||||
                        file: filename,
 | 
			
		||||
                        ms: dt2,
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        (exts._extensions[ext] as any).__startupPatched = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Targeted fs instrumentation (especially for large migrations directory scans)
 | 
			
		||||
function markIfMigrations(op: string, target: any) {
 | 
			
		||||
    if (typeof target === 'string' && target.includes(MIGRATIONS_KEYWORD)) {
 | 
			
		||||
        setLabelForCurrent(`${op}:${path.basename(target)}`);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
try {
 | 
			
		||||
    const origReaddir = fs.readdir.bind(fs);
 | 
			
		||||
    fs.readdir = ((...args: Parameters<typeof fs.readdir>) => {
 | 
			
		||||
        markIfMigrations('fs.readdir', args[0]);
 | 
			
		||||
        return (origReaddir as any)(...(args as any));
 | 
			
		||||
    }) as any;
 | 
			
		||||
    const origReadFile = fs.readFile.bind(fs);
 | 
			
		||||
    fs.readFile = ((...args: Parameters<typeof fs.readFile>) => {
 | 
			
		||||
        markIfMigrations('fs.readFile', args[0]);
 | 
			
		||||
        return (origReadFile as any)(...(args as any));
 | 
			
		||||
    }) as any;
 | 
			
		||||
    if (fs.promises) {
 | 
			
		||||
        const p = fs.promises as any;
 | 
			
		||||
        if (p.readdir) {
 | 
			
		||||
            const orig = p.readdir.bind(p);
 | 
			
		||||
            p.readdir = async (...args: any[]) => {
 | 
			
		||||
                markIfMigrations('fsp.readdir', args[0]);
 | 
			
		||||
                return orig(...args);
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        if (p.readFile) {
 | 
			
		||||
            const orig = p.readFile.bind(p);
 | 
			
		||||
            p.readFile = async (...args: any[]) => {
 | 
			
		||||
                markIfMigrations('fsp.readFile', args[0]);
 | 
			
		||||
                return orig(...args);
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
} catch {}
 | 
			
		||||
 | 
			
		||||
const ahook = async_hooks.createHook({
 | 
			
		||||
    init(asyncId, type, triggerAsyncId) {
 | 
			
		||||
        parentOf.set(asyncId, triggerAsyncId);
 | 
			
		||||
        const rec: Rec = { type, start: performance.now() };
 | 
			
		||||
        const inherited = resolveLabelFrom(triggerAsyncId);
 | 
			
		||||
        if (inherited) {
 | 
			
		||||
            rec.ctx = inherited;
 | 
			
		||||
        } else if (type === 'PROMISE') {
 | 
			
		||||
            // fallback: capture a small user stack so "Sample of slow ops" isn't empty
 | 
			
		||||
            rec.ctx = { label: 'promise', stack: cleanStack(12) };
 | 
			
		||||
        }
 | 
			
		||||
        asyncMap.set(asyncId, rec);
 | 
			
		||||
        traceBegin(`async:${type}:${asyncId}`, 'async', {
 | 
			
		||||
            type,
 | 
			
		||||
            label: inherited?.label,
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    destroy(asyncId) {
 | 
			
		||||
        const rec = asyncMap.get(asyncId);
 | 
			
		||||
        if (!rec) return;
 | 
			
		||||
        asyncMap.delete(asyncId);
 | 
			
		||||
        const dt = performance.now() - rec.start;
 | 
			
		||||
        metrics.async.total++;
 | 
			
		||||
        metrics.async.time += dt;
 | 
			
		||||
        metrics.async.byType.set(
 | 
			
		||||
            rec.type,
 | 
			
		||||
            (metrics.async.byType.get(rec.type) ?? 0) + dt,
 | 
			
		||||
        );
 | 
			
		||||
        const label = rec.ctx?.label;
 | 
			
		||||
        const stack = rec.ctx?.stack;
 | 
			
		||||
        traceEnd(`async:${rec.type}:${asyncId}`, 'async', {
 | 
			
		||||
            dur: dt,
 | 
			
		||||
            label,
 | 
			
		||||
            stack,
 | 
			
		||||
        });
 | 
			
		||||
        if (!END && dt >= THRESHOLD_MS) {
 | 
			
		||||
            slow.push({ type: rec.type, ms: dt, id: asyncId, label, stack });
 | 
			
		||||
            if (ENABLE_PROMISE_STACK_GROUPING && rec.type === 'PROMISE') {
 | 
			
		||||
                const sig = stackSignature(stack);
 | 
			
		||||
                if (sig) {
 | 
			
		||||
                    const agg = promiseStacks.get(sig) || {
 | 
			
		||||
                        time: 0,
 | 
			
		||||
                        count: 0,
 | 
			
		||||
                        stack,
 | 
			
		||||
                        label,
 | 
			
		||||
                    };
 | 
			
		||||
                    agg.time += dt;
 | 
			
		||||
                    agg.count += 1;
 | 
			
		||||
                    if (!agg.stack && stack) agg.stack = stack;
 | 
			
		||||
                    promiseStacks.set(sig, agg);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
ahook.enable();
 | 
			
		||||
 | 
			
		||||
// -------------------- CPU profile during startup --------------------
 | 
			
		||||
let session: inspector.Session | null = null;
 | 
			
		||||
try {
 | 
			
		||||
    session = new inspector.Session();
 | 
			
		||||
    session.connect();
 | 
			
		||||
    await new Promise<void>((r) =>
 | 
			
		||||
        session!.post('Profiler.enable', () =>
 | 
			
		||||
            session!.post('Profiler.start', () => r()),
 | 
			
		||||
        ),
 | 
			
		||||
    );
 | 
			
		||||
} catch {
 | 
			
		||||
    // ignore if inspector unavailable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------------- finalize & reporting --------------------
 | 
			
		||||
function pct(n: number) {
 | 
			
		||||
    return `${((n / Math.max(1, END! - START)) * 100).toFixed(1)}%`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function writeCpuProfile() {
 | 
			
		||||
    if (!session) return;
 | 
			
		||||
    try {
 | 
			
		||||
        session.post('Profiler.stop', (_err: any, payload: any) => {
 | 
			
		||||
            try {
 | 
			
		||||
                fs.writeFileSync(
 | 
			
		||||
                    CPU_PROFILE,
 | 
			
		||||
                    JSON.stringify(payload?.profile ?? payload ?? {}),
 | 
			
		||||
                );
 | 
			
		||||
            } catch {}
 | 
			
		||||
            try {
 | 
			
		||||
                session?.disconnect();
 | 
			
		||||
            } catch {}
 | 
			
		||||
            session = null;
 | 
			
		||||
        });
 | 
			
		||||
    } catch {
 | 
			
		||||
        /* ignore */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function finalize(noListen = false) {
 | 
			
		||||
    try {
 | 
			
		||||
        ahook.disable();
 | 
			
		||||
    } catch {}
 | 
			
		||||
    traceInstant('startup_end', 'milestone', { noListen });
 | 
			
		||||
    const total = END! - START;
 | 
			
		||||
 | 
			
		||||
    // Aggregate by label for readability
 | 
			
		||||
    const byLabel = new Map<
 | 
			
		||||
        string,
 | 
			
		||||
        { count: number; time: number; sampleStack?: string[] }
 | 
			
		||||
    >();
 | 
			
		||||
    for (const s of slow) {
 | 
			
		||||
        const key = s.label ?? s.type;
 | 
			
		||||
        const agg = byLabel.get(key) ?? {
 | 
			
		||||
            count: 0,
 | 
			
		||||
            time: 0,
 | 
			
		||||
            sampleStack: s.stack,
 | 
			
		||||
        };
 | 
			
		||||
        agg.count++;
 | 
			
		||||
        agg.time += s.ms;
 | 
			
		||||
        if (!agg.sampleStack && s.stack) agg.sampleStack = s.stack;
 | 
			
		||||
        byLabel.set(key, agg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const lines: string[] = [];
 | 
			
		||||
    lines.push(`Node ${process.version} | PID ${process.pid}`);
 | 
			
		||||
    lines.push(`Startup window: ${total.toFixed(2)} ms`);
 | 
			
		||||
    if (listenTarget && !noListen) {
 | 
			
		||||
        lines.push(
 | 
			
		||||
            `First server listening: ${listenTarget.proto}://${listenTarget.address ?? '0.0.0.0'}:${listenTarget.port ?? ''}`,
 | 
			
		||||
        );
 | 
			
		||||
    } else {
 | 
			
		||||
        lines.push(
 | 
			
		||||
            `No server "listening" detected; dumping until process idle.`,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    lines.push('');
 | 
			
		||||
 | 
			
		||||
    lines.push(`= Async operations before listen =`);
 | 
			
		||||
    lines.push(
 | 
			
		||||
        `  ops: ${metrics.async.total} | time (sum): ${metrics.async.time.toFixed(2)} ms`,
 | 
			
		||||
    );
 | 
			
		||||
    if (metrics.async.byType.size) {
 | 
			
		||||
        lines.push(`  by type:`);
 | 
			
		||||
        for (const [t, ms] of [...metrics.async.byType.entries()].sort(
 | 
			
		||||
            (a, b) => b[1] - a[1],
 | 
			
		||||
        )) {
 | 
			
		||||
            lines.push(`    ${t.padEnd(14)} ${ms.toFixed(2)} ms (${pct(ms)})`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lines.push('');
 | 
			
		||||
    lines.push(`= Top slow async groups (by label) =`);
 | 
			
		||||
    if (byLabel.size === 0) {
 | 
			
		||||
        lines.push('  (none over threshold)');
 | 
			
		||||
    } else {
 | 
			
		||||
        for (const [label, v] of [...byLabel.entries()]
 | 
			
		||||
            .sort((a, b) => b[1].time - a[1].time)
 | 
			
		||||
            .slice(0, 30)) {
 | 
			
		||||
            lines.push(
 | 
			
		||||
                `  ${label}: ${v.time.toFixed(2)} ms across ${v.count} ops`,
 | 
			
		||||
            );
 | 
			
		||||
            if (v.sampleStack)
 | 
			
		||||
                for (const f of v.sampleStack.slice(0, 5))
 | 
			
		||||
                    lines.push(`      at ${f}`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (slow.length) {
 | 
			
		||||
        lines.push('');
 | 
			
		||||
        lines.push(`= Sample of slow ops (>${THRESHOLD_MS} ms) =`);
 | 
			
		||||
        for (const s of slow.sort((a, b) => b.ms - a.ms).slice(0, 50)) {
 | 
			
		||||
            lines.push(
 | 
			
		||||
                `  ${s.ms.toFixed(2)} ms  ${s.type}${s.label ? `  [${s.label}]` : ''} (id ${s.id})`,
 | 
			
		||||
            );
 | 
			
		||||
            if (s.stack?.length)
 | 
			
		||||
                for (const f of s.stack.slice(0, 4))
 | 
			
		||||
                    lines.push(`      at ${f}`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ENABLE_PROMISE_STACK_GROUPING && promiseStacks.size) {
 | 
			
		||||
        lines.push('');
 | 
			
		||||
        lines.push('= Top PROMISE stacks (aggregated) =');
 | 
			
		||||
        for (const [sig, agg] of [...promiseStacks.entries()]
 | 
			
		||||
            .sort((a, b) => b[1].time - a[1].time)
 | 
			
		||||
            .slice(0, MAX_PROMISE_STACKS)) {
 | 
			
		||||
            lines.push(
 | 
			
		||||
                `  ${agg.time.toFixed(2)} ms across ${agg.count} promises :: ${sig}${agg.label ? ` [label:${agg.label}]` : ''}`,
 | 
			
		||||
            );
 | 
			
		||||
            if (agg.stack) {
 | 
			
		||||
                for (const f of agg.stack.slice(0, 6))
 | 
			
		||||
                    lines.push(`      at ${f}`);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (moduleLoads.length) {
 | 
			
		||||
        lines.push('');
 | 
			
		||||
        lines.push('= Slow module loads / compilations =');
 | 
			
		||||
        const byReq = new Map<
 | 
			
		||||
            string,
 | 
			
		||||
            { time: number; count: number; stack?: string[] }
 | 
			
		||||
        >();
 | 
			
		||||
        for (const m of moduleLoads) {
 | 
			
		||||
            const key = m.request;
 | 
			
		||||
            const agg = byReq.get(key) || {
 | 
			
		||||
                time: 0,
 | 
			
		||||
                count: 0,
 | 
			
		||||
                stack: m.stack,
 | 
			
		||||
            };
 | 
			
		||||
            agg.time += m.ms;
 | 
			
		||||
            agg.count += 1;
 | 
			
		||||
            if (!agg.stack && m.stack) agg.stack = m.stack;
 | 
			
		||||
            byReq.set(key, agg);
 | 
			
		||||
        }
 | 
			
		||||
        for (const [req, agg] of [...byReq.entries()]
 | 
			
		||||
            .sort((a, b) => b[1].time - a[1].time)
 | 
			
		||||
            .slice(0, 40)) {
 | 
			
		||||
            lines.push(
 | 
			
		||||
                `  ${agg.time.toFixed(2)} ms across ${agg.count} load(s) :: ${req}`,
 | 
			
		||||
            );
 | 
			
		||||
            if (agg.stack) {
 | 
			
		||||
                for (const f of agg.stack.slice(0, 4))
 | 
			
		||||
                    lines.push(`      at ${f}`);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lines.push('');
 | 
			
		||||
    lines.push(
 | 
			
		||||
        `Tips: move DB connect/migrations after listen(); lazy-load heavy routes; avoid sync FS; defer remote config/secret fetches; inspect "Slow module loads" and "Top PROMISE stacks" (tune with STARTUP_* env vars).`,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        fs.writeFileSync(REPORT_TXT, `${lines.join('\n')}\n`, 'utf8');
 | 
			
		||||
    } catch {}
 | 
			
		||||
    try {
 | 
			
		||||
        fs.writeFileSync(
 | 
			
		||||
            TRACE_JSON,
 | 
			
		||||
            JSON.stringify({ traceEvents }, null, 2),
 | 
			
		||||
            'utf8',
 | 
			
		||||
        );
 | 
			
		||||
    } catch {}
 | 
			
		||||
    writeCpuProfile();
 | 
			
		||||
 | 
			
		||||
    console.error(
 | 
			
		||||
        `[startup-profiler] ${total.toFixed(2)} ms before first "listening". Report: ${REPORT_TXT} | Trace: ${TRACE_JSON} | CPU: ${CPU_PROFILE}`,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								startup-cpu.cpuprofile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								startup-cpu.cpuprofile
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										402
									
								
								startup-report.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										402
									
								
								startup-report.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,402 @@
 | 
			
		||||
Node v22.17.1 | PID 2141941
 | 
			
		||||
Startup window: 2934.39 ms
 | 
			
		||||
First server listening: http://:::4242
 | 
			
		||||
 | 
			
		||||
= Async operations before listen =
 | 
			
		||||
  ops: 43218 | time (sum): 14113527.21 ms
 | 
			
		||||
  by type:
 | 
			
		||||
    PROMISE        13306289.12 ms (453460.8%)
 | 
			
		||||
    FILEHANDLECLOSEREQ 289939.98 ms (9880.8%)
 | 
			
		||||
    FSREQPROMISE   274105.20 ms (9341.1%)
 | 
			
		||||
    FILEHANDLE     242402.28 ms (8260.8%)
 | 
			
		||||
    TickObject     234.01 ms (8.0%)
 | 
			
		||||
    RANDOMBYTESREQUEST 221.09 ms (7.5%)
 | 
			
		||||
    Timeout        218.94 ms (7.5%)
 | 
			
		||||
    Immediate      45.68 ms (1.6%)
 | 
			
		||||
    TCPWRAP        36.86 ms (1.3%)
 | 
			
		||||
    SHUTDOWNWRAP   15.46 ms (0.5%)
 | 
			
		||||
    GETADDRINFOREQWRAP 11.81 ms (0.4%)
 | 
			
		||||
    TCPCONNECTWRAP 4.23 ms (0.1%)
 | 
			
		||||
    FSREQCALLBACK  2.54 ms (0.1%)
 | 
			
		||||
 | 
			
		||||
= Top slow async groups (by label) =
 | 
			
		||||
  promise: 13295053.76 ms across 38216 ops
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  FILEHANDLECLOSEREQ: 289934.19 ms across 862 ops
 | 
			
		||||
  FSREQPROMISE: 271859.34 ms across 2349 ops
 | 
			
		||||
  FILEHANDLE: 242394.26 ms across 354 ops
 | 
			
		||||
  setImmediate: 368.57 ms across 10 ops
 | 
			
		||||
      at at Async.schedule [as _schedule] (node_modules/bluebird/js/release/schedule.js:12:53)
 | 
			
		||||
      at at Async._queueTick (node_modules/bluebird/js/release/async.js:111:14)
 | 
			
		||||
      at at Async.AsyncInvoke [as invoke] (node_modules/bluebird/js/release/async.js:71:10)
 | 
			
		||||
      at at Promise._then (node_modules/bluebird/js/release/promise.js:290:15)
 | 
			
		||||
      at at Promise.then (node_modules/bluebird/js/release/promise.js:154:17)
 | 
			
		||||
  RANDOMBYTESREQUEST: 221.09 ms across 1 ops
 | 
			
		||||
  setTimeout: 166.54 ms across 6 ops
 | 
			
		||||
      at at Client._connect (node_modules/pg/lib/client.js:104:38)
 | 
			
		||||
      at at Client.connect (node_modules/pg/lib/client.js:166:12)
 | 
			
		||||
      at at exports.connect (node_modules/db-migrate-pg/index.js:775:6)
 | 
			
		||||
      at at connect (node_modules/db-migrate/lib/driver/index.js:93:12)
 | 
			
		||||
      at at exports.connect (node_modules/db-migrate/lib/driver/index.js:134:5)
 | 
			
		||||
  pg.connect: 59.72 ms across 2 ops
 | 
			
		||||
      at at Client_PG._acquireOnlyConnection (node_modules/knex/lib/dialects/postgres/index.js:91:23)
 | 
			
		||||
      at at Client_PG.acquireRawConnection (node_modules/knex/lib/dialects/postgres/index.js:99:17)
 | 
			
		||||
      at at create (node_modules/knex/lib/client.js:262:39)
 | 
			
		||||
  TickObject: 53.63 ms across 1 ops
 | 
			
		||||
 | 
			
		||||
= Sample of slow ops (>15 ms) =
 | 
			
		||||
  1134.35 ms  PROMISE  [promise] (id 63855)
 | 
			
		||||
  1134.21 ms  PROMISE  [promise] (id 63859)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1134.08 ms  PROMISE  [promise] (id 63867)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1134.06 ms  PROMISE  [promise] (id 63868)
 | 
			
		||||
  1134.01 ms  PROMISE  [promise] (id 63870)
 | 
			
		||||
  1133.99 ms  PROMISE  [promise] (id 63871)
 | 
			
		||||
  1133.97 ms  PROMISE  [promise] (id 63872)
 | 
			
		||||
  1133.95 ms  PROMISE  [promise] (id 63873)
 | 
			
		||||
  1133.93 ms  PROMISE  [promise] (id 63874)
 | 
			
		||||
  1133.90 ms  PROMISE  [promise] (id 63875)
 | 
			
		||||
  1133.87 ms  PROMISE  [promise] (id 63876)
 | 
			
		||||
  1133.83 ms  PROMISE  [promise] (id 63878)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1133.81 ms  PROMISE  [promise] (id 63879)
 | 
			
		||||
  1133.78 ms  PROMISE  [promise] (id 63880)
 | 
			
		||||
  1133.76 ms  PROMISE  [promise] (id 63881)
 | 
			
		||||
  1133.74 ms  PROMISE  [promise] (id 63882)
 | 
			
		||||
  1133.73 ms  PROMISE  [promise] (id 63883)
 | 
			
		||||
  1133.68 ms  PROMISE  [promise] (id 63885)
 | 
			
		||||
  1133.67 ms  PROMISE  [promise] (id 63886)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1133.64 ms  PROMISE  [promise] (id 63887)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1133.63 ms  PROMISE  [promise] (id 63888)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1133.52 ms  PROMISE  [promise] (id 63896)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1128.85 ms  PROMISE  [promise] (id 64070)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1128.51 ms  PROMISE  [promise] (id 64091)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1128.50 ms  PROMISE  [promise] (id 64092)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1128.48 ms  PROMISE  [promise] (id 64093)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1126.44 ms  PROMISE  [promise] (id 64217)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1125.06 ms  PROMISE  [promise] (id 64266)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.97 ms  PROMISE  [promise] (id 64270)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.89 ms  PROMISE  [promise] (id 64274)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.80 ms  PROMISE  [promise] (id 64278)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.72 ms  PROMISE  [promise] (id 64282)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.65 ms  PROMISE  [promise] (id 64286)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.57 ms  PROMISE  [promise] (id 64290)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.50 ms  PROMISE  [promise] (id 64294)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.48 ms  PROMISE  [promise] (id 64295)
 | 
			
		||||
  1124.42 ms  PROMISE  [promise] (id 64298)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1124.41 ms  PROMISE  [promise] (id 64299)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1124.32 ms  PROMISE  [promise] (id 64303)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1124.22 ms  PROMISE  [promise] (id 64309)
 | 
			
		||||
  1124.17 ms  PROMISE  [promise] (id 64311)
 | 
			
		||||
  1124.16 ms  PROMISE  [promise] (id 64312)
 | 
			
		||||
  1124.14 ms  PROMISE  [promise] (id 64313)
 | 
			
		||||
  1124.12 ms  PROMISE  [promise] (id 64314)
 | 
			
		||||
  1124.10 ms  PROMISE  [promise] (id 64315)
 | 
			
		||||
  1124.07 ms  PROMISE  [promise] (id 64316)
 | 
			
		||||
  1124.04 ms  PROMISE  [promise] (id 64317)
 | 
			
		||||
  1124.01 ms  PROMISE  [promise] (id 64319)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1123.99 ms  PROMISE  [promise] (id 64320)
 | 
			
		||||
  1123.96 ms  PROMISE  [promise] (id 64321)
 | 
			
		||||
 | 
			
		||||
= Top PROMISE stacks (aggregated) =
 | 
			
		||||
  3774603.57 ms across 8630 promises :: at Promise.then (<anonymous>) [label:promise]
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  1010836.12 ms across 4832 promises :: at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  1008653.70 ms across 4268 promises :: at Promise.then (<anonymous>) | at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  226733.65 ms across 412 promises :: at new Promise (<anonymous>) | at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  226705.14 ms across 412 promises :: at Promise.then (<anonymous>) | at new Promise (<anonymous>) | at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  226690.60 ms across 412 promises :: at new Promise (<anonymous>) | at Promise.then (<anonymous>) | at Promise.finally (<anonymous>) | at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at Promise.finally (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  226689.24 ms across 412 promises :: at new Promise (<anonymous>) | at Promise.then (<anonymous>) | at new Promise (<anonymous>) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
  137085.64 ms across 828 promises :: at new Promise (<anonymous>) | at <anonymous> [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at <anonymous>
 | 
			
		||||
  137060.61 ms across 828 promises :: at new Promise (<anonymous>) | at Promise.then (<anonymous>) | at <anonymous> [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
      at at <anonymous>
 | 
			
		||||
  137023.60 ms across 828 promises :: at new Promise (<anonymous>) | at Promise.then (<anonymous>) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at Promise.then (<anonymous>)
 | 
			
		||||
  558.43 ms across 1 promises :: at new Promise (<anonymous>) | at <anonymous> (node_modules/ky/source/core/constants.ts) | at <anonymous> (node_modules/ky/source/core/constants.ts) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at <anonymous> (node_modules/ky/source/core/constants.ts:14:11)
 | 
			
		||||
      at at <anonymous> (node_modules/ky/source/core/constants.ts:33:3)
 | 
			
		||||
  514.68 ms across 1 promises :: at Function.resolve (<anonymous>) | at Object.<anonymous> (node_modules/lodash/_getTag.js) | at TracingChannel.traceSync (node:diagnostics_channel) | at Object.<anonymous> (node_modules/lodash/_baseClone.js) [label:promise]
 | 
			
		||||
      at at Function.resolve (<anonymous>)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash/_getTag.js:37:32)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash/_baseClone.js:12:14)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash/cloneDeep.js:1:17)
 | 
			
		||||
  494.89 ms across 2 promises :: at new Promise (<anonymous>) | at <anonymous> (node_modules/axios/lib/adapters/fetch.js) | at test (node_modules/axios/lib/adapters/fetch.js) | at Object.<anonymous> (node_modules/axios/lib/adapters/fetch.js) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at <anonymous> (node_modules/axios/lib/adapters/fetch.js:32:11)
 | 
			
		||||
      at at test (node_modules/axios/lib/adapters/fetch.js:22:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/axios/lib/adapters/fetch.js:28:60)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/@slack/web-api/src/WebClient.ts:8:1)
 | 
			
		||||
  266.54 ms across 5 promises :: at Async.schedule [as _schedule] (node_modules/bluebird/js/release/schedule.js) | at Async._queueTick (node_modules/bluebird/js/release/async.js) | at Async.AsyncInvoke [as invoke] (node_modules/bluebird/js/release/async.js) | at Promise._then (node_modules/bluebird/js/release/promise.js) [label:setImmediate]
 | 
			
		||||
      at at Async.schedule [as _schedule] (node_modules/bluebird/js/release/schedule.js:12:53)
 | 
			
		||||
      at at Async._queueTick (node_modules/bluebird/js/release/async.js:111:14)
 | 
			
		||||
      at at Async.AsyncInvoke [as invoke] (node_modules/bluebird/js/release/async.js:71:10)
 | 
			
		||||
      at at Promise._then (node_modules/bluebird/js/release/promise.js:290:15)
 | 
			
		||||
      at at Promise.then (node_modules/bluebird/js/release/promise.js:154:17)
 | 
			
		||||
      at at module.exports (node_modules/db-migrate/lib/commands/check.js:8:6)
 | 
			
		||||
  227.97 ms across 1 promises :: at Function.resolve (<anonymous>) | at runInContext (node_modules/lodash/lodash.js) | at Object.<anonymous> (node_modules/lodash/lodash.js) | at Object.<anonymous> (node_modules/lodash/lodash.js) [label:promise]
 | 
			
		||||
      at at Function.resolve (<anonymous>)
 | 
			
		||||
      at at runInContext (node_modules/lodash/lodash.js:6113:36)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash/lodash.js:17182:11)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash/lodash.js:17209:3)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  162.49 ms across 1 promises :: at Function.resolve (<anonymous>) | at Object.<anonymous> (node_modules/lodash.isequal/index.js) | at TracingChannel.traceSync (node:diagnostics_channel) | at Object.<anonymous> (node_modules/z-schema/src/SchemaCache.js) [label:promise]
 | 
			
		||||
      at at Function.resolve (<anonymous>)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash.isequal/index.js:1373:32)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/z-schema/src/SchemaCache.js:3:27)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/z-schema/src/ZSchema.js:8:25)
 | 
			
		||||
  101.80 ms across 1 promises :: at requiresMigration (src/migrator.ts) | at start (src/lib/server-impl.ts) | at <anonymous> (src/server-dev.ts) [label:promise]
 | 
			
		||||
      at at requiresMigration (src/migrator.ts:43:40)
 | 
			
		||||
      at at start (src/lib/server-impl.ts:343:23)
 | 
			
		||||
      at at <anonymous> (src/server-dev.ts:8:15)
 | 
			
		||||
  101.65 ms across 1 promises :: at noDatabaseUrl (src/migrator.ts) | at requiresMigration (src/migrator.ts) | at start (src/lib/server-impl.ts) | at <anonymous> (src/server-dev.ts) [label:promise]
 | 
			
		||||
      at at noDatabaseUrl (src/migrator.ts:13:29)
 | 
			
		||||
      at at requiresMigration (src/migrator.ts:46:12)
 | 
			
		||||
      at at start (src/lib/server-impl.ts:343:23)
 | 
			
		||||
      at at <anonymous> (src/server-dev.ts:8:15)
 | 
			
		||||
  101.58 ms across 1 promises :: at <anonymous> (src/migrator.ts) | at noDatabaseUrl (src/migrator.ts) | at requiresMigration (src/migrator.ts) | at start (src/lib/server-impl.ts) [label:promise]
 | 
			
		||||
      at at <anonymous> (src/migrator.ts:46:26)
 | 
			
		||||
      at at noDatabaseUrl (src/migrator.ts:17:20)
 | 
			
		||||
      at at requiresMigration (src/migrator.ts:46:12)
 | 
			
		||||
      at at start (src/lib/server-impl.ts:343:23)
 | 
			
		||||
      at at <anonymous> (src/server-dev.ts:8:15)
 | 
			
		||||
  83.95 ms across 1 promises :: at Function.resolve (<anonymous>) | at Object.<anonymous> (node_modules/lodash.groupby/index.js) | at TracingChannel.traceSync (node:diagnostics_channel) [label:promise]
 | 
			
		||||
      at at Function.resolve (<anonymous>)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/lodash.groupby/index.js:1598:32)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  46.57 ms across 1 promises :: at requiresNode8OrGreater (node_modules/db-migrate/node_modules/yargs/yargs.js) | at Object.<anonymous> (node_modules/db-migrate/node_modules/yargs/yargs.js) | at TracingChannel.traceSync (node:diagnostics_channel) | at Object.<anonymous> (node_modules/db-migrate/node_modules/yargs/index.js) [label:promise]
 | 
			
		||||
      at at requiresNode8OrGreater (node_modules/db-migrate/node_modules/yargs/yargs.js:4:39)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/db-migrate/node_modules/yargs/yargs.js:5:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/db-migrate/node_modules/yargs/index.js:5:15)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/db-migrate/lib/commands/set-default-argv.js:1:13)
 | 
			
		||||
  20.07 ms across 1 promises :: at new Promise (<anonymous>) | at Object.getNativePromise (node_modules/bluebird/js/release/util.js) | at Object.<anonymous> (node_modules/bluebird/js/release/schedule.js) | at TracingChannel.traceSync (node:diagnostics_channel) [label:promise]
 | 
			
		||||
      at at new Promise (<anonymous>)
 | 
			
		||||
      at at Object.getNativePromise (node_modules/bluebird/js/release/util.js:328:27)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/bluebird/js/release/schedule.js:7:26)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/bluebird/js/release/async.js:4:16)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
 | 
			
		||||
= Slow module loads / compilations =
 | 
			
		||||
  278.16 ms across 1 load(s) :: /home/gaston/projects/unleash/node_modules/date-fns/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  278.07 ms across 1 load(s) :: node_modules/date-fns/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  136.18 ms across 1 load(s) :: /home/gaston/projects/unleash/node_modules/@wesleytodd/openapi/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  136.09 ms across 1 load(s) :: node_modules/@wesleytodd/openapi/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  121.67 ms across 1 load(s) :: /home/gaston/projects/unleash/node_modules/unleash-client/lib/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  121.57 ms across 1 load(s) :: node_modules/unleash-client/lib/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  119.88 ms across 1 load(s) :: ./unleash
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/index.ts:2:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  119.70 ms across 1 load(s) :: node_modules/unleash-client/lib/unleash.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/index.ts:2:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  102.10 ms across 1 load(s) :: /home/gaston/projects/unleash/node_modules/connect-session-knex/dist/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  102.03 ms across 1 load(s) :: node_modules/connect-session-knex/dist/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  101.57 ms across 1 load(s) :: knex
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/connect-session-knex/dist/src/index.ts:1:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  101.27 ms across 1 load(s) :: node_modules/knex/knex.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/connect-session-knex/dist/src/index.ts:1:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  101.25 ms across 1 load(s) :: ./lib/index
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/knex.js:8:14)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/connect-session-knex/dist/src/index.ts:1:1)
 | 
			
		||||
  101.12 ms across 1 load(s) :: node_modules/knex/lib/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/knex.js:8:14)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/connect-session-knex/dist/src/index.ts:1:1)
 | 
			
		||||
  101.08 ms across 1 load(s) :: ./knex-builder/Knex
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/index.js:1:14)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/knex.js:8:14)
 | 
			
		||||
  100.90 ms across 1 load(s) :: node_modules/knex/lib/knex-builder/Knex.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/index.js:1:14)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/knex.js:8:14)
 | 
			
		||||
  98.83 ms across 1 load(s) :: ../client
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/knex-builder/Knex.js:1:16)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/index.js:1:14)
 | 
			
		||||
  98.57 ms across 1 load(s) :: node_modules/knex/lib/client.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/knex-builder/Knex.js:1:16)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/knex/lib/index.js:1:14)
 | 
			
		||||
  97.78 ms across 1 load(s) :: ./isMatch/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/index.js:1797:40)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  97.67 ms across 1 load(s) :: node_modules/date-fns/isMatch/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/index.js:1797:40)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  97.10 ms across 1 load(s) :: ../parse/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/isMatch/index.js:8:37)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/index.js:1797:40)
 | 
			
		||||
  96.91 ms across 1 load(s) :: node_modules/date-fns/parse/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/isMatch/index.js:8:37)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/index.js:1797:40)
 | 
			
		||||
  95.34 ms across 1 load(s) :: ./repository
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/unleash.ts:4:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/index.ts:2:1)
 | 
			
		||||
  95.11 ms across 1 load(s) :: node_modules/unleash-client/lib/repository/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/unleash.ts:4:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/index.ts:2:1)
 | 
			
		||||
  93.45 ms across 1 load(s) :: ../request
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/repository/index.ts:9:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/unleash.ts:4:1)
 | 
			
		||||
  93.21 ms across 1 load(s) :: node_modules/unleash-client/lib/request.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/repository/index.ts:9:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/unleash.ts:4:1)
 | 
			
		||||
  89.85 ms across 1 load(s) :: make-fetch-happen
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/request.ts:1:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/repository/index.ts:9:1)
 | 
			
		||||
  89.48 ms across 1 load(s) :: node_modules/make-fetch-happen/lib/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/request.ts:1:1)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/repository/index.ts:9:1)
 | 
			
		||||
  85.40 ms across 1 load(s) :: ./_lib/parsers/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/parse/index.js:20:16)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/isMatch/index.js:8:37)
 | 
			
		||||
  85.08 ms across 1 load(s) :: node_modules/date-fns/parse/_lib/parsers/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/parse/index.js:20:16)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/date-fns/isMatch/index.js:8:37)
 | 
			
		||||
  79.73 ms across 1 load(s) :: swagger-parser
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/@wesleytodd/openapi/index.js:4:23)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  79.59 ms across 1 load(s) :: node_modules/swagger-parser/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/@wesleytodd/openapi/index.js:4:23)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
  79.55 ms across 1 load(s) :: @apidevtools/swagger-parser
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/swagger-parser/index.js:2:18)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/@wesleytodd/openapi/index.js:4:23)
 | 
			
		||||
  79.35 ms across 1 load(s) :: node_modules/swagger-parser/node_modules/@apidevtools/swagger-parser/lib/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/swagger-parser/index.js:2:18)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/@wesleytodd/openapi/index.js:4:23)
 | 
			
		||||
  79.16 ms across 1 load(s) :: ./fetch.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/index.js:4:15)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/request.ts:1:1)
 | 
			
		||||
  78.91 ms across 1 load(s) :: node_modules/make-fetch-happen/lib/fetch.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/index.js:4:15)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/unleash-client/src/request.ts:1:1)
 | 
			
		||||
  73.35 ms across 1 load(s) :: ./cache/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/fetch.js:7:15)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/index.js:4:15)
 | 
			
		||||
  73.08 ms across 1 load(s) :: node_modules/make-fetch-happen/lib/cache/index.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/fetch.js:7:15)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/index.js:4:15)
 | 
			
		||||
  72.33 ms across 1 load(s) :: ./entry.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/cache/index.js:2:20)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/fetch.js:7:15)
 | 
			
		||||
  72.06 ms across 1 load(s) :: node_modules/make-fetch-happen/lib/cache/entry.js
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/cache/index.js:2:20)
 | 
			
		||||
      at at TracingChannel.traceSync (node:diagnostics_channel:322:14)
 | 
			
		||||
      at at Object.<anonymous> (node_modules/make-fetch-happen/lib/fetch.js:7:15)
 | 
			
		||||
 | 
			
		||||
Tips: move DB connect/migrations after listen(); lazy-load heavy routes; avoid sync FS; defer remote config/secret fetches; inspect "Slow module loads" and "Top PROMISE stacks" (tune with STARTUP_* env vars).
 | 
			
		||||
							
								
								
									
										1331334
									
								
								startup-trace.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1331334
									
								
								startup-trace.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user