Skip to content

Commit 861e1e6

Browse files
Limit log pattern examples to 100 in side panel (#1990)
## Problem When a log pattern has thousands of sample events with large payloads, the `PatternSidePanel` renders all of them at once via `RawLogTable`, causing the page to freeze (HDX-3838). The root cause: up to 10,000 samples are fetched and grouped by pattern. A single pattern can accumulate thousands of rows, and passing all of them to `RawLogTable` at once causes excessive DOM rendering. ## Solution Limit the initial display in `PatternSidePanel` to **100 sample events**. If a pattern has more than 100 samples, a "Show all N samples" button is rendered below the table to let users load the full set on demand. ### Changes in `packages/app/src/components/PatternSidePanel.tsx`: - Added `INITIAL_LIMIT = 100` constant and `showAll` state - `displayedSamples` memo slices `pattern.samples` to the first 100 unless the user clicks "Show all" - Reset `showAll` to `false` when the `pattern` prop changes (user selects a different pattern) - Added a subtle Mantine `Button` below the table when there are more than 100 samples Linear Issue: [HDX-3838](https://linear.app/clickhouse/issue/HDX-3838/investigate-issues-with-large-log-payloads-causing-problems) <div><a href="https://cursor.com/agents/bc-b7a128cb-a5af-465d-862e-97359077eeaa"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-b7a128cb-a5af-465d-862e-97359077eeaa"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> Co-authored-by: Cursor Agent <199161495+cursoragent@users.noreply.github.com>
1 parent b706bbe commit 861e1e6

1 file changed

Lines changed: 27 additions & 2 deletions

File tree

packages/app/src/components/PatternSidePanel.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { JSDataType } from '@hyperdx/common-utils/dist/clickhouse';
33
import { SourceKind, TSource } from '@hyperdx/common-utils/dist/types';
4-
import { Card, Drawer, Stack, Text } from '@mantine/core';
4+
import { Button, Card, Drawer, Stack, Text } from '@mantine/core';
55

66
import DBRowSidePanel from '@/components/DBRowSidePanel';
77
import { RawLogTable } from '@/components/DBRowTable';
@@ -92,6 +92,20 @@ export default function PatternSidePanel({
9292
[getRowWhere],
9393
);
9494

95+
const INITIAL_LIMIT = 100;
96+
const [showAll, setShowAll] = React.useState(false);
97+
98+
React.useEffect(() => {
99+
setShowAll(false);
100+
}, [pattern]);
101+
102+
const displayedSamples = React.useMemo(() => {
103+
if (showAll || pattern.samples.length <= INITIAL_LIMIT) {
104+
return pattern.samples;
105+
}
106+
return pattern.samples.slice(0, INITIAL_LIMIT);
107+
}, [pattern.samples, showAll]);
108+
95109
const handleCloseRowSidePanel = React.useCallback(() => {
96110
setSelectedRowWhere(null);
97111
}, []);
@@ -126,7 +140,7 @@ export default function PatternSidePanel({
126140
~{pattern.count?.toLocaleString()} Sample Events
127141
</Card.Section>
128142
<RawLogTable
129-
rows={pattern.samples}
143+
rows={displayedSamples}
130144
generateRowId={row => ({ where: row.id, aliasWith: [] })}
131145
displayedColumns={displayedColumns}
132146
columnTypeMap={columnTypeMap}
@@ -136,6 +150,17 @@ export default function PatternSidePanel({
136150
showExpandButton={false}
137151
isLive={false}
138152
/>
153+
{!showAll && pattern.samples.length > INITIAL_LIMIT && (
154+
<Button
155+
variant="subtle"
156+
fullWidth
157+
size="xs"
158+
mt="xs"
159+
onClick={() => setShowAll(true)}
160+
>
161+
Show all {pattern.samples.length.toLocaleString()} samples
162+
</Button>
163+
)}
139164
</Card>
140165
</Stack>
141166
</DrawerBody>

0 commit comments

Comments
 (0)