Skip to content

Commit d972bab

Browse files
fix(logs-sidebar): remove message and fix race condition for quickly switching b/w logs (#1001)
1 parent f254d70 commit d972bab

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/sidebar.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { useEffect, useMemo, useRef, useState } from 'react'
4-
import { ChevronDown, ChevronUp, Eye, X } from 'lucide-react'
4+
import { ChevronDown, ChevronUp, Eye, Loader2, X } from 'lucide-react'
55
import { Button } from '@/components/ui/button'
66
import { CopyButton } from '@/components/ui/copy-button'
77
import { ScrollArea } from '@/components/ui/scroll-area'
@@ -209,6 +209,15 @@ export function Sidebar({
209209
}
210210
}, [log?.id])
211211

212+
const isLoadingDetails = useMemo(() => {
213+
if (!log) return false
214+
// Only show while we expect details to arrive (has executionId)
215+
if (!log.executionId) return false
216+
const hasEnhanced = !!log.executionData?.enhanced
217+
const hasAnyDetails = hasEnhanced || !!log.cost || Array.isArray(log.executionData?.traceSpans)
218+
return !hasAnyDetails
219+
}, [log])
220+
212221
const formattedContent = useMemo(() => {
213222
if (!log) return null
214223

@@ -476,6 +485,14 @@ export function Sidebar({
476485
</div>
477486
)}
478487

488+
{/* Suspense while details load (positioned after summary fields) */}
489+
{isLoadingDetails && (
490+
<div className='flex w-full items-center justify-start gap-2 py-2 text-muted-foreground'>
491+
<Loader2 className='h-4 w-4 animate-spin' />
492+
<span className='text-sm'>Loading details…</span>
493+
</div>
494+
)}
495+
479496
{/* Files */}
480497
{log.files && log.files.length > 0 && (
481498
<div>
@@ -527,11 +544,7 @@ export function Sidebar({
527544
</div>
528545
)}
529546

530-
{/* Message Content */}
531-
<div className='w-full pb-2'>
532-
<h3 className='mb-1 font-medium text-muted-foreground text-xs'>Message</h3>
533-
<div className='w-full'>{formattedContent}</div>
534-
</div>
547+
{/* end suspense */}
535548

536549
{/* Trace Spans (if available and this is a workflow execution log) */}
537550
{isWorkflowExecutionLog && log.executionData?.traceSpans && (

apps/sim/app/workspace/[workspaceId]/logs/logs.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ export default function Logs() {
8585
const [selectedLog, setSelectedLog] = useState<WorkflowLog | null>(null)
8686
const [selectedLogIndex, setSelectedLogIndex] = useState<number>(-1)
8787
const [isSidebarOpen, setIsSidebarOpen] = useState(false)
88+
const [isDetailsLoading, setIsDetailsLoading] = useState(false)
8889
const detailsCacheRef = useRef<Map<string, any>>(new Map())
8990
const detailsAbortRef = useRef<AbortController | null>(null)
91+
const currentDetailsIdRef = useRef<string | null>(null)
9092
const selectedRowRef = useRef<HTMLTableRowElement | null>(null)
9193
const loaderRef = useRef<HTMLDivElement>(null)
9294
const scrollContainerRef = useRef<HTMLDivElement>(null)
@@ -118,6 +120,7 @@ export default function Logs() {
118120
const index = logs.findIndex((l) => l.id === log.id)
119121
setSelectedLogIndex(index)
120122
setIsSidebarOpen(true)
123+
setIsDetailsLoading(true)
121124

122125
// Fetch details for current, previous, and next concurrently with cache
123126
const currentId = log.id
@@ -134,24 +137,26 @@ export default function Logs() {
134137
}
135138
const controller = new AbortController()
136139
detailsAbortRef.current = controller
140+
currentDetailsIdRef.current = currentId
137141

138142
const idsToFetch: Array<{ id: string; merge: boolean }> = []
139-
if (currentId && !detailsCacheRef.current.has(currentId))
140-
idsToFetch.push({ id: currentId, merge: true })
143+
const cachedCurrent = currentId ? detailsCacheRef.current.get(currentId) : undefined
144+
if (currentId && !cachedCurrent) idsToFetch.push({ id: currentId, merge: true })
141145
if (prevId && !detailsCacheRef.current.has(prevId))
142146
idsToFetch.push({ id: prevId, merge: false })
143147
if (nextId && !detailsCacheRef.current.has(nextId))
144148
idsToFetch.push({ id: nextId, merge: false })
145149

146-
if (idsToFetch.length === 0) {
147-
const cached = detailsCacheRef.current.get(currentId)
148-
if (cached) {
149-
setSelectedLog((prev) =>
150-
prev && prev.id === currentId ? ({ ...(prev as any), ...(cached as any) } as any) : prev
151-
)
152-
}
153-
return
150+
// Merge cached current immediately
151+
if (cachedCurrent) {
152+
setSelectedLog((prev) =>
153+
prev && prev.id === currentId
154+
? ({ ...(prev as any), ...(cachedCurrent as any) } as any)
155+
: prev
156+
)
157+
setIsDetailsLoading(false)
154158
}
159+
if (idsToFetch.length === 0) return
155160

156161
Promise.all(
157162
idsToFetch.map(async ({ id, merge }) => {
@@ -166,6 +171,7 @@ export default function Logs() {
166171
setSelectedLog((prev) =>
167172
prev && prev.id === id ? ({ ...(prev as any), ...(detailed as any) } as any) : prev
168173
)
174+
if (currentDetailsIdRef.current === id) setIsDetailsLoading(false)
169175
}
170176
}
171177
} catch (e: any) {

0 commit comments

Comments
 (0)