Commit 029ac9f
fix(logs): split summary/detail contracts to make trace tab gate type-safe (#4431)
* fix(logs): split summary/detail contracts to make trace tab gate type-safe
The Trace tab was silently missing from the Log Details sidepanel because
list and detail rows shared one WorkflowLog type with executionData:
z.unknown(). The UI couldn't distinguish a summary row (no spans) from a
detail row (with spans), so the tab gate read undefined and hid itself.
Splits into WorkflowLogSummary (list) and WorkflowLogDetail (typed
executionData with optional traceSpans). Detail and by-execution routes
both write through to the same logKeys.detail(id) cache, eliminating the
two-key fragmentation that caused the merge memo workaround. List route
moves to cursor pagination on (sortValue, id) with proper NULLS LAST
handling and SQL-side sort across workflow + job execution tables.
Detail route now requires and asserts workspaceId. Deep-link path uses
useLogByExecutionId instead of auto-paginating the entire workspace.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(logs): audit follow-ups — render side-effect, stats invalidation, enhanced spread order
- Move onActiveTabChange call from render into useEffect to avoid
side-effects during render (StrictMode safety).
- Re-add logKeys.stats() invalidation to cancel/retry mutations so
the dashboard reflects status flips immediately.
- Reorder enhanced: true after ...execData spread in detail and
by-execution routes so the literal discriminator is never
overwritten by stale execData.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(logs): mirror SQL NULLS LAST in JS merge for cursor consistency
The in-memory merge of workflow + job pages negated the comparator
for DESC, which placed null sort values at the start. SQL orders
both ASC and DESC with NULLS LAST, so DESC pages emitted a cursor
{v: <last non-null>, id: ...} while null rows still satisfied the
cursor predicate (OR sort_expr IS NULL) on the next page —
producing duplicate null rows across pages on cost/duration sorts.
Handle nulls explicitly in the JS comparator so they always sort
last regardless of direction, matching the SQL ordering.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(logs): final-audit follow-ups — stable tab callback, byExecution invalidation, optimistic detail patch, trace loading state
- Wrap LogDetails -> LogDetailsContent onActiveTabChange in useCallback
so the child useEffect doesn't refire on every parent render.
- Add logKeys.byExecutionAll() to cancel + retry invalidation so the
table-embedded sidebar picks up status changes immediately.
- Optimistic write-through to logKeys.detail in useCancelExecution so
the open sidebar reflects 'cancelling' instantly; rolls back on error.
- Distinguish trace loading from trace-empty: when log.executionData is
not yet fetched, render "Loading trace…" instead of the empty state.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(logs): migrate stores/components to contract types
Replace the legacy `WorkflowLog` / `LogsResponse` / `WorkflowData` /
`CostMetadata` / `ToolCallMetadata` shapes in
`stores/logs/filters/types.ts` with direct use of the contract types
`WorkflowLogSummary`, `WorkflowLogDetail`, and a new `WorkflowLogRow`
alias for surfaces that render either form. Removes the
`summaryToWorkflowLog` / `detailToWorkflowLog` bridge in the React
Query layer along with their double-cast annotations.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(logs): address PR review feedback
- Whitelist sort columns against logSortBy enum to prevent client crash
when non-sortable headers (workflow, trigger) reach the contract parser.
- Extract fetchLogDetail helper shared by /api/logs/[id] and
/api/logs/by-execution/[executionId] — collapses ~360 duplicated lines
to a single source of truth keyed on lookup column.
* fix(logs): exclude job logs when level filter is workflow-only
When level=running or level=pending (workflow-only states involving
endedAt/pausedExecutions semantics), jobLevelConditions stayed empty
so no level constraint reached jobConditions — every job log in the
workspace leaked into the result. Skip the job side entirely when the
level filter has no job-applicable values (error/info).
* chore(logs): drop dead utils — mapToExecutionLog and friends
Remove ExecutionLog/RawLogResponse/ExecutionCost/LogWithExecutionData/
TraceSpan/BlockExecution interfaces and the mapToExecutionLog,
mapToExecutionLogAlt, extractOutput functions — all unreferenced after
the contract split. -212 lines.
* chore(logs): drop unused LOG_COLUMN_ORDER and LogColumnKey
* fix(logs): hydrate filters from URL synchronously on mount
The previous useEffect-based initializeFromURL caused useLogsList and
useDashboardStats to fire once with default store filters, then refetch
after the effect updated filters from the URL. Move the initial hydrate
into a useState lazy initializer so the first render already reads
URL-derived filters; the popstate handler keeps the existing effect for
back/forward navigation.
* chore(logs): trim verbose comments added during PR
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(logs): guard navigation arrows when selected log is off-page
Deep-linked logs resolved via useLogByExecutionId may not be in the
current page list, leaving selectedLogIndex at -1. The hasNext prop
was evaluating -1 < logs.length - 1 (true for any non-empty list),
which enabled the next arrow and jumped to the first item on click.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(logs): sync active-tab callback before paint to keep keyboard guards aligned
Run the resolvedTab → onActiveTabChange propagation in useLayoutEffect
so the parent's activeTabRef updates synchronously before the next
paint. This closes the brief window where window keydown handlers
in the logs page would still see activeTabRef.current === 'trace'
and short-circuit arrow-key navigation immediately after switching
to a log without a Trace tab.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent 6d044a9 commit 029ac9f
16 files changed
Lines changed: 1103 additions & 1343 deletions
File tree
- apps/sim
- app
- api/logs
- [id]
- by-execution/[executionId]
- workspace/[workspaceId]
- home/components/mothership-view/components
- add-resource-dropdown
- resource-content
- logs
- components
- log-details
- logs-list
- w/[workflowId]/components/panel/components/copilot/components/user-input/hooks
- hooks/queries
- lib
- api/contracts
- logs
- stores/logs/filters
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | 1 | | |
10 | | - | |
11 | 2 | | |
12 | | - | |
| 3 | + | |
| 4 | + | |
13 | 5 | | |
14 | | - | |
15 | 6 | | |
| 7 | + | |
16 | 8 | | |
17 | 9 | | |
18 | 10 | | |
19 | | - | |
20 | | - | |
21 | 11 | | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
114 | 17 | | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
| 18 | + | |
| 19 | + | |
137 | 20 | | |
138 | | - | |
139 | | - | |
| 21 | + | |
| 22 | + | |
140 | 23 | | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
154 | 30 | | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
| 31 | + | |
176 | 32 | | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
| 33 | + | |
| 34 | + | |
182 | 35 | | |
183 | 36 | | |
Lines changed: 36 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
0 commit comments