diff --git a/scripts/src/hwlab-node-web-observe-analyzer-request-runtime-source.ts b/scripts/src/hwlab-node-web-observe-analyzer-request-runtime-source.ts index d32b0fc8..6ec3e6de 100644 --- a/scripts/src/hwlab-node-web-observe-analyzer-request-runtime-source.ts +++ b/scripts/src/hwlab-node-web-observe-analyzer-request-runtime-source.ts @@ -718,6 +718,7 @@ function extractWebPerformanceRuntimeDiagnostics(network, promptTimes) { sessionIdHash: event.sessionIdHash ?? null, eventIdHash: event.eventIdHash ?? null, eventCount: numberOrNull(event.eventCount), + deliveredCount: numberOrNull(event.deliveredCount), chunkCount: numberOrNull(event.chunkCount), flushDurationMs: numberOrNull(event.flushDurationMs), droppedCount: numberOrNull(event.droppedCount), @@ -788,6 +789,7 @@ function groupWebPerformanceRuntimeDiagnostics(events) { promptIndexes: new Set(), traceIds: new Set(), eventCount: 0, + deliveredCount: 0, chunkCount: 0, droppedCount: 0, maxFlushDurationMs: null, @@ -802,16 +804,19 @@ function groupWebPerformanceRuntimeDiagnostics(events) { if (Number.isFinite(Number(item.promptIndex))) group.promptIndexes.add(Number(item.promptIndex)); if (item.traceId) group.traceIds.add(String(item.traceId)); group.eventCount += Number(item.eventCount || 0); + group.deliveredCount += Number(item.deliveredCount || 0); group.chunkCount += Number(item.chunkCount || 0); group.droppedCount += Number(item.droppedCount || 0); group.maxFlushDurationMs = maxNumber(group.maxFlushDurationMs, item.flushDurationMs); group.maxItemsPerChunk = maxNumber(group.maxItemsPerChunk, item.maxItemsPerChunk); group.maxChunkMs = maxNumber(group.maxChunkMs, item.maxChunkMs); - if (item.replacedByKey === true || item.replacedByKeyHash) group.replacedByKeyCount += 1; + if (Number.isFinite(Number(item.replacedByKey))) group.replacedByKeyCount += Number(item.replacedByKey); + else if (item.replacedByKey === true || item.replacedByKeyHash) group.replacedByKeyCount += 1; if (group.examples.length < 6) group.examples.push({ ts: item.ts || null, traceId: item.traceId || null, eventCount: item.eventCount ?? null, + deliveredCount: item.deliveredCount ?? null, chunkCount: item.chunkCount ?? null, flushDurationMs: item.flushDurationMs ?? null, droppedCount: item.droppedCount ?? null, @@ -834,6 +839,7 @@ function groupWebPerformanceRuntimeDiagnostics(events) { promptIndexes: Array.from(item.promptIndexes).sort((a, b) => a - b), traceIds: Array.from(item.traceIds).sort().slice(0, 12), eventCount: item.eventCount, + deliveredCount: item.deliveredCount, chunkCount: item.chunkCount, droppedCount: item.droppedCount, maxFlushDurationMs: item.maxFlushDurationMs, diff --git a/scripts/src/hwlab-node-web-observe-collect.ts b/scripts/src/hwlab-node-web-observe-collect.ts index 36598f1d..2aab0dd5 100644 --- a/scripts/src/hwlab-node-web-observe-collect.ts +++ b/scripts/src/hwlab-node-web-observe-collect.ts @@ -754,7 +754,7 @@ function compactPerfFinding(item){ return {severity:item?.severity??item?.level??null,id:short(item?.id||item?.kind||item?.code||'',56),count:item?.count??item?.sampleCount??null,rootCause:item?.rootCause??item?.rootCauseStatus??null,summary:short(item?.summary||item?.message||'',110),valuesRedacted:true}; } function compactWebPerformanceDiagnosticGroup(item){ - return {diagnosticCode:short(item?.diagnosticCode||'',64),reason:short(item?.reason||'',48),module:short(item?.module||'',48),eventType:short(item?.eventType||'',48),count:item?.count??null,eventCount:item?.eventCount??null,chunkCount:item?.chunkCount??null,droppedCount:item?.droppedCount??null,maxFlushDurationMs:item?.maxFlushDurationMs??null,maxItemsPerChunk:item?.maxItemsPerChunk??null,maxChunkMs:item?.maxChunkMs??null,replacedByKeyCount:item?.replacedByKeyCount??null,firstAt:item?.firstAt??null,lastAt:item?.lastAt??null,traceIds:Array.isArray(item?.traceIds)?item.traceIds.slice(0,2).map((id)=>short(id,32)):[],valuesRedacted:true}; + return {diagnosticCode:short(item?.diagnosticCode||'',64),reason:short(item?.reason||'',48),module:short(item?.module||'',48),eventType:short(item?.eventType||'',48),count:item?.count??null,eventCount:item?.eventCount??null,deliveredCount:item?.deliveredCount??null,chunkCount:item?.chunkCount??null,droppedCount:item?.droppedCount??null,maxFlushDurationMs:item?.maxFlushDurationMs??null,maxItemsPerChunk:item?.maxItemsPerChunk??null,maxChunkMs:item?.maxChunkMs??null,replacedByKeyCount:item?.replacedByKeyCount??null,firstAt:item?.firstAt??null,lastAt:item?.lastAt??null,traceIds:Array.isArray(item?.traceIds)?item.traceIds.slice(0,2).map((id)=>short(id,32)):[],valuesRedacted:true}; } function compactWebPerformancePayloadState(item){ return {state:short(item?.state||'',48),count:item?.count??null,valuesRedacted:true}; @@ -897,7 +897,7 @@ function renderPerformanceSummary(perf){ lines.push('payloads='+String(webPerfSummary.payloadRequestCount??0)+' parsed='+String(webPerfSummary.payloadParsedCount??0)+' parseIssues='+String(webPerfSummary.payloadParseIssueCount??0)+' events='+String(webPerfSummary.runtimeDiagnosticCount??0)+' groups='+String(webPerfSummary.runtimeDiagnosticGroupCount??0)); if(Array.isArray(webPerf.states)&&webPerf.states.length>0) lines.push(' payload states='+webPerf.states.map((item)=>String(item.state||'-')+':'+String(item.count??0)).join(', ')); if(!Array.isArray(webPerf.groups)||webPerf.groups.length===0) lines.push('-'); - for(const item of (webPerf.groups||[]).slice(0,6)) lines.push(String(item.diagnosticCode||item.eventType||'-')+' reason='+String(item.reason||'-')+' module='+String(item.module||'-')+' count='+String(item.count??0)+' eventCount='+String(item.eventCount??'-')+' chunks='+String(item.chunkCount??'-')+' flushMax='+String(item.maxFlushDurationMs??'-')+'ms dropped='+String(item.droppedCount??'-')+' maxItemsPerChunk='+String(item.maxItemsPerChunk??'-')+' maxChunkMs='+String(item.maxChunkMs??'-')+' replacedByKey='+String(item.replacedByKeyCount??'-')); + for(const item of (webPerf.groups||[]).slice(0,6)) lines.push(String(item.diagnosticCode||item.eventType||'-')+' reason='+String(item.reason||'-')+' module='+String(item.module||'-')+' count='+String(item.count??0)+' eventCount='+String(item.eventCount??'-')+' delivered='+String(item.deliveredCount??'-')+' chunks='+String(item.chunkCount??'-')+' flushMax='+String(item.maxFlushDurationMs??'-')+'ms dropped='+String(item.droppedCount??'-')+' maxItemsPerChunk='+String(item.maxItemsPerChunk??'-')+' maxChunkMs='+String(item.maxChunkMs??'-')+' replacedByKey='+String(item.replacedByKeyCount??'-')); lines.push('','Time-window correlation'); if(!Array.isArray(perf.performanceWindows)||perf.performanceWindows.length===0) lines.push('-'); for(const item of (perf.performanceWindows||[]).slice(0,3)){ diff --git a/scripts/src/hwlab-node-web-observe-runner-runtime-source.ts b/scripts/src/hwlab-node-web-observe-runner-runtime-source.ts index fd93b9ff..f9eb716d 100644 --- a/scripts/src/hwlab-node-web-observe-runner-runtime-source.ts +++ b/scripts/src/hwlab-node-web-observe-runner-runtime-source.ts @@ -973,6 +973,7 @@ function compactWebPerformancePayloadEvent(event) { sessionIdHash: sessionId ? sha256Text(sessionId) : null, eventIdHash: eventId ? sha256Text(eventId) : null, eventCount: numberOrNull(read("eventCount")), + deliveredCount: numberOrNull(read("deliveredCount")), chunkCount: numberOrNull(read("chunkCount")), flushDurationMs: numberOrNull(read("flushDurationMs")), droppedCount: numberOrNull(read("droppedCount")), diff --git a/scripts/src/hwlab-node/web-observe-web-performance-payload.test.ts b/scripts/src/hwlab-node/web-observe-web-performance-payload.test.ts index a488ed79..acee5a16 100644 --- a/scripts/src/hwlab-node/web-observe-web-performance-payload.test.ts +++ b/scripts/src/hwlab-node/web-observe-web-performance-payload.test.ts @@ -119,12 +119,13 @@ async function writeState(): Promise { traceId: "trc_webperf_fixture", sessionIdHash: "sha256:session", eventCount: 12, + deliveredCount: 10, chunkCount: 3, flushDurationMs: 18.75, droppedCount: 2, maxItemsPerChunk: 5, maxChunkMs: 7.5, - replacedByKey: true, + replacedByKey: 3, valuesRedacted: true, }], valuesRedacted: true, @@ -181,9 +182,10 @@ test("analyzer and performance-summary include bounded web-performance runtime d assert.equal(groups[0].reason, "sse_flush"); assert.equal(groups[0].module, "workbench-runtime"); assert.equal(groups[0].eventCount, 12); + assert.equal(groups[0].deliveredCount, 10); assert.equal(groups[0].chunkCount, 3); assert.equal(groups[0].maxFlushDurationMs, 18.75); - assert.equal(groups[0].replacedByKeyCount, 1); + assert.equal(groups[0].replacedByKeyCount, 3); const reportText = JSON.stringify(report); assert.match(reportText, /workbench_sse_flush/u); @@ -209,6 +211,6 @@ test("analyzer and performance-summary include bounded web-performance runtime d assert.match(renderedText, /Web performance runtime diagnostics/u); assert.match(renderedText, /payloads=3 parsed=1 parseIssues=2 events=1 groups=1/u); assert.match(renderedText, /workbench_sse_flush reason=sse_flush module=workbench-runtime/u); - assert.match(renderedText, /eventCount=12 chunks=3 flushMax=18.75ms dropped=2/u); + assert.match(renderedText, /eventCount=12 delivered=10 chunks=3 flushMax=18.75ms dropped=2/u); assert.match(renderedText, /payload states=invalid-json:1, not-parsed-over-limit:1, parsed:1/u); }, 20_000);