diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index a4448e016..bab17d588 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -17,6 +17,7 @@ import { markExecutionCancelled } from '@/lib/execution/cancellation' import { processInputFileFields } from '@/lib/execution/files' import { preprocessExecution } from '@/lib/execution/preprocessing' import { LoggingSession } from '@/lib/logs/execution/logging-session' +import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans' import { cleanupExecutionBase64Cache, hydrateUserFilesWithBase64, @@ -879,11 +880,14 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: logger.error(`[${requestId}] SSE execution failed: ${errorMessage}`, { isTimeout }) const executionResult = hasExecutionResult(error) ? error.executionResult : undefined + const { traceSpans, totalDuration } = executionResult + ? buildTraceSpans(executionResult) + : { traceSpans: [], totalDuration: 0 } await loggingSession.safeCompleteWithError({ - totalDurationMs: executionResult?.metadata?.duration, + totalDurationMs: totalDuration || executionResult?.metadata?.duration, error: { message: errorMessage }, - traceSpans: executionResult?.logs as any, + traceSpans, }) sendEvent({ diff --git a/apps/sim/executor/execution/engine.ts b/apps/sim/executor/execution/engine.ts index 9bff038ee..47afd8b03 100644 --- a/apps/sim/executor/execution/engine.ts +++ b/apps/sim/executor/execution/engine.ts @@ -162,6 +162,8 @@ export class ExecutionEngine { } } + this.finalizeIncompleteLogs() + const errorMessage = normalizeError(error) logger.error('Execution failed', { error: errorMessage }) diff --git a/apps/sim/executor/utils/subflow-utils.ts b/apps/sim/executor/utils/subflow-utils.ts index c4eb23f38..8c92f82a4 100644 --- a/apps/sim/executor/utils/subflow-utils.ts +++ b/apps/sim/executor/utils/subflow-utils.ts @@ -229,6 +229,10 @@ export function addSubflowErrorLog( } ctx.blockLogs.push(blockLog) + if (contextExtensions?.onBlockStart) { + contextExtensions.onBlockStart(blockId, blockName, blockType, execOrder) + } + if (contextExtensions?.onBlockComplete) { contextExtensions.onBlockComplete(blockId, blockName, blockType, { input: inputData, diff --git a/apps/sim/lib/logs/execution/logger.ts b/apps/sim/lib/logs/execution/logger.ts index 055b8fe26..0fc47fa73 100644 --- a/apps/sim/lib/logs/execution/logger.ts +++ b/apps/sim/lib/logs/execution/logger.ts @@ -261,10 +261,14 @@ export class ExecutionLogger implements IExecutionLoggerService { models: costSummary.models, } - const totalDuration = + const rawDurationMs = isResume && existingLog?.startedAt ? new Date(endedAt).getTime() - new Date(existingLog.startedAt).getTime() : totalDurationMs + const totalDuration = + typeof rawDurationMs === 'number' && Number.isFinite(rawDurationMs) + ? Math.max(0, Math.round(rawDurationMs)) + : 0 const [updatedLog] = await db .update(workflowExecutionLogs)