@nestrix-js/mcp 0.0.0-stage → 0.1.0-alpha.3

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AASA,qGAAqG;AACrG,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,GAAG,aAAa,CAAC;CAC/B;AAED,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,2FAA2F;AAC3F,MAAM,UAAU,UAAU,CACxB,GAAiD;IAEjD,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,WAAW,CACnB,oLAAoL,CACrL,CAAC;IACJ,CAAC;IACD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,mCAAmC,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,WAAW,CAAC,kDAAkD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,WAAW,CACnB,uFAAuF,CACxF,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAElD,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,WAAW,CACnB,4NAA4N,CAC7N,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,WAAW,CACnB,wLAAwL,CACzL,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,GAAG,kBAAkB,CAAC;IACnC,MAAM,UAAU,GAAG,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,WAAW,CACnB,mFAAmF,CACpF,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AACnC,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACnC,OAAO,CACL,IAAI,KAAK,WAAW;YACpB,IAAI,KAAK,OAAO;YAChB,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC9C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ConfigError, loadConfig, type McpConfig } from "./config.js";
2
+ export { createMcpServer, type McpServerOptions } from "./tools.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ConfigError, loadConfig } from "./config.js";
2
+ export { createMcpServer } from "./tools.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,eAAe,EAAyB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { RouteStats, TraceResponse, TraceSummary } from "@nestrix-js/protocol";
2
+ export interface ExplainInput {
3
+ route: string;
4
+ method?: string | undefined;
5
+ windowMinutes: number;
6
+ /** Statistics entries of the route (one per method). */
7
+ stats: RouteStats[];
8
+ /** Every stored trace summary of the route that matched, any order. */
9
+ summaries: TraceSummary[];
10
+ /** The slowest of them, in full. */
11
+ traces: TraceResponse[];
12
+ /** Routes that do have statistics, for a hint when `stats` is empty. */
13
+ knownRoutes: string[];
14
+ }
15
+ export declare const EXPLAIN_TRACES = 5;
16
+ /** Ranked summary of why a route is slow: statistics, then where the self time of its slowest stored traces goes. */
17
+ export declare function renderExplanation(input: ExplainInput): string;
@@ -0,0 +1,113 @@
1
+ import { clean, fmtMs, fmtPct, plural, truncate } from "./format.js";
2
+ import { buildTree, classOf, repeatedStatements, statementOf, } from "./trace.js";
3
+ export const EXPLAIN_TRACES = 5;
4
+ /** Ranked summary of why a route is slow: statistics, then where the self time of its slowest stored traces goes. */
5
+ export function renderExplanation(input) {
6
+ const label = clean(input.method ? `${input.method} ${input.route}` : input.route, 160);
7
+ const lines = [];
8
+ if (input.stats.length === 0) {
9
+ lines.push(`No statistics for ${label} in the last ${input.windowMinutes} minutes (no requests, or the route template differs).`);
10
+ if (input.knownRoutes.length > 0) {
11
+ lines.push(`Routes with statistics: ${input.knownRoutes
12
+ .slice(0, 10)
13
+ .map((r) => clean(r, 120))
14
+ .join(", ")}${input.knownRoutes.length > 10 ? ", ..." : ""}. The route is the template, for example /users/:id.`);
15
+ }
16
+ }
17
+ else {
18
+ lines.push(`Why is ${label} slow? Last ${input.windowMinutes} minutes, every request counted:`);
19
+ for (const s of [...input.stats].sort((a, b) => a.method < b.method ? -1 : 1)) {
20
+ lines.push(`- ${clean(`${s.method} ${s.route}`, 160)}: ${plural(s.count, "request")}, ${plural(s.errors, "error")}, p50 ${fmtMs(s.p50Ms)}, p95 ${fmtMs(s.p95Ms)}, p99 ${fmtMs(s.p99Ms)}, max ${fmtMs(s.maxMs)}`);
21
+ }
22
+ }
23
+ if (input.traces.length === 0) {
24
+ lines.push("", "No stored traces for this route (traces are sampled and kept in memory), so the time cannot be broken down. Statistics above still count every request.");
25
+ return lines.join("\n");
26
+ }
27
+ const trees = input.traces.map((t) => ({ trace: t, tree: buildTree(t) }));
28
+ const bySpan = new Map();
29
+ const byClass = new Map();
30
+ let totalSelf = 0;
31
+ let totalMs = 0;
32
+ const allRepeated = [];
33
+ for (const { tree } of trees) {
34
+ totalMs += tree.traceMs;
35
+ for (const span of tree.spans) {
36
+ const self = tree.selfMs.get(span.spanId) ?? 0;
37
+ totalSelf += self;
38
+ const kind = statementOf(span) !== undefined ? "db" : clean(span.kind, 24);
39
+ const name = clean(span.name, 100);
40
+ const key = `${name}\u0000${kind}`;
41
+ const b = bySpan.get(key) ?? { name, selfMs: 0, calls: 0, kind };
42
+ b.selfMs += self;
43
+ b.calls++;
44
+ bySpan.set(key, b);
45
+ const cls = classOf(span);
46
+ if (cls !== undefined) {
47
+ const c = byClass.get(cls) ?? {
48
+ name: clean(cls, 80),
49
+ selfMs: 0,
50
+ calls: 0,
51
+ };
52
+ c.selfMs += self;
53
+ c.calls++;
54
+ byClass.set(cls, c);
55
+ }
56
+ }
57
+ allRepeated.push(...repeatedStatements(tree.spans, tree.byId));
58
+ }
59
+ const rank = (a, b) => b.selfMs - a.selfMs || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
60
+ const spanRank = [...bySpan.values()].sort(rank);
61
+ const classRank = [...byClass.values()].sort(rank);
62
+ const durations = input.traces
63
+ .map((t) => fmtMs(buildTree(t).traceMs))
64
+ .join(", ");
65
+ lines.push("", `Analysed the ${plural(input.traces.length, "slowest stored trace")} of ${input.summaries.length} for this route (${durations}); ${fmtMs(totalMs)} in total.`, "Where the time goes (self time = duration minus time in child spans, summed over those traces):");
66
+ spanRank.slice(0, 8).forEach((b, i) => {
67
+ lines.push(`${i + 1}. ${b.name} [${b.kind}]: ${fmtMs(b.selfMs)} (${fmtPct(b.selfMs, totalSelf)}) over ${plural(b.calls, "call")}`);
68
+ });
69
+ if (classRank.length > 0) {
70
+ lines.push("", "By class (self time of its method spans):");
71
+ classRank.slice(0, 5).forEach((c, i) => {
72
+ lines.push(`${i + 1}. ${c.name}: ${fmtMs(c.selfMs)} (${fmtPct(c.selfMs, totalSelf)}) over ${plural(c.calls, "call")}`);
73
+ });
74
+ }
75
+ const merged = mergeRepeated(allRepeated);
76
+ if (merged.length > 0) {
77
+ lines.push("", "Repeated statements (3 or more times in one trace):");
78
+ for (const r of merged.slice(0, 5)) {
79
+ lines.push(`- ${r.count}x ${truncate(r.statement, 160)} (${fmtMs(r.totalMs)} total)`);
80
+ }
81
+ }
82
+ const top = spanRank[0];
83
+ const summary = [];
84
+ if (top) {
85
+ summary.push(`most self time is in "${truncate(top.name, 80)}" (${fmtPct(top.selfMs, totalSelf)})`);
86
+ }
87
+ const firstRepeat = merged[0];
88
+ if (firstRepeat) {
89
+ summary.push(`the statement "${truncate(firstRepeat.statement, 80)}" runs ${firstRepeat.count} times (N+1 suspect)`);
90
+ }
91
+ const slowest = input.traces[0];
92
+ if (slowest) {
93
+ lines.push("", `Summary: ${summary.join("; ")}. Use get_trace ${clean(slowest.traceId, 64)} for the slowest trace in full.`);
94
+ }
95
+ return lines.join("\n");
96
+ }
97
+ function mergeRepeated(all) {
98
+ const merged = new Map();
99
+ for (const r of all) {
100
+ const m = merged.get(r.statement);
101
+ if (m) {
102
+ m.count += r.count;
103
+ m.totalMs += r.totalMs;
104
+ }
105
+ else {
106
+ merged.set(r.statement, { ...r });
107
+ }
108
+ }
109
+ return [...merged.values()].sort((a, b) => b.count - a.count ||
110
+ b.totalMs - a.totalMs ||
111
+ (a.statement < b.statement ? -1 : 1));
112
+ }
113
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/render/explain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** Small formatting helpers shared by the renderers. All output is deterministic: no locale, no time zone. */
2
+ /** Milliseconds as `0.42ms`, `12.3ms`, `182ms` or `1.25s`. */
3
+ export declare function fmtMs(ms: number): string;
4
+ /** `12.3%`; `0%` when the whole is 0. */
5
+ export declare function fmtPct(part: number, whole: number): string;
6
+ /** Unix ms as `2026-11-12T10:15:30Z`. */
7
+ export declare function fmtTime(unixMs: number): string;
8
+ /** Collapses whitespace runs (including newlines) to one space. */
9
+ export declare function oneLine(text: string): string;
10
+ /** At most `max` characters, ending in `…` when cut. */
11
+ export declare function truncate(text: string, max: number): string;
12
+ /** For any string that came from telemetry: one line, at most `max` characters. */
13
+ export declare function clean(text: string, max: number): string;
14
+ /** Pads every cell but the last of each row to its column's width. */
15
+ export declare function table(rows: string[][]): string[];
16
+ export declare function plural(n: number, one: string, many?: string): string;
@@ -0,0 +1,59 @@
1
+ /** Small formatting helpers shared by the renderers. All output is deterministic: no locale, no time zone. */
2
+ /** Milliseconds as `0.42ms`, `12.3ms`, `182ms` or `1.25s`. */
3
+ export function fmtMs(ms) {
4
+ if (!Number.isFinite(ms))
5
+ return "?";
6
+ const abs = Math.abs(ms);
7
+ if (abs >= 1000)
8
+ return `${trimZeros((ms / 1000).toFixed(2))}s`;
9
+ if (abs >= 100)
10
+ return `${Math.round(ms)}ms`;
11
+ if (abs >= 10)
12
+ return `${trimZeros(ms.toFixed(1))}ms`;
13
+ return `${trimZeros(ms.toFixed(2))}ms`;
14
+ }
15
+ function trimZeros(text) {
16
+ return text.includes(".") ? text.replace(/\.?0+$/, "") : text;
17
+ }
18
+ /** `12.3%`; `0%` when the whole is 0. */
19
+ export function fmtPct(part, whole) {
20
+ if (!(whole > 0))
21
+ return "0%";
22
+ return `${trimZeros(((part / whole) * 100).toFixed(1))}%`;
23
+ }
24
+ /** Unix ms as `2026-11-12T10:15:30Z`. */
25
+ export function fmtTime(unixMs) {
26
+ const date = new Date(unixMs);
27
+ if (Number.isNaN(date.getTime()))
28
+ return "?";
29
+ return `${date.toISOString().slice(0, 19)}Z`;
30
+ }
31
+ /** Collapses whitespace runs (including newlines) to one space. */
32
+ export function oneLine(text) {
33
+ return text.replace(/\s+/g, " ").trim();
34
+ }
35
+ /** At most `max` characters, ending in `…` when cut. */
36
+ export function truncate(text, max) {
37
+ return text.length <= max ? text : `${text.slice(0, Math.max(0, max - 1))}…`;
38
+ }
39
+ /** For any string that came from telemetry: one line, at most `max` characters. */
40
+ export function clean(text, max) {
41
+ return truncate(oneLine(text), max);
42
+ }
43
+ /** Pads every cell but the last of each row to its column's width. */
44
+ export function table(rows) {
45
+ const widths = [];
46
+ for (const row of rows) {
47
+ row.forEach((cell, i) => {
48
+ widths[i] = Math.max(widths[i] ?? 0, cell.length);
49
+ });
50
+ }
51
+ return rows.map((row) => row
52
+ .map((cell, i) => i === row.length - 1 ? cell : cell.padEnd(widths[i] ?? 0))
53
+ .join(" ")
54
+ .trimEnd());
55
+ }
56
+ export function plural(n, one, many = `${one}s`) {
57
+ return `${n} ${n === 1 ? one : many}`;
58
+ }
59
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/render/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { AppMapResponse, ClassStatsResponse, ErrorListResponse, MetaResponse, RouteStatsResponse, TraceListResponse } from "@nestrix-js/protocol";
2
+ /** Rows shown in a statistics table. */
3
+ export declare const MAX_ROWS = 25;
4
+ export declare function renderTraceList(list: TraceListResponse, filters: string): string;
5
+ export declare function renderErrors(list: ErrorListResponse, route?: string): string;
6
+ export declare function renderRoutes(stats: RouteStatsResponse): string;
7
+ export declare function renderClasses(stats: ClassStatsResponse): string;
8
+ export declare function renderMap(map: AppMapResponse): string;
9
+ export interface OverviewInput {
10
+ meta: MetaResponse;
11
+ routes: RouteStatsResponse | undefined;
12
+ errors: ErrorListResponse | undefined;
13
+ }
14
+ export declare function renderOverview(input: OverviewInput): string;
@@ -0,0 +1,243 @@
1
+ import { clean, fmtMs, fmtPct, fmtTime, plural, table } from "./format.js";
2
+ /** Rows shown in a statistics table. */
3
+ export const MAX_ROWS = 25;
4
+ export function renderTraceList(list, filters) {
5
+ if (list.items.length === 0) {
6
+ return `No stored traces match${filters ? ` (${filters})` : ""}. Traces are sampled and the store is in memory, so older or unsampled requests are not here; route_stats counts every request.`;
7
+ }
8
+ const rows = list.items.map((t) => {
9
+ const what = t.method && t.route ? `${t.method} ${t.route}` : t.name;
10
+ const tags = [
11
+ t.error ? "ERROR" : "",
12
+ t.hasJob ? "job" : "",
13
+ t.type !== "http" ? t.type : "",
14
+ ].filter(Boolean);
15
+ const extra = [
16
+ clean(tags.join(","), 60),
17
+ t.release ? `release ${clean(t.release, 60)}` : "",
18
+ t.user ? `user ${clean(t.user, 40)}` : "",
19
+ ].filter(Boolean);
20
+ return [
21
+ clean(t.traceId, 64),
22
+ fmtTime(t.startTimeUnixMs),
23
+ clean(what, 80),
24
+ t.statusCode === undefined ? "-" : String(t.statusCode),
25
+ fmtMs(t.durationMs),
26
+ `${t.spanCount} spans`,
27
+ extra.join(" "),
28
+ ];
29
+ });
30
+ const lines = [
31
+ `${plural(list.items.length, "trace")}${filters ? ` (${filters})` : ""}, newest first. Pass a trace id to get_trace.`,
32
+ ...table([
33
+ ["trace id", "start (UTC)", "request", "status", "duration", "size", ""],
34
+ ...rows,
35
+ ]),
36
+ ];
37
+ if (list.older !== null) {
38
+ lines.push("More matching traces exist; narrow the filters (route, minDurationMs, search) to find others.");
39
+ }
40
+ return lines.join("\n");
41
+ }
42
+ export function renderErrors(list, route) {
43
+ if (list.items.length === 0) {
44
+ return `No stored errors${route ? ` for ${route}` : ""}.`;
45
+ }
46
+ const groups = new Map();
47
+ for (const e of list.items) {
48
+ const key = `${clean(e.errorType ?? e.spanName, 100)}: ${clean(e.message ?? "", 160)}`;
49
+ const g = groups.get(key);
50
+ if (g) {
51
+ g.count++;
52
+ if (e.timeUnixMs > g.latest) {
53
+ g.latest = e.timeUnixMs;
54
+ g.traceId = clean(e.traceId, 64);
55
+ }
56
+ }
57
+ else {
58
+ groups.set(key, {
59
+ count: 1,
60
+ latest: e.timeUnixMs,
61
+ traceId: clean(e.traceId, 64),
62
+ });
63
+ }
64
+ }
65
+ const lines = [
66
+ `${plural(list.items.length, "error")}${route ? ` for ${route}` : ""}, newest first${list.older !== null ? " (more exist)" : ""}.`,
67
+ "",
68
+ "Grouped by type and message:",
69
+ ];
70
+ const ranked = [...groups.entries()].sort((a, b) => b[1].count - a[1].count || b[1].latest - a[1].latest);
71
+ for (const [key, g] of ranked.slice(0, 10)) {
72
+ lines.push(`- ${g.count}x ${key} (latest trace ${g.traceId})`);
73
+ }
74
+ lines.push("", "Each error:");
75
+ lines.push(...table(list.items.map((e) => [
76
+ fmtTime(e.timeUnixMs),
77
+ clean(e.method && e.route
78
+ ? `${e.method} ${e.route}`
79
+ : (e.route ?? e.spanName), 60),
80
+ e.statusCode === undefined ? "-" : String(e.statusCode),
81
+ clean(e.traceId, 64),
82
+ ])));
83
+ lines.push("Pass a trace id to get_trace for the stack frames.");
84
+ return lines.join("\n");
85
+ }
86
+ function routeLine(r) {
87
+ return [
88
+ clean(`${r.method} ${r.route}`, 120),
89
+ String(r.count),
90
+ String(r.errors),
91
+ fmtPct(r.errors, r.count),
92
+ fmtMs(r.p50Ms),
93
+ fmtMs(r.p95Ms),
94
+ fmtMs(r.p99Ms),
95
+ fmtMs(r.maxMs),
96
+ ];
97
+ }
98
+ export function renderRoutes(stats) {
99
+ if (stats.routes.length === 0) {
100
+ return `No requests counted in the last ${stats.windowMinutes} minutes.`;
101
+ }
102
+ const sorted = [...stats.routes].sort((a, b) => b.p95Ms - a.p95Ms ||
103
+ (`${a.method} ${a.route}` < `${b.method} ${b.route}` ? -1 : 1));
104
+ const shown = sorted.slice(0, MAX_ROWS);
105
+ const lines = [
106
+ `Routes over the last ${stats.windowMinutes} minutes, slowest p95 first. Every request is counted, sampled or not.`,
107
+ ...table([
108
+ ["route", "requests", "errors", "error rate", "p50", "p95", "p99", "max"],
109
+ ...shown.map(routeLine),
110
+ ]),
111
+ ];
112
+ if (sorted.length > shown.length) {
113
+ lines.push(`... ${sorted.length - shown.length} more routes not shown.`);
114
+ }
115
+ return lines.join("\n");
116
+ }
117
+ export function renderClasses(stats) {
118
+ if (stats.methodsState === "no-data-in-range") {
119
+ return `This service has sent method spans before, but none in the last ${stats.windowMinutes} minutes (it may be idle). Try a longer window.`;
120
+ }
121
+ if (!stats.methodsEnabled) {
122
+ return "Method spans are off in this app (no NestrixInstrument, or it runs under @nestjs/testing), so there are no per-class statistics.";
123
+ }
124
+ if (stats.classes.length === 0) {
125
+ return `No traced class calls in the last ${stats.windowMinutes} minutes.`;
126
+ }
127
+ const sorted = [...stats.classes].sort((a, b) => (b.ownMs ?? -1) - (a.ownMs ?? -1) ||
128
+ b.totalMs - a.totalMs ||
129
+ (a.className < b.className ? -1 : 1));
130
+ const shown = sorted.slice(0, MAX_ROWS);
131
+ const lines = [
132
+ `Classes over the last ${stats.windowMinutes} minutes, most own time first. Own time is estimated from the sampled traces in the store; calls and errors are counted before sampling.`,
133
+ ...table([
134
+ ["class", "kind", "calls", "errors", "avg", "own time"],
135
+ ...shown.map((c) => [
136
+ clean(c.className, 80),
137
+ clean(c.kind, 24),
138
+ String(c.calls),
139
+ String(c.errors),
140
+ fmtMs(c.avgMs),
141
+ c.ownMs === null ? "-" : fmtMs(c.ownMs),
142
+ ]),
143
+ ]),
144
+ ];
145
+ const top = shown.slice(0, 5);
146
+ lines.push("", "Slowest methods of the top classes:");
147
+ for (const c of top) {
148
+ const methods = [...c.methods]
149
+ .sort((a, b) => b.totalMs - a.totalMs || (a.method < b.method ? -1 : 1))
150
+ .slice(0, 3)
151
+ .map((m) => `${clean(m.method, 60)} ${m.calls} calls avg ${fmtMs(m.avgMs)} max ${fmtMs(m.maxMs)}${m.errors > 0 ? ` ${m.errors} errors` : ""}`);
152
+ lines.push(`- ${clean(c.className, 80)}: ${methods.join("; ")}`);
153
+ }
154
+ if (sorted.length > shown.length) {
155
+ lines.push(`... ${sorted.length - shown.length} more classes not shown.`);
156
+ }
157
+ return lines.join("\n");
158
+ }
159
+ export function renderMap(map) {
160
+ if (map.edges.length === 0) {
161
+ return `No calls between the app and other systems in the stored traces of the last ${map.windowMinutes} minutes.`;
162
+ }
163
+ const names = new Map(map.nodes.map((n) => [n.id, n]));
164
+ const label = (id) => {
165
+ const n = names.get(id);
166
+ return n ? `${clean(n.name, 80)} (${clean(n.kind, 24)})` : clean(id, 80);
167
+ };
168
+ const edges = [...map.edges].sort((a, b) => b.calls - a.calls || (a.to < b.to ? -1 : 1));
169
+ const lines = [
170
+ `App map from the sampled traces of the last ${map.windowMinutes} minutes (call counts reflect sampling):`,
171
+ ...edges
172
+ .slice(0, MAX_ROWS)
173
+ .map((e) => `- ${label(e.from)} -> ${label(e.to)}: ${plural(e.calls, "call")}, ${plural(e.errors, "error")}, p50 ${fmtMs(e.p50Ms)}, p95 ${fmtMs(e.p95Ms)}`),
174
+ ];
175
+ if (edges.length > MAX_ROWS) {
176
+ lines.push(`... ${edges.length - MAX_ROWS} more edges not shown.`);
177
+ }
178
+ return lines.join("\n");
179
+ }
180
+ export function renderOverview(input) {
181
+ const { meta, routes, errors } = input;
182
+ const lines = [];
183
+ const service = meta.service;
184
+ lines.push(`Nestrix ${meta.mode === "standalone" ? "server (standalone)" : "dashboard (embedded in one app)"}${service.name ? `: ${clean(service.name, 80)}` : ""}${service.version ? ` ${clean(service.version, 60)}` : ""}${service.environment ? ` (${clean(service.environment, 40)})` : ""}`);
185
+ if (meta.services && meta.services.length > 0) {
186
+ lines.push(`Services with data: ${meta.services
187
+ .slice(0, 50)
188
+ .map((x) => clean(x, 80))
189
+ .join(", ")} (filter other tools with service)`);
190
+ }
191
+ lines.push(`Sampling: ${meta.sampling.owner === "nestrix" ? `${trimRate(meta.sampling.rate)} of requests are stored as traces` : "owned by the host app (rate unknown)"}; route statistics count every request.`);
192
+ lines.push(`Store: ${meta.store.traces}/${meta.store.maxTraces} traces, ${meta.store.spans} spans, ${meta.store.evictedTraces} evicted, ${meta.store.droppedSpans} spans dropped.`);
193
+ lines.push(`CPU profiler: ${meta.profiler.available ? (meta.profiler.running ? "available, a capture is running" : "available (start_profile)") : "not available here (embedded dashboards only)"}.`);
194
+ for (const w of meta.warnings)
195
+ lines.push(`Warning: ${clean(w.message, 300)}`);
196
+ if (routes) {
197
+ const withTraffic = routes.routes.filter((r) => r.count > 0);
198
+ const total = withTraffic.reduce((n, r) => n + r.count, 0);
199
+ const failed = withTraffic.reduce((n, r) => n + r.errors, 0);
200
+ lines.push("", `Traffic in the last ${routes.windowMinutes} minutes: ${plural(total, "request")}, ${plural(failed, "error")} (${fmtPct(failed, total)}).`);
201
+ const slowest = [...withTraffic]
202
+ .sort((a, b) => b.p95Ms - a.p95Ms ||
203
+ (`${a.method} ${a.route}` < `${b.method} ${b.route}` ? -1 : 1))
204
+ .slice(0, 5);
205
+ if (slowest.length > 0) {
206
+ lines.push("Slowest routes (p95):");
207
+ for (const r of slowest) {
208
+ lines.push(`- ${clean(`${r.method} ${r.route}`, 120)}: p95 ${fmtMs(r.p95Ms)}, p50 ${fmtMs(r.p50Ms)}, ${plural(r.count, "request")}`);
209
+ }
210
+ }
211
+ const failing = withTraffic
212
+ .filter((r) => r.errors > 0)
213
+ .sort((a, b) => b.errors / b.count - a.errors / a.count ||
214
+ b.errors - a.errors ||
215
+ (`${a.method} ${a.route}` < `${b.method} ${b.route}` ? -1 : 1))
216
+ .slice(0, 5);
217
+ if (failing.length > 0) {
218
+ lines.push("Most failing routes:");
219
+ for (const r of failing) {
220
+ lines.push(`- ${clean(`${r.method} ${r.route}`, 120)}: ${r.errors}/${r.count} failed (${fmtPct(r.errors, r.count)})`);
221
+ }
222
+ }
223
+ else if (withTraffic.length > 0) {
224
+ lines.push("No failing routes in this window.");
225
+ }
226
+ }
227
+ else {
228
+ lines.push("", "Route statistics could not be read.");
229
+ }
230
+ if (errors) {
231
+ const n = errors.items.length;
232
+ lines.push(`Stored errors: ${n}${errors.older !== null ? "+" : ""}${n > 0 ? " (list_errors)" : ""}.`);
233
+ }
234
+ else {
235
+ lines.push("Stored errors could not be read.");
236
+ }
237
+ lines.push("", "Next: find_traces or explain_slowness for a slow route, list_errors then get_trace for a failure, class_stats and app_map for structure.");
238
+ return lines.join("\n");
239
+ }
240
+ function trimRate(rate) {
241
+ return `${Math.round(rate * 1000) / 10}%`;
242
+ }
243
+ //# sourceMappingURL=lists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lists.js","sourceRoot":"","sources":["../../src/render/lists.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ProfileDetail } from "@nestrix-js/protocol";
2
+ export declare const PROFILE_TOP = 15;
3
+ /** The hottest functions of a finished capture, by self time. */
4
+ export declare function renderProfile(detail: ProfileDetail): string;
@@ -0,0 +1,43 @@
1
+ import { clean, fmtMs, fmtPct } from "./format.js";
2
+ export const PROFILE_TOP = 15;
3
+ /** `file:///app/dist/x.js` as `/app/dist/x.js`, cut from the left to at most 90 characters. */
4
+ function place(url, line) {
5
+ if (url === "")
6
+ return "(runtime)";
7
+ let path = clean(url.startsWith("file://") ? decodeSafe(url.slice(7)) : url, 400);
8
+ const dependency = path.lastIndexOf("/node_modules/");
9
+ if (dependency >= 0)
10
+ path = path.slice(dependency + 1);
11
+ const shortened = path.length > 90 ? `…${path.slice(path.length - 89)}` : path;
12
+ return line > 0 ? `${shortened}:${line}` : shortened;
13
+ }
14
+ function decodeSafe(text) {
15
+ try {
16
+ return decodeURIComponent(text);
17
+ }
18
+ catch {
19
+ return text;
20
+ }
21
+ }
22
+ /** The hottest functions of a finished capture, by self time. */
23
+ export function renderProfile(detail) {
24
+ // The flame root's total excludes (idle): the share is of the time the process was working.
25
+ const busy = detail.flame.totalSamples;
26
+ const lines = [
27
+ `CPU profile ${clean(detail.id, 64)}: ${fmtMs(detail.actualDurationMs)} captured, ${detail.samples} samples (${busy} not idle), starting it paused the app for ${fmtMs(detail.startPauseMs)}.`,
28
+ ];
29
+ if (detail.topFunctions.length === 0 || busy === 0) {
30
+ lines.push("The process was idle for the whole capture: nothing ran. Send the traffic you want to profile while the capture runs.");
31
+ return lines.join("\n");
32
+ }
33
+ lines.push("Top functions by self time (share of non-idle samples):");
34
+ detail.topFunctions.slice(0, PROFILE_TOP).forEach((f, i) => {
35
+ lines.push(`${i + 1}. ${fmtPct(f.selfSamples, busy)} ${clean(f.functionName, 100)} ${place(f.url, f.line)} (self ${f.selfSamples} samples, with callees ${f.totalSamples})`);
36
+ });
37
+ if (detail.topFunctions.length > PROFILE_TOP) {
38
+ lines.push(`... ${detail.topFunctions.length - PROFILE_TOP} more functions not shown.`);
39
+ }
40
+ lines.push("(program) is native work outside JavaScript and (garbage collector) is GC. Line numbers are of the running JavaScript, without source maps.");
41
+ return lines.join("\n");
42
+ }
43
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/render/profile.ts"],"names":[],"mappings":"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"}