@adonis-agora/telescope 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +6 -0
- package/dist/configure.js.map +1 -1
- package/dist/providers/telescope_cpu_profiling_provider.d.ts +28 -0
- package/dist/providers/telescope_cpu_profiling_provider.d.ts.map +1 -0
- package/dist/providers/telescope_cpu_profiling_provider.js +45 -0
- package/dist/providers/telescope_cpu_profiling_provider.js.map +1 -0
- package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
- package/dist/providers/telescope_ui_provider.js +163 -12
- package/dist/providers/telescope_ui_provider.js.map +1 -1
- package/dist/providers/telescope_watchers_provider.d.ts +10 -0
- package/dist/providers/telescope_watchers_provider.d.ts.map +1 -1
- package/dist/providers/telescope_watchers_provider.js +32 -0
- package/dist/providers/telescope_watchers_provider.js.map +1 -1
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/alerts/index.d.ts +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/entry.d.ts +8 -0
- package/dist/src/entry.d.ts.map +1 -1
- package/dist/src/entry.js +8 -0
- package/dist/src/entry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/profiling/aggregate-profile.d.ts +21 -0
- package/dist/src/profiling/aggregate-profile.d.ts.map +1 -0
- package/dist/src/profiling/aggregate-profile.js +124 -0
- package/dist/src/profiling/aggregate-profile.js.map +1 -0
- package/dist/src/profiling/cpu-profiler.d.ts +59 -0
- package/dist/src/profiling/cpu-profiler.d.ts.map +1 -0
- package/dist/src/profiling/cpu-profiler.js +94 -0
- package/dist/src/profiling/cpu-profiler.js.map +1 -0
- package/dist/src/profiling/define_config.d.ts +38 -0
- package/dist/src/profiling/define_config.d.ts.map +1 -0
- package/dist/src/profiling/define_config.js +23 -0
- package/dist/src/profiling/define_config.js.map +1 -0
- package/dist/src/profiling/index.d.ts +11 -0
- package/dist/src/profiling/index.d.ts.map +1 -0
- package/dist/src/profiling/index.js +7 -0
- package/dist/src/profiling/index.js.map +1 -0
- package/dist/src/profiling/profiler_service.d.ts +100 -0
- package/dist/src/profiling/profiler_service.d.ts.map +1 -0
- package/dist/src/profiling/profiler_service.js +162 -0
- package/dist/src/profiling/profiler_service.js.map +1 -0
- package/dist/src/profiling/types.d.ts +86 -0
- package/dist/src/profiling/types.d.ts.map +1 -0
- package/dist/src/profiling/types.js +5 -0
- package/dist/src/profiling/types.js.map +1 -0
- package/dist/src/registry.d.ts +28 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +20 -0
- package/dist/src/registry.js.map +1 -1
- package/dist/src/telescope_middleware.d.ts.map +1 -1
- package/dist/src/telescope_middleware.js +25 -0
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/api.d.ts +41 -1
- package/dist/src/ui/api.d.ts.map +1 -1
- package/dist/src/ui/api.js +27 -1
- package/dist/src/ui/api.js.map +1 -1
- package/dist/src/ui/define_config.d.ts +26 -0
- package/dist/src/ui/define_config.d.ts.map +1 -1
- package/dist/src/ui/define_config.js +8 -0
- package/dist/src/ui/define_config.js.map +1 -1
- package/dist/src/ui/diagnosis_api.d.ts +33 -0
- package/dist/src/ui/diagnosis_api.d.ts.map +1 -0
- package/dist/src/ui/diagnosis_api.js +60 -0
- package/dist/src/ui/diagnosis_api.js.map +1 -0
- package/dist/src/ui/extension_api.d.ts +6 -2
- package/dist/src/ui/extension_api.d.ts.map +1 -1
- package/dist/src/ui/extension_api.js +7 -2
- package/dist/src/ui/extension_api.js.map +1 -1
- package/dist/src/ui/index.d.ts +8 -2
- package/dist/src/ui/index.d.ts.map +1 -1
- package/dist/src/ui/index.js +7 -1
- package/dist/src/ui/index.js.map +1 -1
- package/dist/src/ui/profiles_api.d.ts +48 -0
- package/dist/src/ui/profiles_api.d.ts.map +1 -0
- package/dist/src/ui/profiles_api.js +94 -0
- package/dist/src/ui/profiles_api.js.map +1 -0
- package/dist/src/ui/queue_manager_api.d.ts +46 -0
- package/dist/src/ui/queue_manager_api.d.ts.map +1 -0
- package/dist/src/ui/queue_manager_api.js +118 -0
- package/dist/src/ui/queue_manager_api.js.map +1 -0
- package/dist/src/ui/schedules_api.d.ts +43 -0
- package/dist/src/ui/schedules_api.d.ts.map +1 -0
- package/dist/src/ui/schedules_api.js +46 -0
- package/dist/src/ui/schedules_api.js.map +1 -0
- package/dist/src/watchers/cron_next_run.d.ts +8 -0
- package/dist/src/watchers/cron_next_run.d.ts.map +1 -0
- package/dist/src/watchers/cron_next_run.js +67 -0
- package/dist/src/watchers/cron_next_run.js.map +1 -0
- package/dist/src/watchers/define_config.d.ts +28 -1
- package/dist/src/watchers/define_config.d.ts.map +1 -1
- package/dist/src/watchers/define_config.js +5 -0
- package/dist/src/watchers/define_config.js.map +1 -1
- package/dist/src/watchers/index.d.ts +7 -4
- package/dist/src/watchers/index.d.ts.map +1 -1
- package/dist/src/watchers/index.js +5 -2
- package/dist/src/watchers/index.js.map +1 -1
- package/dist/src/watchers/queue_manager.d.ts +229 -0
- package/dist/src/watchers/queue_manager.d.ts.map +1 -0
- package/dist/src/watchers/queue_manager.js +223 -0
- package/dist/src/watchers/queue_manager.js.map +1 -0
- package/dist/src/watchers/schedule_watcher.d.ts +94 -1
- package/dist/src/watchers/schedule_watcher.d.ts.map +1 -1
- package/dist/src/watchers/schedule_watcher.js +83 -1
- package/dist/src/watchers/schedule_watcher.js.map +1 -1
- package/dist/stubs/config/telescope_cpu_profiling.stub +0 -0
- package/package.json +29 -14
package/dist/src/entry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;IACpB,wEAAwE;;IAExE,0DAA0D;;;;;;;;;;IAW1D,kEAAkE;;IAElE;;;;OAIG;;IAEH;;;;;OAKG;;IAEH;;;;;OAKG;;CAEK,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAE1E;;;;GAIG;AACH,QAAA,MAAM,aAAa,yDAA0D,CAAC;AAC9E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;;GAIG;AACH,MAAM,WAAW,KAAK,CAAC,QAAQ,GAAG,OAAO;IACvC,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iCAAiC;IACjC,OAAO,EAAE,QAAQ,CAAC;IAClB,iFAAiF;IACjF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oCAAoC;IACpC,MAAM,EAAE,WAAW,CAAC;IACpB,qEAAqE;IACrE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mCAAmC;IACnC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,QAAQ,GAAG,OAAO;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;IACpB,wEAAwE;;IAExE,0DAA0D;;;;;;;;;;IAW1D,kEAAkE;;IAElE;;;;OAIG;;IAEH;;;;;OAKG;;IAEH;;;;;OAKG;;IAEH;;;;;;OAMG;;CAEK,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAE1E;;;;GAIG;AACH,QAAA,MAAM,aAAa,yDAA0D,CAAC;AAC9E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;;GAIG;AACH,MAAM,WAAW,KAAK,CAAC,QAAQ,GAAG,OAAO;IACvC,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iCAAiC;IACjC,OAAO,EAAE,QAAQ,CAAC;IAClB,iFAAiF;IACjF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oCAAoC;IACpC,MAAM,EAAE,WAAW,CAAC;IACpB,qEAAqE;IACrE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mCAAmC;IACnC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,QAAQ,GAAG,OAAO;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
|
package/dist/src/entry.js
CHANGED
|
@@ -41,6 +41,14 @@ export const EntryType = {
|
|
|
41
41
|
* tags, so it composes with dedup, prune, sampling, and the dashboard.
|
|
42
42
|
*/
|
|
43
43
|
ClientException: 'client_exception',
|
|
44
|
+
/**
|
|
45
|
+
* An aggregated V8 CPU profile (flamegraph tree + precomputed hot frames)
|
|
46
|
+
* captured via `node:inspector`'s `Profiler.start`/`Profiler.stop`, recorded
|
|
47
|
+
* by the OPTIONAL `cpu_profiling` feature (`@adonis-agora/telescope/cpu_profiling`).
|
|
48
|
+
* Distinct from {@link EntryType.Profile} (user-instrumented timing spans) —
|
|
49
|
+
* this is a real V8 sampling-profiler capture.
|
|
50
|
+
*/
|
|
51
|
+
CpuProfile: 'cpu_profile',
|
|
44
52
|
};
|
|
45
53
|
/**
|
|
46
54
|
* Where a batch of entries originated. An entry recorded inside an HTTP request
|
package/dist/src/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,wEAAwE;IACxE,OAAO,EAAE,SAAS;IAClB,0DAA0D;IAC1D,UAAU,EAAE,YAAY;IACxB,8DAA8D;IAC9D,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,kEAAkE;IAClE,UAAU,EAAE,aAAa;IACzB;;;;OAIG;IACH,OAAO,EAAE,SAAS;IAClB;;;;;OAKG;IACH,aAAa,EAAE,gBAAgB;IAC/B;;;;;OAKG;IACH,eAAe,EAAE,kBAAkB;
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,wEAAwE;IACxE,OAAO,EAAE,SAAS;IAClB,0DAA0D;IAC1D,UAAU,EAAE,YAAY;IACxB,8DAA8D;IAC9D,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,kEAAkE;IAClE,UAAU,EAAE,aAAa;IACzB;;;;OAIG;IACH,OAAO,EAAE,SAAS;IAClB;;;;;OAKG;IACH,aAAa,EAAE,gBAAgB;IAC/B;;;;;OAKG;IACH,eAAe,EAAE,kBAAkB;IACnC;;;;;;OAMG;IACH,UAAU,EAAE,aAAa;CACjB,CAAC;AAIX;;;;GAIG;AACH,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAU,CAAC;AAG9E,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC3F,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.7.0";
|
|
3
3
|
export { EntryType, isBatchOrigin } from './entry.js';
|
|
4
4
|
export type { BatchOrigin, BuiltinEntryType, Entry, RecordInput } from './entry.js';
|
|
5
5
|
export type { EntryQuery, TelescopeStore } from './store.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.7.0';
|
|
3
3
|
// — entry model —
|
|
4
4
|
export { EntryType, isBatchOrigin } from './entry.js';
|
|
5
5
|
export { InMemoryTelescopeStore } from './stores/memory.js';
|
package/dist/src/mcp/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.7.0";
|
|
3
3
|
export { defineConfig, resolveConfig, MCP_TOOL_NAMES } from './define_config.js';
|
|
4
4
|
export type { McpToolName, ResolvedTelescopeMcpConfig, TelescopeMcpConfig, } from './define_config.js';
|
|
5
5
|
export { MCP_INTERNAL_ERROR, MCP_METHOD_NOT_FOUND, MCP_TOOLS, MCP_UNAUTHORIZED, TelescopeMcpServer, } from './server.js';
|
package/dist/src/mcp/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.7.0';
|
|
3
3
|
// — config —
|
|
4
4
|
export { defineConfig, resolveConfig, MCP_TOOL_NAMES } from './define_config.js';
|
|
5
5
|
// — server (plain, testable JSON-RPC surface) —
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FlameNode, HotFrame, V8CpuProfile } from './types.js';
|
|
2
|
+
interface Aggregated {
|
|
3
|
+
tree: FlameNode;
|
|
4
|
+
durationMs: number;
|
|
5
|
+
sampleCount: number;
|
|
6
|
+
hot: HotFrame[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Aggregates a raw V8 CPU profile into a flamegraph frame tree with self/total
|
|
10
|
+
* time in milliseconds. Pure and deterministic — no inspector dependency, so it
|
|
11
|
+
* is trivially unit-testable and runs OUTSIDE any hot path (only when a capture
|
|
12
|
+
* actually completes).
|
|
13
|
+
*
|
|
14
|
+
* Method: each sample's `timeDelta` (microseconds) is charged to the SELF time
|
|
15
|
+
* of the node it landed on. Total time is then the sum of a node's self time and
|
|
16
|
+
* its descendants', computed by a single post-order walk. The flame tree mirrors
|
|
17
|
+
* V8's `children` call-graph so callers nest exactly as they did at runtime.
|
|
18
|
+
*/
|
|
19
|
+
export declare function aggregateCpuProfile(profile: V8CpuProfile): Aggregated;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=aggregate-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-profile.d.ts","sourceRoot":"","sources":["../../../src/profiling/aggregate-profile.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAiB,MAAM,YAAY,CAAC;AAQnF,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CA2FrE"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** How many hottest-by-self frames to precompute for the dashboard. */
|
|
2
|
+
const HOT_FRAME_LIMIT = 12;
|
|
3
|
+
/** The synthetic root name V8 uses; we keep/normalize to it. */
|
|
4
|
+
const ROOT_NAME = '(root)';
|
|
5
|
+
/**
|
|
6
|
+
* Aggregates a raw V8 CPU profile into a flamegraph frame tree with self/total
|
|
7
|
+
* time in milliseconds. Pure and deterministic — no inspector dependency, so it
|
|
8
|
+
* is trivially unit-testable and runs OUTSIDE any hot path (only when a capture
|
|
9
|
+
* actually completes).
|
|
10
|
+
*
|
|
11
|
+
* Method: each sample's `timeDelta` (microseconds) is charged to the SELF time
|
|
12
|
+
* of the node it landed on. Total time is then the sum of a node's self time and
|
|
13
|
+
* its descendants', computed by a single post-order walk. The flame tree mirrors
|
|
14
|
+
* V8's `children` call-graph so callers nest exactly as they did at runtime.
|
|
15
|
+
*/
|
|
16
|
+
export function aggregateCpuProfile(profile) {
|
|
17
|
+
const byId = new Map();
|
|
18
|
+
for (const node of profile.nodes)
|
|
19
|
+
byId.set(node.id, node);
|
|
20
|
+
// 1. Charge each sample's time delta to its node's self time (microseconds).
|
|
21
|
+
const selfMicros = new Map();
|
|
22
|
+
const selfSamples = new Map();
|
|
23
|
+
const samples = profile.samples ?? [];
|
|
24
|
+
const deltas = profile.timeDeltas ?? [];
|
|
25
|
+
let totalMicros = 0;
|
|
26
|
+
for (let i = 0; i < samples.length; i++) {
|
|
27
|
+
const id = samples[i];
|
|
28
|
+
if (id === undefined)
|
|
29
|
+
continue;
|
|
30
|
+
// V8 emits one delta per sample (the time elapsed before that sample). Fall
|
|
31
|
+
// back to 0 if the arrays are mismatched rather than guessing.
|
|
32
|
+
const delta = deltas[i] ?? 0;
|
|
33
|
+
totalMicros += delta;
|
|
34
|
+
selfMicros.set(id, (selfMicros.get(id) ?? 0) + delta);
|
|
35
|
+
selfSamples.set(id, (selfSamples.get(id) ?? 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
// 2. Find (or synthesize) the root. V8 puts the (root) node first; tolerate
|
|
38
|
+
// its absence by stitching all top-level nodes under a synthetic root.
|
|
39
|
+
const rootNode = profile.nodes.find((n) => n.callFrame.functionName === ROOT_NAME);
|
|
40
|
+
const build = (node) => {
|
|
41
|
+
const childIds = node.children ?? [];
|
|
42
|
+
const children = [];
|
|
43
|
+
for (const childId of childIds) {
|
|
44
|
+
const child = byId.get(childId);
|
|
45
|
+
if (child)
|
|
46
|
+
children.push(build(child));
|
|
47
|
+
}
|
|
48
|
+
const self = (selfMicros.get(node.id) ?? 0) / 1000;
|
|
49
|
+
const selfCount = selfSamples.get(node.id) ?? 0;
|
|
50
|
+
const childTotal = children.reduce((sum, c) => sum + c.totalMs, 0);
|
|
51
|
+
const childSamples = children.reduce((sum, c) => sum + c.totalSamples, 0);
|
|
52
|
+
return {
|
|
53
|
+
name: normalizeName(node.callFrame.functionName),
|
|
54
|
+
file: frameFile(node),
|
|
55
|
+
selfMs: self,
|
|
56
|
+
totalMs: self + childTotal,
|
|
57
|
+
totalSamples: selfCount + childSamples,
|
|
58
|
+
children,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
let tree;
|
|
62
|
+
if (rootNode) {
|
|
63
|
+
tree = build(rootNode);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// No explicit root: every node referenced as a child belongs to a parent;
|
|
67
|
+
// top-level nodes are those never referenced. Stitch them under a synthetic root.
|
|
68
|
+
const referenced = new Set();
|
|
69
|
+
for (const node of profile.nodes) {
|
|
70
|
+
for (const childId of node.children ?? [])
|
|
71
|
+
referenced.add(childId);
|
|
72
|
+
}
|
|
73
|
+
const tops = profile.nodes.filter((n) => !referenced.has(n.id)).map(build);
|
|
74
|
+
const childTotal = tops.reduce((sum, c) => sum + c.totalMs, 0);
|
|
75
|
+
tree = {
|
|
76
|
+
name: ROOT_NAME,
|
|
77
|
+
file: '',
|
|
78
|
+
selfMs: 0,
|
|
79
|
+
totalMs: childTotal,
|
|
80
|
+
totalSamples: tops.reduce((sum, c) => sum + c.totalSamples, 0),
|
|
81
|
+
children: tops,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// 3. Hot frames by self time (flatten, sort desc, take N).
|
|
85
|
+
const totalMs = totalMicros / 1000;
|
|
86
|
+
const flat = [];
|
|
87
|
+
const visit = (node) => {
|
|
88
|
+
if (node.selfMs > 0) {
|
|
89
|
+
flat.push({
|
|
90
|
+
name: node.name,
|
|
91
|
+
file: node.file,
|
|
92
|
+
selfMs: node.selfMs,
|
|
93
|
+
selfPct: totalMs > 0 ? (node.selfMs / totalMs) * 100 : 0,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
for (const child of node.children)
|
|
97
|
+
visit(child);
|
|
98
|
+
};
|
|
99
|
+
visit(tree);
|
|
100
|
+
flat.sort((a, b) => b.selfMs - a.selfMs);
|
|
101
|
+
return {
|
|
102
|
+
tree,
|
|
103
|
+
durationMs: durationFor(profile, totalMicros),
|
|
104
|
+
sampleCount: samples.length,
|
|
105
|
+
hot: flat.slice(0, HOT_FRAME_LIMIT),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Prefer the summed sample deltas; fall back to start/end when samples absent. */
|
|
109
|
+
function durationFor(profile, totalMicros) {
|
|
110
|
+
if (totalMicros > 0)
|
|
111
|
+
return totalMicros / 1000;
|
|
112
|
+
const wall = profile.endTime - profile.startTime;
|
|
113
|
+
return wall > 0 ? wall / 1000 : 0;
|
|
114
|
+
}
|
|
115
|
+
function normalizeName(name) {
|
|
116
|
+
return name === '' ? '(anonymous)' : name;
|
|
117
|
+
}
|
|
118
|
+
function frameFile(node) {
|
|
119
|
+
const { url, lineNumber } = node.callFrame;
|
|
120
|
+
if (url === '')
|
|
121
|
+
return '';
|
|
122
|
+
return lineNumber >= 0 ? `${url}:${lineNumber + 1}` : url;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=aggregate-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-profile.js","sourceRoot":"","sources":["../../../src/profiling/aggregate-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { FlameNode, HotFrame } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The slice of `inspector.Session` we depend on. Declared structurally so the
|
|
4
|
+
* profiler can be unit-tested with a fake and — crucially — so the real
|
|
5
|
+
* `node:inspector` module is NEVER imported at module load. It is required
|
|
6
|
+
* lazily by {@link defaultSessionFactory} ONLY when a capture actually starts.
|
|
7
|
+
*/
|
|
8
|
+
export interface InspectorSessionLike {
|
|
9
|
+
connect(): void;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
post(method: string, paramsOrCallback?: unknown | ((err: Error | null, result?: unknown) => void), callback?: (err: Error | null, result?: unknown) => void): void;
|
|
12
|
+
}
|
|
13
|
+
export type SessionFactory = () => InspectorSessionLike;
|
|
14
|
+
export interface CpuProfilerOptions {
|
|
15
|
+
/**
|
|
16
|
+
* V8 sampling interval in microseconds. Lower = finer-grained but more
|
|
17
|
+
* overhead. V8's default is 1000µs (1ms); we keep that default.
|
|
18
|
+
*/
|
|
19
|
+
samplingIntervalMicros?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface CpuProfilerResult {
|
|
22
|
+
tree: FlameNode;
|
|
23
|
+
durationMs: number;
|
|
24
|
+
sampleCount: number;
|
|
25
|
+
hot: HotFrame[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wraps a V8 CPU profiling session over the inspector protocol. A single
|
|
29
|
+
* profiler instance captures ONE profile at a time (`start` then `stop`).
|
|
30
|
+
*
|
|
31
|
+
* OVERHEAD GUARANTEE: constructing a profiler does no work and creates no
|
|
32
|
+
* session. The inspector session is created (and `node:inspector` is required)
|
|
33
|
+
* only inside `start()`. When profiling is disabled the controller never
|
|
34
|
+
* constructs one, so there is provably zero inspector activity.
|
|
35
|
+
*/
|
|
36
|
+
export declare class CpuProfiler {
|
|
37
|
+
private readonly sessionFactory;
|
|
38
|
+
private session;
|
|
39
|
+
private running;
|
|
40
|
+
private readonly intervalMicros;
|
|
41
|
+
constructor(sessionFactory?: SessionFactory, options?: CpuProfilerOptions);
|
|
42
|
+
get isRunning(): boolean;
|
|
43
|
+
/** Begin a CPU profile. No-op if one is already running. */
|
|
44
|
+
start(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Stop the profile and aggregate it into a flame tree. Returns `null` when no
|
|
47
|
+
* profile is running. Always disconnects the session, even on error.
|
|
48
|
+
*/
|
|
49
|
+
stop(): Promise<CpuProfilerResult | null>;
|
|
50
|
+
private postAsync;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Lazily require `node:inspector` and return a fresh Session. Kept out of the
|
|
54
|
+
* module's import graph so that importing this file (or the whole package) does
|
|
55
|
+
* NOT load the inspector binding — that only happens the first time a capture
|
|
56
|
+
* starts, i.e. only when profiling is enabled AND a request is sampled.
|
|
57
|
+
*/
|
|
58
|
+
export declare function defaultSessionFactory(): InspectorSessionLike;
|
|
59
|
+
//# sourceMappingURL=cpu-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu-profiler.d.ts","sourceRoot":"","sources":["../../../src/profiling/cpu-profiler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,IAAI,IAAI,CAAC;IACnB,IAAI,CACF,MAAM,EAAE,MAAM,EACd,gBAAgB,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,EAC5E,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,GACvD,IAAI,CAAC;CACT;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB;AAID;;;;;;;;GAQG;AACH,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,cAAc;IALjC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAGrB,cAAc,GAAE,cAAsC,EACvE,OAAO,GAAE,kBAAuB;IAKlC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,4DAA4D;IACtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAmB/C,OAAO,CAAC,SAAS;CAclB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAS5D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Ported near-verbatim (only the import path changed) from `nestjs-telescope`'s
|
|
2
|
+
// `packages/core/src/profiling/cpu-profiler.ts`. `node:inspector`'s Session API is a Node.js
|
|
3
|
+
// built-in, identical under NestJS or AdonisJS — this file has NO framework glue at all.
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { aggregateCpuProfile } from './aggregate-profile.js';
|
|
6
|
+
const DEFAULT_SAMPLING_INTERVAL_MICROS = 1000;
|
|
7
|
+
/**
|
|
8
|
+
* Wraps a V8 CPU profiling session over the inspector protocol. A single
|
|
9
|
+
* profiler instance captures ONE profile at a time (`start` then `stop`).
|
|
10
|
+
*
|
|
11
|
+
* OVERHEAD GUARANTEE: constructing a profiler does no work and creates no
|
|
12
|
+
* session. The inspector session is created (and `node:inspector` is required)
|
|
13
|
+
* only inside `start()`. When profiling is disabled the controller never
|
|
14
|
+
* constructs one, so there is provably zero inspector activity.
|
|
15
|
+
*/
|
|
16
|
+
export class CpuProfiler {
|
|
17
|
+
sessionFactory;
|
|
18
|
+
session = null;
|
|
19
|
+
running = false;
|
|
20
|
+
intervalMicros;
|
|
21
|
+
constructor(sessionFactory = defaultSessionFactory, options = {}) {
|
|
22
|
+
this.sessionFactory = sessionFactory;
|
|
23
|
+
this.intervalMicros = options.samplingIntervalMicros ?? DEFAULT_SAMPLING_INTERVAL_MICROS;
|
|
24
|
+
}
|
|
25
|
+
get isRunning() {
|
|
26
|
+
return this.running;
|
|
27
|
+
}
|
|
28
|
+
/** Begin a CPU profile. No-op if one is already running. */
|
|
29
|
+
async start() {
|
|
30
|
+
if (this.running)
|
|
31
|
+
return;
|
|
32
|
+
const session = this.sessionFactory();
|
|
33
|
+
session.connect();
|
|
34
|
+
this.session = session;
|
|
35
|
+
await this.postAsync(session, 'Profiler.enable');
|
|
36
|
+
await this.postAsync(session, 'Profiler.setSamplingInterval', {
|
|
37
|
+
interval: this.intervalMicros,
|
|
38
|
+
});
|
|
39
|
+
await this.postAsync(session, 'Profiler.start');
|
|
40
|
+
this.running = true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Stop the profile and aggregate it into a flame tree. Returns `null` when no
|
|
44
|
+
* profile is running. Always disconnects the session, even on error.
|
|
45
|
+
*/
|
|
46
|
+
async stop() {
|
|
47
|
+
const session = this.session;
|
|
48
|
+
if (!this.running || session === null)
|
|
49
|
+
return null;
|
|
50
|
+
try {
|
|
51
|
+
const result = (await this.postAsync(session, 'Profiler.stop'));
|
|
52
|
+
return aggregateCpuProfile(result.profile);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
this.running = false;
|
|
56
|
+
this.session = null;
|
|
57
|
+
try {
|
|
58
|
+
session.disconnect();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// A disconnect failure must never mask the captured profile or throw.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
postAsync(session, method, params) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const cb = (err, result) => {
|
|
68
|
+
if (err)
|
|
69
|
+
reject(err);
|
|
70
|
+
else
|
|
71
|
+
resolve(result);
|
|
72
|
+
};
|
|
73
|
+
if (params === undefined)
|
|
74
|
+
session.post(method, cb);
|
|
75
|
+
else
|
|
76
|
+
session.post(method, params, cb);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Lazily require `node:inspector` and return a fresh Session. Kept out of the
|
|
82
|
+
* module's import graph so that importing this file (or the whole package) does
|
|
83
|
+
* NOT load the inspector binding — that only happens the first time a capture
|
|
84
|
+
* starts, i.e. only when profiling is enabled AND a request is sampled.
|
|
85
|
+
*/
|
|
86
|
+
export function defaultSessionFactory() {
|
|
87
|
+
// `createRequire` performs a SYNCHRONOUS require of the built-in without it
|
|
88
|
+
// appearing in this module's static import graph, so loading the package never
|
|
89
|
+
// pulls in the inspector binding. Built only on first capture.
|
|
90
|
+
const requireFn = createRequire(import.meta.url);
|
|
91
|
+
const inspector = requireFn('node:inspector');
|
|
92
|
+
return new inspector.Session();
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=cpu-profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu-profiler.js","sourceRoot":"","sources":["../../../src/profiling/cpu-profiler.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,6FAA6F;AAC7F,yFAAyF;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAoC7D,MAAM,gCAAgC,GAAG,IAAI,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IAMH;IALX,OAAO,GAAgC,IAAI,CAAC;IAC5C,OAAO,GAAG,KAAK,CAAC;IACP,cAAc,CAAS;IAExC,YACmB,iBAAiC,qBAAqB,EACvE,UAA8B,EAAE;QADf,mBAAc,GAAd,cAAc,CAAwC;QAGvE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,sBAAsB,IAAI,gCAAgC,CAAC;IAC3F,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QACjD,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,8BAA8B,EAAE;YAC5D,QAAQ,EAAE,IAAI,CAAC,cAAc;SAC9B,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC,CAE7D,CAAC;YACF,OAAO,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,sEAAsE;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,SAAS,CACf,OAA6B,EAC7B,MAAc,EACd,MAAgB;QAEhB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,EAAE,GAAG,CAAC,GAAiB,EAAE,MAAgB,EAAQ,EAAE;gBACvD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC,CAAC;YACF,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;;gBAC9C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,4EAA4E;IAC5E,+EAA+E;IAC/E,+DAA+D;IAC/D,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,SAAS,CAAC,gBAAgB,CAE3C,CAAC;IACF,OAAO,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape of `config/telescope_cpu_profiling.ts`. Mirrors `nestjs-telescope`'s
|
|
3
|
+
* `profiling-config.ts` (`ResolvedProfilingConfig`) — the knobs are framework-agnostic (they gate a
|
|
4
|
+
* `node:inspector` capture, not anything NestJS/AdonisJS-specific).
|
|
5
|
+
*/
|
|
6
|
+
export interface TelescopeCpuProfilingConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Master switch. CPU profiling carries real overhead (a running V8 sampling
|
|
9
|
+
* profiler slows the process it profiles), so it is OFF by default — opt in
|
|
10
|
+
* explicitly. When `false` the middleware hook is a single boolean check and
|
|
11
|
+
* `node:inspector` is never required. Default `false`.
|
|
12
|
+
*/
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Fraction (0–1) of requests to automatically capture. `0` (the default) means
|
|
16
|
+
* captures only happen when armed via `POST <path>/api/profiles/arm`.
|
|
17
|
+
*/
|
|
18
|
+
sampleRate?: number;
|
|
19
|
+
/** Maximum concurrent captures. Keeps overhead bounded under load. Default 2. */
|
|
20
|
+
maxConcurrent?: number;
|
|
21
|
+
/** Captures shorter than this are discarded (not worth an entry). Default 5. */
|
|
22
|
+
minDurationMs?: number;
|
|
23
|
+
/** V8 sampling interval in microseconds (lower = finer-grained, more overhead). Default 1000. */
|
|
24
|
+
samplingIntervalMicros?: number;
|
|
25
|
+
}
|
|
26
|
+
/** The fully-resolved config the provider + `ProfilerService` act on (no optionals). */
|
|
27
|
+
export interface ResolvedTelescopeCpuProfilingConfig {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
sampleRate: number;
|
|
30
|
+
maxConcurrent: number;
|
|
31
|
+
minDurationMs: number;
|
|
32
|
+
samplingIntervalMicros: number;
|
|
33
|
+
}
|
|
34
|
+
/** Identity helper giving `config/telescope_cpu_profiling.ts` full type-checking. */
|
|
35
|
+
export declare function defineConfig(config: TelescopeCpuProfilingConfig): TelescopeCpuProfilingConfig;
|
|
36
|
+
/** Apply defaults to a (possibly partial) config. */
|
|
37
|
+
export declare function resolveConfig(config?: TelescopeCpuProfilingConfig): ResolvedTelescopeCpuProfilingConfig;
|
|
38
|
+
//# sourceMappingURL=define_config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/profiling/define_config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iGAAiG;IACjG,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wFAAwF;AACxF,MAAM,WAAW,mCAAmC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAMD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,MAAM,EAAE,2BAA2B,GAAG,2BAA2B,CAE7F;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAC3B,MAAM,GAAE,2BAAgC,GACvC,mCAAmC,CAWrC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const DEFAULT_MAX_CONCURRENT = 2;
|
|
2
|
+
const DEFAULT_MIN_DURATION_MS = 5;
|
|
3
|
+
const DEFAULT_SAMPLING_INTERVAL_MICROS = 1000;
|
|
4
|
+
/** Identity helper giving `config/telescope_cpu_profiling.ts` full type-checking. */
|
|
5
|
+
export function defineConfig(config) {
|
|
6
|
+
return config;
|
|
7
|
+
}
|
|
8
|
+
/** Apply defaults to a (possibly partial) config. */
|
|
9
|
+
export function resolveConfig(config = {}) {
|
|
10
|
+
return {
|
|
11
|
+
enabled: config.enabled ?? false,
|
|
12
|
+
sampleRate: clamp01(config.sampleRate ?? 0),
|
|
13
|
+
maxConcurrent: Math.max(1, Math.floor(config.maxConcurrent ?? DEFAULT_MAX_CONCURRENT)),
|
|
14
|
+
minDurationMs: Math.max(0, config.minDurationMs ?? DEFAULT_MIN_DURATION_MS),
|
|
15
|
+
samplingIntervalMicros: Math.max(100, Math.floor(config.samplingIntervalMicros ?? DEFAULT_SAMPLING_INTERVAL_MICROS)),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function clamp01(value) {
|
|
19
|
+
if (!Number.isFinite(value))
|
|
20
|
+
return 0;
|
|
21
|
+
return Math.min(1, Math.max(0, value));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=define_config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/profiling/define_config.ts"],"names":[],"mappings":"AAmCA,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAClC,MAAM,gCAAgC,GAAG,IAAI,CAAC;AAE9C,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,MAAmC;IAC9D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAC3B,SAAsC,EAAE;IAExC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;QAChC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;QAC3C,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,IAAI,sBAAsB,CAAC,CAAC;QACtF,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,IAAI,uBAAuB,CAAC;QAC3E,sBAAsB,EAAE,IAAI,CAAC,GAAG,CAC9B,GAAG,EACH,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,IAAI,gCAAgC,CAAC,CAC9E;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,KAAa;IAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
+
export declare const VERSION = "0.7.0";
|
|
3
|
+
export { defineConfig, resolveConfig } from './define_config.js';
|
|
4
|
+
export type { ResolvedTelescopeCpuProfilingConfig, TelescopeCpuProfilingConfig, } from './define_config.js';
|
|
5
|
+
export { CPU_PROFILE_ENTRY_TYPE, ProfilerService, } from './profiler_service.js';
|
|
6
|
+
export type { ProfileHandle, ProfilerLike, ProfilerServiceDeps, ProfilerStatus, } from './profiler_service.js';
|
|
7
|
+
export { CpuProfiler, defaultSessionFactory } from './cpu-profiler.js';
|
|
8
|
+
export type { CpuProfilerOptions, CpuProfilerResult, InspectorSessionLike, SessionFactory, } from './cpu-profiler.js';
|
|
9
|
+
export { aggregateCpuProfile } from './aggregate-profile.js';
|
|
10
|
+
export type { CpuProfileContent, FlameNode, HotFrame, V8CpuProfile, V8ProfileNode, } from './types.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/profiling/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EACV,mCAAmC,EACnC,2BAA2B,GAC5B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,sBAAsB,EACtB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,cAAc,GACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACvE,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
+
export const VERSION = '0.7.0';
|
|
3
|
+
export { defineConfig, resolveConfig } from './define_config.js';
|
|
4
|
+
export { CPU_PROFILE_ENTRY_TYPE, ProfilerService, } from './profiler_service.js';
|
|
5
|
+
export { CpuProfiler, defaultSessionFactory } from './cpu-profiler.js';
|
|
6
|
+
export { aggregateCpuProfile } from './aggregate-profile.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/profiling/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMjE,OAAO,EACL,sBAAsB,EACtB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAQ/B,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAQvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type RecordInput } from '../entry.js';
|
|
2
|
+
import { type CpuProfilerResult } from './cpu-profiler.js';
|
|
3
|
+
import type { ResolvedTelescopeCpuProfilingConfig } from './define_config.js';
|
|
4
|
+
import type { CpuProfileContent } from './types.js';
|
|
5
|
+
/** The `type` of the entries this service records. */
|
|
6
|
+
export declare const CPU_PROFILE_ENTRY_TYPE: "cpu_profile";
|
|
7
|
+
/** Opaque handle for an in-flight capture, returned by {@link ProfilerService.begin}. */
|
|
8
|
+
export interface ProfileHandle {
|
|
9
|
+
readonly profiler: ProfilerLike;
|
|
10
|
+
readonly startedAt: number;
|
|
11
|
+
readonly reason: 'manual' | 'sampled';
|
|
12
|
+
/**
|
|
13
|
+
* The (fire-and-forget) start promise. {@link ProfilerService.end} awaits it
|
|
14
|
+
* before calling `stop()` so a capture that ends before `start()` settled (a
|
|
15
|
+
* very fast request, or a synchronous test) is still stopped correctly rather
|
|
16
|
+
* than seeing `isRunning === false` and silently dropping the profile.
|
|
17
|
+
*/
|
|
18
|
+
readonly started: Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Minimal profiler contract so the service can be tested with a fake. */
|
|
21
|
+
export interface ProfilerLike {
|
|
22
|
+
readonly isRunning: boolean;
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
stop(): Promise<CpuProfilerResult | null>;
|
|
25
|
+
}
|
|
26
|
+
export interface ProfilerServiceDeps {
|
|
27
|
+
/** RNG for sampling — injectable for deterministic tests. */
|
|
28
|
+
random?: () => number;
|
|
29
|
+
/** Builds a profiler; injectable so tests avoid the real inspector. */
|
|
30
|
+
profilerFactory?: () => ProfilerLike;
|
|
31
|
+
/** Records the finished profile; injectable for tests. Defaults to `safeRecord`
|
|
32
|
+
* through the runtime store slot (mirrors every other watcher). */
|
|
33
|
+
record?: (input: RecordInput<CpuProfileContent>) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface ProfilerStatus {
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
sampleRate: number;
|
|
38
|
+
/** Currently in-flight captures. */
|
|
39
|
+
active: number;
|
|
40
|
+
maxConcurrent: number;
|
|
41
|
+
/** Remaining manual budget across all arms. */
|
|
42
|
+
pendingManual: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Decides whether to profile a request and drives the capture lifecycle around
|
|
46
|
+
* it. {@link TelescopeMiddleware} calls {@link shouldProfile} (cheap gate), then
|
|
47
|
+
* {@link begin}/{@link end} around the request body — ported near-verbatim from
|
|
48
|
+
* `nestjs-telescope`'s `ProfilerService`; only the recording seam changed (fire-and-forget
|
|
49
|
+
* `safeRecord` through the runtime store slot, matching every other Adonis watcher, instead of a
|
|
50
|
+
* NestJS-injected recorder).
|
|
51
|
+
*
|
|
52
|
+
* OVERHEAD: while disabled, {@link shouldProfile} returns false and {@link begin}
|
|
53
|
+
* returns null after a single boolean check — no profiler is ever constructed
|
|
54
|
+
* and `node:inspector` is never required. While enabled but a request isn't
|
|
55
|
+
* selected, the only added cost is the gate and (if sampling) one RNG call.
|
|
56
|
+
*/
|
|
57
|
+
export declare class ProfilerService {
|
|
58
|
+
private readonly config;
|
|
59
|
+
private active;
|
|
60
|
+
private readonly manual;
|
|
61
|
+
private readonly random;
|
|
62
|
+
private readonly profilerFactory;
|
|
63
|
+
private readonly recordFn;
|
|
64
|
+
constructor(config: ResolvedTelescopeCpuProfilingConfig, deps?: ProfilerServiceDeps);
|
|
65
|
+
/**
|
|
66
|
+
* Arm a manual capture for the next `count` requests (optionally only those
|
|
67
|
+
* matching `label`). Returns the pending budget. No-op when disabled.
|
|
68
|
+
*/
|
|
69
|
+
arm(arm: {
|
|
70
|
+
count: number;
|
|
71
|
+
label?: string;
|
|
72
|
+
}): {
|
|
73
|
+
pendingManual: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Whether this request should be profiled. Consults the manual arm budget
|
|
77
|
+
* first (targeted captures win), then sampling. Cheap and side-effect-free
|
|
78
|
+
* EXCEPT it does not yet consume the manual budget — that happens in
|
|
79
|
+
* {@link begin} so a request rejected by the concurrency cap doesn't waste it.
|
|
80
|
+
*/
|
|
81
|
+
shouldProfile(label: string | null): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Begin a capture for a request that {@link shouldProfile} accepted. Returns a
|
|
84
|
+
* handle to pass to {@link end}, or `null` if the request should not be
|
|
85
|
+
* profiled (disabled, concurrency cap reached, or not selected). The caller
|
|
86
|
+
* MUST treat a null handle as "no profiling" and proceed untouched.
|
|
87
|
+
*/
|
|
88
|
+
begin(label: string | null): ProfileHandle | null;
|
|
89
|
+
/**
|
|
90
|
+
* Stop a capture and record it as a `cpu_profile` entry. Safe to call with a
|
|
91
|
+
* null handle (no-op). Never throws into the host request path. Captures below
|
|
92
|
+
* the `minDurationMs` floor are discarded.
|
|
93
|
+
*/
|
|
94
|
+
end(handle: ProfileHandle | null, label: string | null): Promise<void>;
|
|
95
|
+
status(): ProfilerStatus;
|
|
96
|
+
private pendingManual;
|
|
97
|
+
/** First arm matching this label (labelled arms require an exact match). */
|
|
98
|
+
private matchingArm;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=profiler_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler_service.d.ts","sourceRoot":"","sources":["../../../src/profiling/profiler_service.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,eAAuB,CAAC;AAE3D,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CAC3C;AASD,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,YAAY,CAAC;IACrC;wEACoE;IACpE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAe;IAQxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkD;gBAGxD,MAAM,EAAE,mCAAmC,EAC5D,IAAI,GAAE,mBAAwB;IAShC;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE;IAOtE;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAO5C;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI;IAuBjD;;;;OAIG;IACG,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC5E,MAAM,IAAI,cAAc;IAUxB,OAAO,CAAC,aAAa;IAIrB,4EAA4E;IAC5E,OAAO,CAAC,WAAW;CAQpB"}
|