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>
This commit is contained in:
Mike Shi 2026-03-25 19:20:55 -07:00 committed by GitHub
parent 4318d0a3c3
commit fb8a7e990d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import { JSDataType } from '@hyperdx/common-utils/dist/clickhouse';
import { SourceKind, TSource } from '@hyperdx/common-utils/dist/types';
import { Card, Drawer, Stack, Text } from '@mantine/core';
import { Button, Card, Drawer, Stack, Text } from '@mantine/core';
import DBRowSidePanel from '@/components/DBRowSidePanel';
import { RawLogTable } from '@/components/DBRowTable';
@ -92,6 +92,20 @@ export default function PatternSidePanel({
[getRowWhere],
);
const INITIAL_LIMIT = 100;
const [showAll, setShowAll] = React.useState(false);
React.useEffect(() => {
setShowAll(false);
}, [pattern]);
const displayedSamples = React.useMemo(() => {
if (showAll || pattern.samples.length <= INITIAL_LIMIT) {
return pattern.samples;
}
return pattern.samples.slice(0, INITIAL_LIMIT);
}, [pattern.samples, showAll]);
const handleCloseRowSidePanel = React.useCallback(() => {
setSelectedRowWhere(null);
}, []);
@ -126,7 +140,7 @@ export default function PatternSidePanel({
~{pattern.count?.toLocaleString()} Sample Events
</Card.Section>
<RawLogTable
rows={pattern.samples}
rows={displayedSamples}
generateRowId={row => ({ where: row.id, aliasWith: [] })}
displayedColumns={displayedColumns}
columnTypeMap={columnTypeMap}
@ -136,6 +150,17 @@ export default function PatternSidePanel({
showExpandButton={false}
isLive={false}
/>
{!showAll && pattern.samples.length > INITIAL_LIMIT && (
<Button
variant="subtle"
fullWidth
size="xs"
mt="xs"
onClick={() => setShowAll(true)}
>
Show all {pattern.samples.length.toLocaleString()} samples
</Button>
)}
</Card>
</Stack>
</DrawerBody>