Skip to content

Commit b27e4c2

Browse files
committed
fix(vfs): add error on vfs materialize fail
1 parent 6f2c355 commit b27e4c2

2 files changed

Lines changed: 35 additions & 19 deletions

File tree

apps/sim/lib/copilot/request/tools/executor.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -399,20 +399,31 @@ export async function executeToolAndReport(
399399
},
400400
async (otelSpan) => {
401401
const startedAt = Date.now()
402-
const completion = await executeToolAndReportInner(toolCall, context, execContext, options)
403-
const durationMs = Date.now() - startedAt
404-
otelSpan.setAttribute(TraceAttr.ToolOutcome, completion.status)
405-
otelSpan.setAttribute(TraceAttr.ToolDurationMs, durationMs)
406-
if (completion.message) {
407-
otelSpan.setAttribute(
408-
TraceAttr.ToolOutcomeMessage,
409-
String(completion.message).slice(0, 500)
410-
)
402+
try {
403+
const completion = await executeToolAndReportInner(toolCall, context, execContext, options)
404+
const durationMs = Date.now() - startedAt
405+
otelSpan.setAttribute(TraceAttr.ToolOutcome, completion.status)
406+
otelSpan.setAttribute(TraceAttr.ToolDurationMs, durationMs)
407+
if (completion.message) {
408+
otelSpan.setAttribute(
409+
TraceAttr.ToolOutcomeMessage,
410+
String(completion.message).slice(0, 500)
411+
)
412+
}
413+
// Durable Grafana signal for "which Sim tool is slowest" (executor=sim);
414+
// pairs with the Go executor-boundary metric (U15) as one series set.
415+
recordSimToolMetric(toolCall.name, completion.status, durationMs)
416+
return completion
417+
} catch (err) {
418+
// executeToolAndReportInner threw (infra/unexpected error, not a normal
419+
// 'error' completion). Still stamp the span + record the dispatch so
420+
// copilot.tool.* isn't silently biased toward successful calls.
421+
const durationMs = Date.now() - startedAt
422+
otelSpan.setAttribute(TraceAttr.ToolOutcome, 'error')
423+
otelSpan.setAttribute(TraceAttr.ToolDurationMs, durationMs)
424+
recordSimToolMetric(toolCall.name, 'error', durationMs)
425+
throw err
411426
}
412-
// Durable Grafana signal for "which Sim tool is slowest" (executor=sim);
413-
// pairs with the Go executor-boundary metric (U15) as one series set.
414-
recordSimToolMetric(toolCall.name, completion.status, durationMs)
415-
return completion
416427
}
417428
)
418429
}

apps/sim/lib/copilot/vfs/workspace-vfs.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -473,20 +473,25 @@ export class WorkspaceVFS {
473473
markSpanForError(span, err)
474474
throw err
475475
} finally {
476+
// Record on success AND failure: a mid-phase failure (e.g. a DB
477+
// timeout) still belongs in copilot.vfs.materialize.duration, else
478+
// p50/p99 skew toward successes only. phaseMs holds whatever phases
479+
// completed before the failure.
480+
for (const [phase, ms] of Object.entries(phaseMs)) {
481+
recordVfsMaterialize(phase, ms)
482+
}
483+
recordVfsMaterialize('total', Date.now() - start)
476484
span.end()
477485
}
478486
}
479487
)
480488

481-
const totalMs = Date.now() - start
482489
// Durable Grafana signal for "how long does VFS materialize" — total plus
483490
// per-phase (bounded phase set). getOrMaterializeVFS runs per VFS tool call
484491
// with no cross-request cache, so this reveals whether materialize is the
485-
// bottleneck (observability only; not a fix).
486-
for (const [phase, ms] of Object.entries(phaseMs)) {
487-
recordVfsMaterialize(phase, ms)
488-
}
489-
recordVfsMaterialize('total', totalMs)
492+
// bottleneck (observability only; not a fix). Recorded inside the span's
493+
// finally above so a failed materialize is captured too, not just successes.
494+
const totalMs = Date.now() - start
490495

491496
logger.info('VFS materialized', {
492497
workspaceId,

0 commit comments

Comments
 (0)