fix(claude-hook): derive span durations from start timestamps

This commit is contained in:
William Valentin
2026-03-20 11:17:40 -07:00
parent d235e3c873
commit a87bbc6983
2 changed files with 52 additions and 6 deletions
+27 -3
View File
@@ -331,6 +331,8 @@ async function handleToolStart(input) {
if (spanKey) {
activeSpans.set(spanKey, spanId);
state.spans[spanKey] = spanId;
state.spanStartTimes = state.spanStartTimes || {};
state.spanStartTimes[spanId] = Date.now();
if (runId)
state.runId = runId;
if (sessionKey)
@@ -358,7 +360,13 @@ async function handleToolEnd(input) {
const spanId = spanKey ? activeSpans.get(spanKey) || state.spans[spanKey] : void 0;
const result = isRecord(input.result) ? input.result : isRecord(input.output) ? input.output : {};
const success = !result.error;
const duration = pickNumber(input.duration_ms, input.elapsed_ms);
const startTime = spanId ? state.spanStartTimes?.[spanId] : void 0;
const duration = pickNumber(input.duration_ms, input.elapsed_ms) ?? (startTime ? Date.now() - startTime : void 0);
if (spanId && state.spanStartTimes) {
delete state.spanStartTimes[spanId];
if (sessionKey)
saveState(sessionKey, state);
}
enqueue(buildEnvelope("span.end", sessionKey, {
runId,
spanId,
@@ -387,6 +395,8 @@ async function handleSubagentStart(input) {
if (sessionKey) {
activeSubagents.set(sessionKey, { name: agentName, spanId });
state.subagent = { name: agentName, spanId };
state.spanStartTimes = state.spanStartTimes || {};
state.spanStartTimes[spanId] = Date.now();
if (runId)
state.runId = runId;
saveState(sessionKey, state);
@@ -412,8 +422,14 @@ async function handleSubagentStop(input) {
const subagent = sessionKey ? activeSubagents.get(sessionKey) || state.subagent : void 0;
const spanId = subagent?.spanId;
const agentName = subagent?.name || pickString(input.agent, input.agent_name) || "unknown";
const duration = pickNumber(input.duration_ms, input.elapsed_ms);
const startTime = spanId ? state.spanStartTimes?.[spanId] : void 0;
const duration = pickNumber(input.duration_ms, input.elapsed_ms) ?? (startTime ? Date.now() - startTime : void 0);
const usage = getUsage(input);
if (spanId && state.spanStartTimes) {
delete state.spanStartTimes[spanId];
if (sessionKey)
saveState(sessionKey, state);
}
enqueue(buildEnvelope("span.end", sessionKey, {
runId,
spanId,
@@ -439,6 +455,8 @@ async function handleCompactStart(input) {
if (sessionKey) {
activeSpans.set(sessionKey + ":compact", spanId);
state.compactSpanId = spanId;
state.spanStartTimes = state.spanStartTimes || {};
state.spanStartTimes[spanId] = Date.now();
if (runId)
state.runId = runId;
saveState(sessionKey, state);
@@ -459,8 +477,14 @@ async function handleCompactEnd(input) {
const runId = sessionKey ? activeRuns.get(sessionKey) || state.runId : void 0;
const spanKey = sessionKey ? sessionKey + ":compact" : void 0;
const spanId = spanKey ? activeSpans.get(spanKey) || state.compactSpanId : void 0;
const duration = pickNumber(input.duration_ms, input.elapsed_ms);
const startTime = spanId ? state.spanStartTimes?.[spanId] : void 0;
const duration = pickNumber(input.duration_ms, input.elapsed_ms) ?? (startTime ? Date.now() - startTime : void 0);
const contextWindow = getContextWindow(input);
if (spanId && state.spanStartTimes) {
delete state.spanStartTimes[spanId];
if (sessionKey)
saveState(sessionKey, state);
}
enqueue(buildEnvelope("span.end", sessionKey, {
runId,
spanId,