From e8dd6dd857eecdafe7cc0f2fc0867b72ddffb0d9 Mon Sep 17 00:00:00 2001 From: Drew Davis Date: Wed, 12 Nov 2025 15:56:03 -0500 Subject: [PATCH] feat: Add filter for root spans --- .changeset/silent-ducks-crash.md | 5 ++ .../src/components/DBSearchPageFilters.tsx | 54 ++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 .changeset/silent-ducks-crash.md diff --git a/.changeset/silent-ducks-crash.md b/.changeset/silent-ducks-crash.md new file mode 100644 index 000000000..5fa8d0a46 --- /dev/null +++ b/.changeset/silent-ducks-crash.md @@ -0,0 +1,5 @@ +--- +"@hyperdx/app": patch +--- + +feat: Add filter for root spans diff --git a/packages/app/src/components/DBSearchPageFilters.tsx b/packages/app/src/components/DBSearchPageFilters.tsx index cac03700b..1e0eb21be 100644 --- a/packages/app/src/components/DBSearchPageFilters.tsx +++ b/packages/app/src/components/DBSearchPageFilters.tsx @@ -13,7 +13,10 @@ import { tcFromChartConfig, tcFromSource, } from '@hyperdx/common-utils/dist/core/metadata'; -import { ChartConfigWithDateRange } from '@hyperdx/common-utils/dist/types'; +import { + ChartConfigWithDateRange, + SourceKind, +} from '@hyperdx/common-utils/dist/types'; import { Accordion, ActionIcon, @@ -186,7 +189,7 @@ export const FilterCheckbox = ({ flex={1} title={label} > - {label} + {label || (empty)} {percentage != null && ( { + if (!source?.parentSpanIdExpression) return; + + if (rootSpansOnly) { + setFilterValue(source.parentSpanIdExpression, '', 'only'); + } else { + clearFilter(source.parentSpanIdExpression); + } + }, + [setFilterValue, clearFilter, source], + ); + + const isRootSpansOnly = useMemo(() => { + if (!source?.parentSpanIdExpression || source.kind !== SourceKind.Trace) + return false; + + const parentSpanIdFilter = filterState?.[source?.parentSpanIdExpression]; + return ( + parentSpanIdFilter?.included.size === 1 && + parentSpanIdFilter?.included.has('') + ); + }, [filterState, source]); + return (
@@ -996,6 +1023,29 @@ const DBSearchPageFiltersComponent = ({ /> )} + {source?.kind === SourceKind.Trace && + source.parentSpanIdExpression && ( + + + Root Spans Only + + + } + onChange={event => setRootSpansOnly(event.target.checked)} + /> + )} + {isLoading || isFacetsLoading ? (