From 8171a61af1e4006c0aea82f98a14dffe59d19508 Mon Sep 17 00:00:00 2001 From: Din Date: Tue, 25 Feb 2025 16:22:13 +0500 Subject: [PATCH] show browser session by default in rt, disable filters in spans, fix ids path --- app-server/src/traces/spans.rs | 8 +- frontend/components/traces/spans-table.tsx | 57 +++++---- frontend/components/traces/trace-view.tsx | 122 +++++++++++--------- frontend/components/traces/traces-table.tsx | 15 ++- 4 files changed, 117 insertions(+), 85 deletions(-) diff --git a/app-server/src/traces/spans.rs b/app-server/src/traces/spans.rs index d1fbd7d5..49410299 100644 --- a/app-server/src/traces/spans.rs +++ b/app-server/src/traces/spans.rs @@ -277,9 +277,9 @@ impl SpanAttributes { pub fn update_path(&mut self) { self.attributes.insert( - SPAN_PATH.to_string(), + SPAN_IDS_PATH.to_string(), Value::Array( - self.path() + self.ids_path() .unwrap_or_default() .into_iter() .map(serde_json::Value::String) @@ -287,9 +287,9 @@ impl SpanAttributes { ), ); self.attributes.insert( - SPAN_IDS_PATH.to_string(), + SPAN_PATH.to_string(), Value::Array( - self.ids_path() + self.path() .unwrap_or_default() .into_iter() .map(serde_json::Value::String) diff --git a/frontend/components/traces/spans-table.tsx b/frontend/components/traces/spans-table.tsx index fa7247f8..7eed9f43 100644 --- a/frontend/components/traces/spans-table.tsx +++ b/frontend/components/traces/spans-table.tsx @@ -67,10 +67,12 @@ export default function SpansTable({ onRowClick }: SpansTableProps) { const [spanId, setSpanId] = useState( searchParams.get('spanId') ?? null ); - const [enableLiveUpdates, setEnableLiveUpdates] = useState(() => { + const [enableLiveUpdates, setEnableLiveUpdates] = useState(true); + + useEffect(() => { const stored = globalThis?.localStorage?.getItem(LIVE_UPDATES_STORAGE_KEY); - return stored == null ? true : stored === 'true'; - }); + setEnableLiveUpdates(stored == null ? true : stored === 'true'); + }, []); const spansRef = useRef(spans); @@ -171,6 +173,11 @@ export default function SpansTable({ onRowClick }: SpansTableProps) { return; } + if (!enableLiveUpdates) { + supabase.removeAllChannels(); + return; + } + supabase.channel('table-db-changes').unsubscribe(); supabase @@ -230,24 +237,24 @@ export default function SpansTable({ onRowClick }: SpansTableProps) { } }; - const handleAddFilter = (column: string, value: string) => { - const newFilter = { column, operator: 'eq', value }; - const existingFilterIndex = activeFilters.findIndex( - (filter) => filter.column === column && filter.value === value - ); + // const handleAddFilter = (column: string, value: string) => { + // const newFilter = { column, operator: 'eq', value }; + // const existingFilterIndex = activeFilters.findIndex( + // (filter) => filter.column === column && filter.value === value + // ); - let updatedFilters; - if (existingFilterIndex === -1) { + // let updatedFilters; + // if (existingFilterIndex === -1) { - updatedFilters = [...activeFilters, newFilter]; - } else { + // updatedFilters = [...activeFilters, newFilter]; + // } else { - updatedFilters = [...activeFilters]; - } + // updatedFilters = [...activeFilters]; + // } - setActiveFilters(updatedFilters); - updateUrlWithFilters(updatedFilters); - }; + // setActiveFilters(updatedFilters); + // updateUrlWithFilters(updatedFilters); + // }; const updateUrlWithFilters = (filters: DatatableFilter[]) => { searchParams.delete('filter'); @@ -293,10 +300,10 @@ export default function SpansTable({ onRowClick }: SpansTableProps) { id: 'span_type', cell: (row) => (
{ - event.stopPropagation(); - handleAddFilter('span_type', row.getValue()); - }} + // onClick={(event) => { + // event.stopPropagation(); + // handleAddFilter('span_type', row.getValue()); + // }} className="cursor-pointer flex space-x-2 items-center hover:underline" > @@ -307,10 +314,10 @@ export default function SpansTable({ onRowClick }: SpansTableProps) { { cell: (row) => (
{ - event.stopPropagation(); - handleAddFilter('name', row.getValue()); - }} + // onClick={(event) => { + // event.stopPropagation(); + // handleAddFilter('name', row.getValue()); + // }} className="cursor-pointer hover:underline" > {row.getValue()} diff --git a/frontend/components/traces/trace-view.tsx b/frontend/components/traces/trace-view.tsx index e25893ae..419f3d69 100644 --- a/frontend/components/traces/trace-view.tsx +++ b/frontend/components/traces/trace-view.tsx @@ -38,6 +38,7 @@ export default function TraceView({ traceId, onClose }: TraceViewProps) { const [timelineWidth, setTimelineWidth] = useState(0); const [traceTreePanelWidth, setTraceTreePanelWidth] = useState(0); const { projectId } = useProjectContext(); + const [hasBrowserSession, setHasBrowserSession] = useState(false); const [showBrowserSession, setShowBrowserSession] = useState(false); const browserSessionRef = useRef(null); const { data: trace, isLoading, mutate } = useSWR( @@ -102,10 +103,18 @@ export default function TraceView({ traceId, onClose }: TraceViewProps) { : null ); } + if (trace?.hasBrowserSession) { + if (!hasBrowserSession) { + // if we previously didn't have a browser session, show it + setShowBrowserSession(true); + } + setHasBrowserSession(true); + } }, [trace]); useEffect(() => { if (trace?.hasBrowserSession) { + setHasBrowserSession(true); setShowBrowserSession(true); } }, []); @@ -415,60 +424,69 @@ const enrichSpansWithPending = (existingSpans: Span[]): Span[] => { const parentSpanIds = span.attributes['lmnr.span.ids_path'] as string[] | undefined; const parentSpanNames = span.attributes['lmnr.span.path'] as string[] | undefined; - if (parentSpanIds !== undefined && parentSpanNames !== undefined - && parentSpanIds.length === parentSpanNames.length && parentSpanIds.length > 0 - ) { - const startTime = new Date(span.startTime); - const endTime = new Date(span.endTime); - for (let i = 0; i < parentSpanIds.length; i++) { - const spanId = parentSpanIds[i]; - const spanName = parentSpanNames[i]; - - if (!existingSpanIds.has(spanId)) { - if (pendingSpans.has(spanId)) { - // if the pending span is already present, just update the start and end time - // to span over all its children - const existingStartTime = new Date(pendingSpans.get(spanId)!.startTime); - const existingEndTime = new Date(pendingSpans.get(spanId)!.endTime); - pendingSpans.set( - spanId, - { - ...pendingSpans.get(spanId)!, - startTime: (startTime < existingStartTime ? startTime : existingStartTime).toISOString(), - endTime: (endTime > existingEndTime ? endTime : existingEndTime).toISOString(), - } - ); - continue; - } + if (parentSpanIds === undefined || parentSpanNames === undefined) { + continue; + } - const parentSpanId = i > 0 ? parentSpanIds[i - 1] : null; - const parentSpanName = i > 0 ? parentSpanNames[i - 1] : null; - const pendingSpan = { - spanId, - name: spanName, - parentSpanId, - parentSpanName, - startTime: new Date(span.startTime).toISOString(), - endTime: new Date(span.endTime).toISOString(), - attributes: {}, - events: [], - logs: [], - spans: [], - traceId: span.traceId, - traceName: span.name, - input: null, - output: null, - inputPreview: null, - outputPreview: null, - spanType: SpanType.DEFAULT, - path: '', - inputUrl: null, - outputUrl: null, - pending: true, - } as Span; - pendingSpans.set(spanId, pendingSpan); - } + if (parentSpanIds.length === 0 || parentSpanNames.length === 0) { + continue; + } + if (parentSpanIds.length !== parentSpanNames.length) { + continue; + } + + const startTime = new Date(span.startTime); + const endTime = new Date(span.endTime); + for (let i = 0; i < parentSpanIds.length; i++) { + const spanId = parentSpanIds[i]; + const spanName = parentSpanNames[i]; + + if (existingSpanIds.has(spanId)) { + continue; } + + if (pendingSpans.has(spanId)) { + // if the pending span is already present, just update the start and end time + // to span over all its children + const existingStartTime = new Date(pendingSpans.get(spanId)!.startTime); + const existingEndTime = new Date(pendingSpans.get(spanId)!.endTime); + pendingSpans.set( + spanId, + { + ...pendingSpans.get(spanId)!, + startTime: (startTime < existingStartTime ? startTime : existingStartTime).toISOString(), + endTime: (endTime > existingEndTime ? endTime : existingEndTime).toISOString(), + } + ); + continue; + } + + const parentSpanId = i > 0 ? parentSpanIds[i - 1] : null; + const parentSpanName = i > 0 ? parentSpanNames[i - 1] : null; + const pendingSpan = { + spanId, + name: spanName, + parentSpanId, + parentSpanName, + startTime: new Date(span.startTime).toISOString(), + endTime: new Date(span.endTime).toISOString(), + attributes: {}, + events: [], + logs: [], + spans: [], + traceId: span.traceId, + traceName: span.name, + input: null, + output: null, + inputPreview: null, + outputPreview: null, + spanType: SpanType.DEFAULT, + path: '', + inputUrl: null, + outputUrl: null, + pending: true, + } as Span; + pendingSpans.set(spanId, pendingSpan); } } } diff --git a/frontend/components/traces/traces-table.tsx b/frontend/components/traces/traces-table.tsx index 64dc4d48..fd559009 100644 --- a/frontend/components/traces/traces-table.tsx +++ b/frontend/components/traces/traces-table.tsx @@ -70,10 +70,12 @@ export default function TracesTable({ onRowClick }: TracesTableProps) { const [traceId, setTraceId] = useState( searchParams.get('traceId') ?? null ); - const [enableLiveUpdates, setEnableLiveUpdates] = useState(() => { + const [enableLiveUpdates, setEnableLiveUpdates] = useState(true); + + useEffect(() => { const stored = globalThis?.localStorage?.getItem(LIVE_UPDATES_STORAGE_KEY); - return stored == null ? true : stored === 'true'; - }); + setEnableLiveUpdates(stored == null ? true : stored === 'true'); + }, []); const [activeFilters, setActiveFilters] = useState( filter ? (getFilterFromUrlParams(filter) ?? []) : [] @@ -226,7 +228,12 @@ export default function TracesTable({ onRowClick }: TracesTableProps) { const { supabaseClient: supabase } = useUserContext(); useEffect(() => { - if (!supabase || !enableLiveUpdates) { + if (!supabase) { + return; + } + + if (!enableLiveUpdates) { + supabase.removeAllChannels(); return; }