Log Side Panel: exceptions ui improvements (#118)

This commit is contained in:
Shorpo 2023-11-21 17:26:10 -07:00 committed by GitHub
parent 9c2e279012
commit abe3b12515
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 11 deletions

View file

@ -0,0 +1,5 @@
---
'@hyperdx/app': patch
---
Log Side Panel: exceptions ui improvements

View file

@ -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<StacktraceBreadcrumb[]>(() => {
try {
@ -1875,6 +1876,11 @@ const ExceptionSubpanel = ({
[firstException.stacktrace?.frames],
);
const chronologicalBreadcrumbs = useMemo(
() => breadcrumbs?.slice().reverse() ?? [],
[breadcrumbs],
);
// TODO: show all frames (stackable)
return (
<div>
@ -1936,7 +1942,7 @@ const ExceptionSubpanel = ({
<SectionWrapper>
<Table
columns={breadcrumbColumns}
data={breadcrumbs}
data={chronologicalBreadcrumbs}
emptyMessage="No breadcrumbs found"
/>
</SectionWrapper>
@ -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({
>
<TraceSubpanel
logData={logData}
isException={isException}
onPropertyAddClick={onPropertyAddClick}
generateSearchUrl={generateSearchUrl}
generateChartUrl={generateChartUrl}

View file

@ -158,27 +158,82 @@ export const stacktraceColumns: ColumnDef<StacktraceFrame>[] = [
},
];
const MAX_URL_LENGTH = 120;
const Url = ({ url }: { url?: string }) => (
<span className="text-slate-300" title={url}>
{url == null
? ''
: url.length > MAX_URL_LENGTH
? `${url.slice(0, MAX_URL_LENGTH)}...`
: url}
</span>
);
export const breadcrumbColumns: ColumnDef<StacktraceBreadcrumb>[] = [
{
accessorKey: 'category',
header: 'Category',
size: 180,
cell: ({ row }) => (
<span className="text-slate-300">{row.original.category}</span>
),
},
{
accessorKey: 'message',
header: 'Message',
header: 'Data',
size: UNDEFINED_WIDTH,
cell: ({ row }) =>
row.original.message || <span className="text-slate-500">Empty</span>,
cell: ({ row }) => {
// fetch
if (row.original.category === 'fetch' && row.original.data) {
const { method, url } = row.original.data;
return (
<>
<span>{method} </span>
<span className="text-slate-300" title={url}>
<Url url={url} />
</span>
</>
);
}
// navigation
if (row.original.category === 'navigation' && row.original.data) {
const { from, to } = row.original.data;
return (
<>
<span className="text-slate-300" title={from}>
<Url url={from} />
</span>
<span>{' → '}</span>
<span className="text-slate-300" title={to}>
<Url url={to} />
</span>
</>
);
}
return (
row.original.message || <span className="text-slate-500">Empty</span>
);
},
},
{
accessorKey: 'level',
header: '',
size: 140,
cell: ({ row }) =>
row.original.level ? <LogLevel level={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 ? (
<span className="text-danger"> {status_code}</span>
) : (
<span className="text-slate-500"> {status_code}</span>
);
}
return row.original.level ? (
<LogLevel level={row.original.level} />
) : null;
},
},
{
header: 'Timestamp',
@ -200,9 +255,9 @@ export const headerColumns: ColumnDef<[string, string]>[] = [
header: 'Header',
size: 260,
cell: ({ row }) => (
<span className="text-slate-300 text-truncate" title={row.original[0]}>
<div className="text-slate-300 text-truncate" title={row.original[0]}>
{row.original[0]}
</span>
</div>
),
},
{