fix: bound web-probe observe analyze output
This commit is contained in:
@@ -330,6 +330,146 @@ export function renderWebObserveAnalyzeTable(value: Record<string, unknown>): st
|
||||
webObserveText(item.overBudgetCount ?? item.overFiveSecondCount),
|
||||
webObserveShort(webObserveArray(item.slowSamples).map((sample) => webObserveText(record(sample)?.otelTraceId)).filter((text) => text !== "-").join(",") || "-", 36),
|
||||
]);
|
||||
const frontendPerformance = record(analysis?.frontendPerformance);
|
||||
const frontendPerformanceSummary = nonEmptyRecord(frontendPerformance?.summary) ?? frontendPerformance;
|
||||
const frontendPerformanceHotspots = record(analysis?.frontendPerformanceHotspots);
|
||||
const frontendProfileFunctions = webObserveArray(frontendPerformanceHotspots?.profileFunctions ?? frontendPerformance?.profileFunctions ?? frontendPerformance?.profileHotspots).map(record).filter((item): item is Record<string, unknown> => item !== null).slice(0, 4);
|
||||
const frontendProfileStacks = webObserveArray(frontendPerformanceHotspots?.profileStacks ?? frontendPerformance?.profileStacks).map(record).filter((item): item is Record<string, unknown> => item !== null).slice(0, 3);
|
||||
const frontendScriptHotspots = webObserveArray(frontendPerformanceHotspots?.scripts ?? frontendPerformance?.scripts ?? frontendPerformance?.scriptHotspots).map(record).filter((item): item is Record<string, unknown> => item !== null).slice(0, 4);
|
||||
const highSignalFindings = dedupeWebObserveRecords(
|
||||
[...toolFindings, ...findings, ...archiveRedFindings],
|
||||
(item) => String(item.kind ?? item.id ?? item.code ?? ""),
|
||||
).slice(0, 6);
|
||||
const id = webObserveText(value.id);
|
||||
const statusLine = value.ok === false
|
||||
? `blocked reason=${webObserveText(record(value.failure)?.reason)} exit=${webObserveText(result.exitCode)} timeout=${webObserveText(result.timedOut)} recovered=${webObserveText(record(value.failure)?.recoveredFromArtifacts)}`
|
||||
: `ok=${webObserveText(value.ok !== false)} exit=${webObserveText(result.exitCode)} timeout=${webObserveText(result.timedOut)}`;
|
||||
const compactLines = [
|
||||
`web-probe observe analyze (${webObserveText(value.status)})`,
|
||||
"",
|
||||
webObserveTable(["ID", "NODE", "LANE", "STATUS", "SCOPE", "STATE_DIR"], [[
|
||||
id,
|
||||
value.node,
|
||||
value.lane,
|
||||
statusLine,
|
||||
webObserveShort([webObserveText(jsonlScope?.mode ?? "current"), webObserveText(record(jsonlScope?.focus)?.mode), jsonlScope?.archivePrefix ? webObserveText(jsonlScope.archivePrefix) : ""].filter((part) => part && part !== "-").join(":"), 36),
|
||||
webObserveShort(webObserveText(analysis?.stateDir), 72),
|
||||
]]),
|
||||
"",
|
||||
"Artifacts:",
|
||||
webObserveTable(["KIND", "PATH", "SHA256"], [
|
||||
["report.json", webObserveShort(webObserveText(analysis?.reportJsonPath), 72), webObserveShort(webObserveText(analysis?.reportJsonSha256), 24)],
|
||||
["report.md", webObserveShort(webObserveText(analysis?.reportMdPath), 72), webObserveShort(webObserveText(analysis?.reportMdSha256), 24)],
|
||||
]),
|
||||
"",
|
||||
"Counts:",
|
||||
webObserveTable(["SAMPLES", "CONTROL", "NETWORK", "CONSOLE", "ARTIFACTS", "ARCHIVE_SAMPLES", "ARCHIVE_RED"], [[
|
||||
webObserveText(counts?.samples),
|
||||
webObserveText(counts?.control),
|
||||
webObserveText(counts?.network),
|
||||
webObserveText(counts?.console),
|
||||
webObserveText(counts?.artifacts),
|
||||
webObserveText(record(archiveSummary?.sampleMetrics)?.sampleCount),
|
||||
webObserveText(archiveSummary?.redFindingCount),
|
||||
]]),
|
||||
"",
|
||||
"Tool state:",
|
||||
webObserveTable(["PENDING", "PROCESSING", "ABANDONED", "FAILED", "RUNNER_ERRORS", "COMMAND_FAILURES"], [[
|
||||
webObserveText(commandState?.pendingCount),
|
||||
webObserveText(commandState?.processingCount),
|
||||
webObserveText(commandState?.abandonedCount),
|
||||
webObserveText(commandState?.failedCount),
|
||||
webObserveText(runnerErrors.length),
|
||||
webObserveText(commandFailures.length),
|
||||
]]),
|
||||
"",
|
||||
"Findings:",
|
||||
webObserveTable(["KIND", "SEVERITY", "COUNT", "ROOT_CAUSE", "SUMMARY"], highSignalFindings.length > 0 ? highSignalFindings.map((item) => [
|
||||
webObserveShort(webObserveText(item.kind ?? item.id ?? item.code), 38),
|
||||
webObserveText(item.severity ?? item.level),
|
||||
webObserveText(item.count ?? item.sampleCount),
|
||||
webObserveShort(webObserveText(item.rootCause ?? item.rootCauseStatus), 38),
|
||||
webObserveShort(webObserveText(item.summary ?? item.message), 104),
|
||||
]) : [["-", "-", "-", "-", "-"]]),
|
||||
"",
|
||||
"Turn/loading:",
|
||||
webObserveTable(["ROUNDS", "TURNS", "ROWS", "ELAPSED_JUMP", "RECENT_JUMP", "LOADING_SAMPLES", "MAX_LOADING", `OVER_${loadingBudgetLabel}`], [[
|
||||
webObserveText(roundCount),
|
||||
webObserveText(turnColumnCount),
|
||||
webObserveText(sampleMetrics?.turnTimingRows),
|
||||
webObserveText(sampleMetrics?.turnTimingTotalElapsedForwardJumpCount ?? elapsedForwardJumps.length),
|
||||
webObserveText(sampleMetrics?.turnTimingRecentUpdateJumpCount ?? sampleMetrics?.turnTimingRecentUpdateSawtoothJumpCount),
|
||||
webObserveText(loadingSummary?.loadingSampleCount ?? sampleMetrics?.loadingSampleCount),
|
||||
webObserveText(loadingSummary?.maxSimultaneousCount ?? sampleMetrics?.loadingMaxCount),
|
||||
webObserveText(loadingSummary?.overBudgetSegmentCount ?? loadingSummary?.overFiveSecondSegmentCount ?? sampleMetrics?.loadingOverFiveSecondSegmentCount),
|
||||
]]),
|
||||
"",
|
||||
"Request/performance:",
|
||||
webObserveTable(["REQUESTS", "TOTAL_PEAK", "PAGE_PEAK", "API_PEAK", "SLOW_API", "ARCHIVE_SLOW", "SSE_SLOW"], [[
|
||||
webObserveText(requestRateSummary?.requestCount),
|
||||
webObserveText(requestRateSummary?.totalPeakPerMinute),
|
||||
webObserveText(requestRateSummary?.pagePeakPerMinute),
|
||||
webObserveText(requestRateSummary?.apiPathPeakPerMinute),
|
||||
webObserveText(slowApis.length),
|
||||
webObserveText(archiveSlowApis.length),
|
||||
webObserveText(sseStreams.length),
|
||||
]]),
|
||||
webObserveTable(["PATH", "SAMPLES", "P95", "MAX", "OVER"], (slowApis.length > 0 ? slowApis : archiveSlowApis).slice(0, 4).map((item) => [
|
||||
webObserveShort(webObserveText(item.path ?? item.route), 56),
|
||||
webObserveText(item.sampleCount),
|
||||
webObserveText(item.p95Ms ?? item.p95),
|
||||
webObserveText(item.maxMs ?? item.max),
|
||||
webObserveText(item.overBudgetCount ?? item.overFiveSecondCount),
|
||||
]).concat((slowApis.length > 0 || archiveSlowApis.length > 0) ? [] : [["-", "-", "-", "-", "-"]])),
|
||||
"",
|
||||
"Frontend performance:",
|
||||
webObserveTable(["EVENTS", "LONGTASK", "LOAF", "GAP", "CAPTURES", "MAX_LONGTASK", "MAX_LOAF", "MAX_GAP"], [[
|
||||
webObserveText(frontendPerformanceSummary?.eventCount),
|
||||
webObserveText(frontendPerformanceSummary?.longTaskCount),
|
||||
webObserveText(frontendPerformanceSummary?.longAnimationFrameCount),
|
||||
webObserveText(frontendPerformanceSummary?.eventLoopGapCount),
|
||||
webObserveText(frontendPerformanceSummary?.captureCount),
|
||||
webObserveText(frontendPerformanceSummary?.maxLongTaskMs),
|
||||
webObserveText(frontendPerformanceSummary?.maxLongAnimationFrameMs),
|
||||
webObserveText(frontendPerformanceSummary?.maxEventLoopGapMs),
|
||||
]]),
|
||||
webObserveTable(["CPU_SELF_MS", "TOTAL_MS", "HITS", "FUNCTION", "URL"], frontendProfileFunctions.length > 0 ? frontendProfileFunctions.map((item) => [
|
||||
webObserveText(item.selfTimeMs),
|
||||
webObserveText(item.totalTimeMs),
|
||||
webObserveText(item.hitCount),
|
||||
webObserveShort(webObserveText(item.functionName ?? item.name), 42),
|
||||
webObserveShort(webObserveText(item.url ?? item.sourceURL ?? item.scriptUrl), 64),
|
||||
]) : [["-", "-", "-", "-", "-"]]),
|
||||
webObserveTable(["STACK_SELF_MS", "FRAMES", "FUNCTION", "TOP_FRAME"], frontendProfileStacks.length > 0 ? frontendProfileStacks.map((item) => {
|
||||
const frames = webObserveArray(item.frames).map(record).filter((frame): frame is Record<string, unknown> => frame !== null);
|
||||
const topFrame = frames[0] ?? {};
|
||||
return [
|
||||
webObserveText(item.selfTimeMs),
|
||||
webObserveText(item.frameCount ?? frames.length),
|
||||
webObserveShort(webObserveText(item.functionName ?? item.name), 38),
|
||||
webObserveShort(`${webObserveText(topFrame.functionName ?? "(anonymous)")}@${webObserveText(topFrame.url ?? topFrame.scriptId)}`, 68),
|
||||
];
|
||||
}) : [["-", "-", "-", "-"]]),
|
||||
webObserveTable(["LOAF_MS", "COUNT", "FUNCTION", "URL"], frontendScriptHotspots.length > 0 ? frontendScriptHotspots.map((item) => [
|
||||
webObserveText(item.totalDurationMs ?? item.durationMs),
|
||||
webObserveText(item.count ?? item.hitCount),
|
||||
webObserveShort(webObserveText(item.sourceFunctionName ?? item.functionName ?? item.invoker), 42),
|
||||
webObserveShort(webObserveText(item.sourceURL ?? item.url), 64),
|
||||
]) : [["-", "-", "-", "-"]]),
|
||||
"",
|
||||
"Next:",
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view turn-summary`,
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view timeline --command-id <commandId>`,
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view trace-frame --trace-id <traceId> --sample-seq <seq>`,
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view workbench-triad --trace-id <traceId>`,
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view performance-summary`,
|
||||
` bun scripts/cli.ts web-probe observe collect ${id} --view files --file analysis/report.json --finding <findingId>`,
|
||||
"",
|
||||
"Disclosure:",
|
||||
" default analyze output is a bounded index; full offline report stays in report.md/report.json artifacts.",
|
||||
];
|
||||
if (value.full !== true) return compactLines.join("\n");
|
||||
|
||||
const lines = [
|
||||
`web-probe observe analyze (${webObserveText(value.status)})`,
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user