From 7d7fd82df110ffe1bf87d980422568f354511022 Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:28:49 +0800 Subject: [PATCH] fix(workbench): derive running timing from trace events (#1981) Co-authored-by: root --- internal/cloud/server-workbench-http.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/internal/cloud/server-workbench-http.ts b/internal/cloud/server-workbench-http.ts index 961f48ce..33962611 100644 --- a/internal/cloud/server-workbench-http.ts +++ b/internal/cloud/server-workbench-http.ts @@ -884,7 +884,7 @@ function factTraceSnapshot(facts = {}, traceId) { const status = durableTraceStatus(events); const lastEvent = events.at(-1) ?? null; const checkpoint = factCheckpointForTrace(facts, safeTrace); - const timing = factTimingProjection(checkpoint, status); + const timing = factTraceTimingProjection(events, checkpoint, status); return { traceId: safeTrace, status, @@ -902,6 +902,29 @@ function factTraceSnapshot(facts = {}, traceId) { }; } +function factTraceTimingProjection(events = [], checkpoint = null, status = null) { + const checkpointTiming = factTimingProjection(checkpoint, status); + const normalizedStatus = normalizeStatus(status ?? checkpoint?.status); + const terminal = TERMINAL_STATUSES.has(normalizedStatus) && !RUNNING_STATUSES.has(normalizedStatus); + const observedAt = new Date().toISOString(); + const eventTimes = factArray(events).flatMap((event) => [event?.createdAt, event?.updatedAt, event?.occurredAt]); + const startedAt = firstTimestampIso(checkpointTiming.startedAt, ...eventTimes); + const lastEventAt = latestTimestampIso(checkpointTiming.lastEventAt, ...eventTimes); + const finishedAt = terminal ? latestTimestampIso(checkpointTiming.finishedAt, lastEventAt) : null; + const durationMs = elapsedFactMs(startedAt, terminal ? finishedAt : observedAt); + const lastEventAgeMs = terminal ? null : elapsedFactMs(lastEventAt, observedAt); + return { + ...checkpointTiming, + startedAt, + lastEventAt, + finishedAt, + durationMs, + observedAt: terminal ? null : observedAt, + lastEventAgeMs, + valuesRedacted: true + }; +} + function factTraceEventDto(event, index) { const seq = factProjectedSeq(event); if (!seq) return null;