Skip to content

Commit 0f2a125

Browse files
improvement(block-error-logs): workflow in workflow (#1084)
* improvement(add-block-logs): workflow in workflow * fix lint
1 parent 7e364a7 commit 0f2a125

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

apps/sim/executor/handlers/workflow/workflow-handler.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,13 @@ export class WorkflowBlockHandler implements BlockHandler {
118118

119119
if ((mappedResult as any).success === false) {
120120
const childError = (mappedResult as any).error || 'Unknown error'
121-
throw new Error(`Error in child workflow "${childWorkflowName}": ${childError}`)
121+
const errorWithSpans = new Error(
122+
`Error in child workflow "${childWorkflowName}": ${childError}`
123+
) as any
124+
// Attach trace spans and name for higher-level logging to consume
125+
errorWithSpans.childTraceSpans = childTraceSpans
126+
errorWithSpans.childWorkflowName = childWorkflowName
127+
throw errorWithSpans
122128
}
123129

124130
return mappedResult
@@ -306,11 +312,16 @@ export class WorkflowBlockHandler implements BlockHandler {
306312
const success = childResult.success !== false
307313
if (!success) {
308314
logger.warn(`Child workflow ${childWorkflowName} failed`)
309-
return {
315+
const failure: Record<string, any> = {
310316
success: false,
311317
childWorkflowName,
312318
error: childResult.error || 'Child workflow execution failed',
313-
} as Record<string, any>
319+
}
320+
// Only include spans when present to keep output stable for callers/tests
321+
if (Array.isArray(childTraceSpans) && childTraceSpans.length > 0) {
322+
failure.childTraceSpans = childTraceSpans
323+
}
324+
return failure as Record<string, any>
314325
}
315326
let result = childResult
316327
if (childResult?.output) {

apps/sim/executor/index.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,11 @@ export class Executor {
17421742
blockLog.durationMs =
17431743
new Date(blockLog.endedAt).getTime() - new Date(blockLog.startedAt).getTime()
17441744

1745+
// If this error came from a child workflow execution, persist its trace spans on the log
1746+
if (block.metadata?.id === BlockType.WORKFLOW) {
1747+
this.attachChildWorkflowSpansToLog(blockLog, error)
1748+
}
1749+
17451750
// Log the error even if we'll continue execution through error path
17461751
context.blockLogs.push(blockLog)
17471752

@@ -1820,6 +1825,11 @@ export class Executor {
18201825
status: error.status || 500,
18211826
}
18221827

1828+
// Preserve child workflow spans on the block state so downstream logging can render them
1829+
if (block.metadata?.id === BlockType.WORKFLOW) {
1830+
this.attachChildWorkflowSpansToOutput(errorOutput, error)
1831+
}
1832+
18231833
// Set block state with error output
18241834
context.blockStates.set(blockId, {
18251835
output: errorOutput,
@@ -1864,6 +1874,39 @@ export class Executor {
18641874
}
18651875
}
18661876

1877+
/**
1878+
* Copies child workflow trace spans from an error object into a block log.
1879+
* Ensures consistent structure and avoids duplication of inline guards.
1880+
*/
1881+
private attachChildWorkflowSpansToLog(blockLog: BlockLog, error: unknown): void {
1882+
const spans = (
1883+
error as { childTraceSpans?: TraceSpan[]; childWorkflowName?: string } | null | undefined
1884+
)?.childTraceSpans
1885+
if (Array.isArray(spans) && spans.length > 0) {
1886+
blockLog.output = {
1887+
...(blockLog.output || {}),
1888+
childTraceSpans: spans,
1889+
childWorkflowName: (error as { childWorkflowName?: string } | null | undefined)
1890+
?.childWorkflowName,
1891+
}
1892+
}
1893+
}
1894+
1895+
/**
1896+
* Copies child workflow trace spans from an error object into a normalized output.
1897+
*/
1898+
private attachChildWorkflowSpansToOutput(output: NormalizedBlockOutput, error: unknown): void {
1899+
const spans = (
1900+
error as { childTraceSpans?: TraceSpan[]; childWorkflowName?: string } | null | undefined
1901+
)?.childTraceSpans
1902+
if (Array.isArray(spans) && spans.length > 0) {
1903+
output.childTraceSpans = spans
1904+
output.childWorkflowName = (
1905+
error as { childWorkflowName?: string } | null | undefined
1906+
)?.childWorkflowName
1907+
}
1908+
}
1909+
18671910
/**
18681911
* Activates error paths from a block that had an error.
18691912
* Checks for connections from the block's "error" handle and adds them to the active execution path.

apps/sim/executor/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { TraceSpan } from '@/lib/logs/types'
12
import type { BlockOutput } from '@/blocks/types'
23
import type { SerializedBlock, SerializedWorkflow } from '@/serializer/types'
34

@@ -52,6 +53,9 @@ export interface NormalizedBlockOutput {
5253
headers?: Record<string, string> // HTTP headers
5354
// Error handling
5455
error?: string // Error message if block execution failed
56+
// Child workflow introspection (for workflow blocks)
57+
childTraceSpans?: TraceSpan[]
58+
childWorkflowName?: string
5559
}
5660

5761
/**

apps/sim/lib/logs/execution/trace-spans/trace-spans.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ export function buildTraceSpans(result: ExecutionResult): {
5656
}
5757
}
5858

59+
// Prefer human-friendly workflow block naming if provided by child execution mapping
60+
const displayName =
61+
log.blockType === 'workflow' && log.output?.childWorkflowName
62+
? `${log.output.childWorkflowName} workflow`
63+
: log.blockName || log.blockId
64+
5965
const span: TraceSpan = {
6066
id: spanId,
61-
name: log.blockName || log.blockId,
67+
name: displayName,
6268
type: log.blockType,
6369
duration: duration,
6470
startTime: log.startedAt,

0 commit comments

Comments
 (0)