diff --git a/.changeset/young-pans-search.md b/.changeset/young-pans-search.md new file mode 100644 index 00000000..3560f540 --- /dev/null +++ b/.changeset/young-pans-search.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/app': patch +--- + +Log Side Panel: exceptions ui improvements diff --git a/packages/app/src/LogSidePanel.tsx b/packages/app/src/LogSidePanel.tsx index 75a7947c..51e7467b 100644 --- a/packages/app/src/LogSidePanel.tsx +++ b/packages/app/src/LogSidePanel.tsx @@ -492,6 +492,7 @@ function isExceptionSpan({ logData }: { logData: any }) { function TraceSubpanel({ logData, + isException, onClose, onPropertyAddClick, generateChartUrl, @@ -500,6 +501,7 @@ function TraceSubpanel({ toggleColumn, }: { logData: any; + isException: boolean; onClose: () => void; generateSearchUrl: (query?: string, timeRange?: [Date, Date]) => string; generateChartUrl: (config: { @@ -558,7 +560,6 @@ function TraceSubpanel({ }, [_searchedQuery, _inputQuery]); // Allows us to determine if the user has changed the search query const searchedQuery = _searchedQuery ?? ''; - const isException = isExceptionSpan({ logData: selectedLogData }); const exceptionBreadcrumbs = useMemo(() => { try { @@ -1875,6 +1876,11 @@ const ExceptionSubpanel = ({ [firstException.stacktrace?.frames], ); + const chronologicalBreadcrumbs = useMemo( + () => breadcrumbs?.slice().reverse() ?? [], + [breadcrumbs], + ); + // TODO: show all frames (stackable) return (
@@ -1936,7 +1942,7 @@ const ExceptionSubpanel = ({ @@ -2011,7 +2017,11 @@ export default function LogSidePanel({ }, [setQueryTab, isNestedPanel, onClose]); const logData = useMemo(() => logDataRaw?.data[0], [logDataRaw]); - const displayedTab = tab ?? (logData?.type === 'span' ? 'trace' : 'parsed'); + + const isException = useMemo(() => isExceptionSpan({ logData }), [logData]); + + const displayedTab = + tab ?? (logData?.type === 'span' || isException ? 'trace' : 'parsed'); // Keep track of sub-drawers so we can disable closing this root drawer const [subDrawerOpen, setSubDrawerOpen] = useState(false); @@ -2177,6 +2187,7 @@ export default function LogSidePanel({ > [] = [ }, ]; +const MAX_URL_LENGTH = 120; +const Url = ({ url }: { url?: string }) => ( + + {url == null + ? '' + : url.length > MAX_URL_LENGTH + ? `${url.slice(0, MAX_URL_LENGTH)}...` + : url} + +); + export const breadcrumbColumns: ColumnDef[] = [ { accessorKey: 'category', header: 'Category', + size: 180, cell: ({ row }) => ( {row.original.category} ), }, { accessorKey: 'message', - header: 'Message', + header: 'Data', size: UNDEFINED_WIDTH, - cell: ({ row }) => - row.original.message || Empty, + cell: ({ row }) => { + // fetch + if (row.original.category === 'fetch' && row.original.data) { + const { method, url } = row.original.data; + return ( + <> + {method} + + + + + ); + } + + // navigation + if (row.original.category === 'navigation' && row.original.data) { + const { from, to } = row.original.data; + return ( + <> + + + + {' → '} + + + + + ); + } + + return ( + row.original.message || Empty + ); + }, }, { accessorKey: 'level', header: '', - size: 140, - cell: ({ row }) => - row.original.level ? : null, + size: 80, + cell: ({ row }) => { + if (row.original.category === 'fetch' && row.original.data) { + const { status_code } = row.original.data; + return parseInt(status_code) >= 400 ? ( + {status_code} + ) : ( + {status_code} + ); + } + return row.original.level ? ( + + ) : null; + }, }, { header: 'Timestamp', @@ -200,9 +255,9 @@ export const headerColumns: ColumnDef<[string, string]>[] = [ header: 'Header', size: 260, cell: ({ row }) => ( - +
{row.original[0]} - +
), }, {