Skip to content

Commit 3332d5e

Browse files
Event Deltas Heatmap Customization (#1246)
Introduces the ability to edit the y, count, and group by values on the search event deltas heatmap allowing for deeper analysis https://github.com/user-attachments/assets/1f4d7ca2-86be-424a-84de-23eccaf02a68 Fixes HDX-2422
1 parent 2f49f9b commit 3332d5e

File tree

7 files changed

+434
-107
lines changed

7 files changed

+434
-107
lines changed

.changeset/many-donkeys-help.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": patch
3+
---
4+
5+
Add ability to customize event deltas heat map y, count, and grouping attributes

packages/app/src/ChartUtils.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,23 @@ export function timeBucketByGranularity(
385385
return buckets;
386386
}
387387

388+
export const isAggregateFunction = (value: string) => {
389+
const fns = [
390+
'count',
391+
'countIf',
392+
'countDistinct',
393+
'sum',
394+
'avg',
395+
'distinct',
396+
'min',
397+
'max',
398+
'quantile',
399+
'any',
400+
'none',
401+
];
402+
return fns.some(fn => value.includes(fn + '('));
403+
};
404+
388405
export const INTEGER_NUMBER_FORMAT: NumberFormat = {
389406
factor: 1,
390407
output: 'number',

packages/app/src/DBSearchPage.tsx

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
Flex,
4444
Grid,
4545
Group,
46+
Input,
4647
Menu,
4748
Modal,
4849
Paper,
@@ -60,8 +61,6 @@ import { SortingState } from '@tanstack/react-table';
6061
import CodeMirror from '@uiw/react-codemirror';
6162

6263
import { ContactSupportText } from '@/components/ContactSupportText';
63-
import DBDeltaChart from '@/components/DBDeltaChart';
64-
import DBHeatmapChart from '@/components/DBHeatmapChart';
6564
import { DBSearchPageFilters } from '@/components/DBSearchPageFilters';
6665
import { DBTimeChart } from '@/components/DBTimeChart';
6766
import { ErrorBoundary } from '@/components/ErrorBoundary';
@@ -88,7 +87,6 @@ import {
8887
import { useSearchPageFilterState } from '@/searchFilters';
8988
import SearchInputV2 from '@/SearchInputV2';
9089
import {
91-
getDurationMsExpression,
9290
getFirstTimestampValueExpression,
9391
useSource,
9492
useSources,
@@ -99,6 +97,7 @@ import { QUERY_LOCAL_STORAGE, useLocalStorage, usePrevious } from '@/utils';
9997
import { SQLPreview } from './components/ChartSQLPreview';
10098
import DBSqlRowTableWithSideBar from './components/DBSqlRowTableWithSidebar';
10199
import PatternTable from './components/PatternTable';
100+
import { DBSearchHeatmapChart } from './components/Search/DBSearchHeatmapChart';
102101
import SourceSchemaPreview from './components/SourceSchemaPreview';
103102
import { useTableMetadata } from './hooks/useMetadata';
104103
import { useSqlSuggestions } from './hooks/useSqlSuggestions';
@@ -1583,57 +1582,15 @@ function DBSearchPage() {
15831582
</Flex>
15841583
)}
15851584
{analysisMode === 'delta' && searchedSource != null && (
1586-
<Flex direction="column" w="100%">
1587-
<div
1588-
style={{ minHeight: 210, maxHeight: 210, width: '100%' }}
1589-
>
1590-
<DBHeatmapChart
1591-
config={{
1592-
...chartConfig,
1593-
select: [
1594-
{
1595-
aggFn: 'heatmap',
1596-
valueExpression:
1597-
getDurationMsExpression(searchedSource),
1598-
},
1599-
],
1600-
dateRange: searchedTimeRange,
1601-
displayType: DisplayType.Heatmap,
1602-
granularity: 'auto',
1603-
with: aliasWith,
1604-
}}
1605-
enabled={isReady}
1606-
onFilter={(xMin, xMax, yMin, yMax) => {
1607-
setOutlierSqlCondition(
1608-
[
1609-
`${searchedSource.durationExpression} >= ${yMin} * 1e${(searchedSource.durationPrecision ?? 9) - 3}`,
1610-
`${searchedSource.durationExpression} <= ${yMax} * 1e${(searchedSource.durationPrecision ?? 9) - 3}`,
1611-
`${getFirstTimestampValueExpression(chartConfig.timestampValueExpression)} >= ${xMin}`,
1612-
`${getFirstTimestampValueExpression(chartConfig.timestampValueExpression)} <= ${xMax}`,
1613-
].join(' AND '),
1614-
);
1615-
}}
1616-
/>
1617-
</div>
1618-
{outlierSqlCondition ? (
1619-
<DBDeltaChart
1620-
config={{
1621-
...chartConfig,
1622-
dateRange: searchedTimeRange,
1623-
}}
1624-
outlierSqlCondition={outlierSqlCondition ?? ''}
1625-
/>
1626-
) : (
1627-
<Paper shadow="xs" p="xl" h="100%">
1628-
<Center mih={100} h="100%">
1629-
<Text size="sm" c="gray.4">
1630-
Please highlight an outlier range in the heatmap to
1631-
view the delta chart.
1632-
</Text>
1633-
</Center>
1634-
</Paper>
1635-
)}
1636-
</Flex>
1585+
<DBSearchHeatmapChart
1586+
chartConfig={{
1587+
...chartConfig,
1588+
dateRange: searchedTimeRange,
1589+
with: aliasWith,
1590+
}}
1591+
isReady={isReady}
1592+
source={searchedSource}
1593+
/>
16371594
)}
16381595
<div style={{ display: 'flex', flexDirection: 'column' }}>
16391596
{analysisMode === 'results' &&

packages/app/src/components/DBDeltaChart.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,12 @@ export default function DBDeltaChart({
334334
const { percentageOccurences: inlierValueOccurences } =
335335
getPropertyStatistics(inlierData?.data ?? []);
336336

337-
const sortedProperties = Array.from(outlierValueOccurences.keys())
337+
// Get all the unique keys from both maps, and process them to get the merged arrays
338+
const uniqueKeys = new Set([
339+
...outlierValueOccurences.keys(),
340+
...inlierValueOccurences.keys(),
341+
]);
342+
const sortedProperties = Array.from(uniqueKeys)
338343
.map(key => {
339344
const inlierCount =
340345
inlierValueOccurences.get(key) ?? new Map<string, number>();

0 commit comments

Comments
 (0)