@@ -27,7 +27,11 @@ import {
2727} from '@hyperdx/common-utils/dist/types' ;
2828import { splitAndTrimWithBracket } from '@hyperdx/common-utils/dist/utils' ;
2929import { Box , Code , Flex , Text } from '@mantine/core' ;
30- import { FetchNextPageOptions } from '@tanstack/react-query' ;
30+ import {
31+ FetchNextPageOptions ,
32+ useQuery ,
33+ useQueryClient ,
34+ } from '@tanstack/react-query' ;
3135import {
3236 ColumnDef ,
3337 ColumnResizeMode ,
@@ -41,6 +45,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
4145
4246import { useTableMetadata } from '@/hooks/useMetadata' ;
4347import useOffsetPaginatedQuery from '@/hooks/useOffsetPaginatedQuery' ;
48+ import { useGroupedPatterns } from '@/hooks/usePatterns' ;
4449import useRowWhere from '@/hooks/useRowWhere' ;
4550import { UNDEFINED_WIDTH } from '@/tableUtils' ;
4651import { FormatTime } from '@/useFormatTime' ;
@@ -900,6 +905,7 @@ export function DBSqlRowTable({
900905 isLive = false ,
901906 queryKeyPrefix,
902907 onScroll,
908+ denoiseResults = false ,
903909} : {
904910 config : ChartConfigWithDateRange ;
905911 onRowExpandClick ?: ( where : string ) => void ;
@@ -909,6 +915,7 @@ export function DBSqlRowTable({
909915 isLive ?: boolean ;
910916 onScroll ?: ( scrollTop : number ) => void ;
911917 onError ?: ( error : Error | ClickHouseQueryError ) => void ;
918+ denoiseResults ?: boolean ;
912919} ) {
913920 const mergedConfig = useConfigWithPrimaryAndPartitionKey ( config ) ;
914921
@@ -964,7 +971,7 @@ export function DBSqlRowTable({
964971 } ) ;
965972 return newRow ;
966973 } ) ;
967- } , [ data , objectTypeColumns ] ) ;
974+ } , [ data , objectTypeColumns , columnMap ] ) ;
968975
969976 const aliasMap = chSqlToAliasMap ( data ?. chSql ?? { sql : '' , params : { } } ) ;
970977
@@ -983,23 +990,117 @@ export function DBSqlRowTable({
983990 }
984991 } , [ isError , onError , error ] ) ;
985992
993+ const patternColumn = columns [ columns . length - 1 ] ;
994+ const groupedPatterns = useGroupedPatterns ( {
995+ config,
996+ samples : 10_000 ,
997+ bodyValueExpression : patternColumn ?? '' ,
998+ totalCount : undefined ,
999+ enabled : denoiseResults ,
1000+ } ) ;
1001+ const noisyPatterns = useQuery ( {
1002+ queryKey : [ 'noisy-patterns' , config ] ,
1003+ queryFn : async ( ) => {
1004+ return Object . values ( groupedPatterns . data ) . filter (
1005+ p => p . count / ( groupedPatterns . sampledRowCount ?? 1 ) > 0.1 ,
1006+ ) ;
1007+ } ,
1008+ enabled :
1009+ denoiseResults &&
1010+ groupedPatterns . data != null &&
1011+ Object . values ( groupedPatterns . data ) . length > 0 &&
1012+ groupedPatterns . miner != null ,
1013+ } ) ;
1014+ const noisyPatternIds = useMemo ( ( ) => {
1015+ return noisyPatterns . data ?. map ( p => p . id ) ?? [ ] ;
1016+ } , [ noisyPatterns . data ] ) ;
1017+
1018+ const queryClient = useQueryClient ( ) ;
1019+
1020+ const denoisedRows = useQuery ( {
1021+ queryKey : [
1022+ 'denoised-rows' ,
1023+ config ,
1024+ processedRows ,
1025+ noisyPatternIds ,
1026+ patternColumn ,
1027+ ] ,
1028+ queryFn : async ( ) => {
1029+ // No noisy patterns, so no need to denoise
1030+ if ( noisyPatternIds . length === 0 ) {
1031+ return processedRows ;
1032+ }
1033+
1034+ const matchedLogs = await groupedPatterns . miner ?. matchLogs (
1035+ processedRows . map ( row => row [ patternColumn ] ) ,
1036+ ) ;
1037+ return processedRows . filter ( ( row , i ) => {
1038+ const match = matchedLogs ?. [ i ] ;
1039+ return ! noisyPatternIds . includes ( `${ match } ` ) ;
1040+ } ) ;
1041+ } ,
1042+ placeholderData : ( previousData , previousQuery ) => {
1043+ // If it's the same search, but new data, return the previous data while we load
1044+ if (
1045+ previousQuery ?. queryKey ?. [ 0 ] === 'denoised-rows' &&
1046+ previousQuery ?. queryKey ?. [ 1 ] === config
1047+ ) {
1048+ return previousData ;
1049+ }
1050+ return undefined ;
1051+ } ,
1052+ enabled :
1053+ denoiseResults &&
1054+ noisyPatterns . isSuccess &&
1055+ processedRows . length > 0 &&
1056+ groupedPatterns . miner != null ,
1057+ } ) ;
1058+
1059+ const isLoading = denoiseResults
1060+ ? isFetching ||
1061+ denoisedRows . isFetching ||
1062+ noisyPatterns . isFetching ||
1063+ groupedPatterns . isLoading
1064+ : isFetching ;
1065+
9861066 return (
987- < RawLogTable
988- isLive = { isLive }
989- wrapLines = { false }
990- displayedColumns = { columns }
991- highlightedLineId = { highlightedLineId }
992- rows = { processedRows }
993- isLoading = { isFetching }
994- fetchNextPage = { fetchNextPage }
995- // onPropertySearchClick={onPropertySearchClick}
996- hasNextPage = { hasNextPage }
997- onRowExpandClick = { _onRowExpandClick }
998- onScroll = { onScroll }
999- generateRowId = { getRowWhere }
1000- isError = { isError }
1001- error = { error ?? undefined }
1002- columnTypeMap = { columnMap }
1003- />
1067+ < >
1068+ { denoiseResults && (
1069+ < Box mb = "xxs" px = "sm" mt = "-24px" >
1070+ < Text fw = "bold" fz = "xs" mb = "xxs" >
1071+ Removed Noisy Event Patterns
1072+ </ Text >
1073+ < Box mah = { 100 } style = { { overflow : 'auto' } } >
1074+ { noisyPatterns . data ?. map ( p => (
1075+ < Text c = "gray.3" fz = "xs" key = { p . id } >
1076+ { p . pattern }
1077+ </ Text >
1078+ ) ) }
1079+ { noisyPatternIds . length === 0 && (
1080+ < Text c = "gray.3" fz = "xs" >
1081+ No noisy patterns found
1082+ </ Text >
1083+ ) }
1084+ </ Box >
1085+ </ Box >
1086+ ) }
1087+ < RawLogTable
1088+ isLive = { isLive }
1089+ wrapLines = { false }
1090+ displayedColumns = { columns }
1091+ highlightedLineId = { highlightedLineId }
1092+ rows = { denoiseResults ? ( denoisedRows ?. data ?? [ ] ) : processedRows }
1093+ isLoading = { isLoading }
1094+ fetchNextPage = { fetchNextPage }
1095+ // onPropertySearchClick={onPropertySearchClick}
1096+ hasNextPage = { hasNextPage }
1097+ onRowExpandClick = { _onRowExpandClick }
1098+ onScroll = { onScroll }
1099+ generateRowId = { getRowWhere }
1100+ isError = { isError }
1101+ error = { error ?? undefined }
1102+ columnTypeMap = { columnMap }
1103+ />
1104+ </ >
10041105 ) ;
10051106}
0 commit comments