diff --git a/src/dashboard/ui.ts b/src/dashboard/ui.ts index dda3dc0..f96a024 100644 --- a/src/dashboard/ui.ts +++ b/src/dashboard/ui.ts @@ -1602,6 +1602,9 @@ export function getDashboardHTML(): string { // Fetch initial data async function fetchData() { + log.info('Fetching dashboard data...'); + const startTime = performance.now(); + // Use Promise.allSettled to handle partial failures gracefully const results = await Promise.allSettled([ fetch('/api/status'), @@ -1610,6 +1613,9 @@ export function getDashboardHTML(): string { fetch('/api/beads') ]); + const elapsed = Math.round(performance.now() - startTime); + log.info('API requests completed in ' + elapsed + 'ms'); + let currentStatus = null; let currentConfig = null; @@ -1617,20 +1623,26 @@ export function getDashboardHTML(): string { if (results[0].status === 'fulfilled' && results[0].value.ok) { try { currentStatus = await results[0].value.json(); + log.info('Status loaded', currentStatus); updateStatus(currentStatus); } catch (e) { - console.error('Failed to parse status:', e); + log.error('Failed to parse status', e); } + } else { + log.warn('Failed to fetch status', results[0]); } // Process config result if (results[1].status === 'fulfilled' && results[1].value.ok) { try { currentConfig = await results[1].value.json(); + log.info('Config loaded', currentConfig); updateConfig(currentConfig); } catch (e) { - console.error('Failed to parse config:', e); + log.error('Failed to parse config', e); } + } else { + log.warn('Failed to fetch config', results[1]); } // Check if configured backend differs from running backend @@ -1663,21 +1675,34 @@ export function getDashboardHTML(): string { } } + // Logging utility for browser console + const log = { + info: (msg, data) => console.log('%c[lance-context]%c ' + msg, 'color: #58a6ff; font-weight: bold', 'color: inherit', data || ''), + warn: (msg, data) => console.warn('%c[lance-context]%c ' + msg, 'color: #d29922; font-weight: bold', 'color: inherit', data || ''), + error: (msg, data) => console.error('%c[lance-context]%c ' + msg, 'color: #f85149; font-weight: bold', 'color: inherit', data || ''), + event: (name, data) => console.log('%c[lance-context]%c SSE: %c' + name, 'color: #58a6ff; font-weight: bold', 'color: inherit', 'color: #3fb950', data || ''), + }; + + log.info('Dashboard initialized'); + // Connect to SSE function connectSSE() { if (eventSource) { eventSource.close(); } + log.info('Connecting to SSE...'); eventSource = new EventSource('/api/events'); eventSource.addEventListener('connected', (e) => { + log.event('connected'); setConnected(true); fetchData(); }); eventSource.addEventListener('indexing:progress', (e) => { const progress = JSON.parse(e.data); + log.event('indexing:progress', progress); progressContainer.className = 'progress-container active'; indexBadge.textContent = 'Indexing...'; indexBadge.className = 'badge warning pulsing'; @@ -1685,6 +1710,7 @@ export function getDashboardHTML(): string { }); eventSource.addEventListener('indexing:start', () => { + log.event('indexing:start'); progressContainer.className = 'progress-container active'; indexBadge.textContent = 'Indexing...'; indexBadge.className = 'badge warning pulsing'; @@ -1693,27 +1719,31 @@ export function getDashboardHTML(): string { }); eventSource.addEventListener('indexing:complete', () => { + log.event('indexing:complete'); progressContainer.className = 'progress-container'; fetchData(); }); eventSource.addEventListener('status:change', (e) => { const status = JSON.parse(e.data); + log.event('status:change', status); updateStatus(status); }); eventSource.addEventListener('usage:update', (e) => { const usage = JSON.parse(e.data); + log.event('usage:update', { count: usage.length }); // The event data is the usage array, need to compute total const total = usage.reduce((sum, u) => sum + u.count, 0); updateUsage({ usage, total }); }); eventSource.addEventListener('heartbeat', () => { - // Just keep connection alive + // Just keep connection alive - don't log to reduce noise }); - eventSource.onerror = () => { + eventSource.onerror = (e) => { + log.warn('SSE connection error, will reconnect...', e); setConnected(false); // EventSource will automatically reconnect };