@@ -2,11 +2,13 @@ import {
22 createContext ,
33 useCallback ,
44 useContext ,
5+ useEffect ,
56 useMemo ,
67 useRef ,
78 useState ,
89 type Dispatch ,
910} from 'react' ;
11+ import * as Sentry from '@sentry/react' ;
1012
1113import { useOrganizationSeerSetup } from 'sentry/components/events/autofix/useOrganizationSeerSetup' ;
1214import type { SearchQueryBuilderProps } from 'sentry/components/searchQueryBuilder' ;
@@ -26,10 +28,12 @@ import type {
2628import { parseQueryBuilderValue } from 'sentry/components/searchQueryBuilder/utils' ;
2729import type { ParseResult } from 'sentry/components/searchSyntax/parser' ;
2830import type { SavedSearchType , Tag , TagCollection } from 'sentry/types/group' ;
31+ import { defined } from 'sentry/utils' ;
2932import type { FieldDefinition , FieldKind } from 'sentry/utils/fields' ;
3033import { getFieldDefinition } from 'sentry/utils/fields' ;
3134import { useDimensions } from 'sentry/utils/useDimensions' ;
3235import useOrganization from 'sentry/utils/useOrganization' ;
36+ import usePrevious from 'sentry/utils/usePrevious' ;
3337
3438interface SearchQueryBuilderContextData {
3539 actionBarRef : React . RefObject < HTMLDivElement | null > ;
@@ -189,6 +193,35 @@ export function SearchQueryBuilderProvider({
189193 ) ;
190194 const parsedQuery = useMemo ( ( ) => parseQuery ( state . query ) , [ parseQuery , state . query ] ) ;
191195
196+ const previousQuery = usePrevious ( state . query ) ;
197+ const firstRender = useRef ( true ) ;
198+ useEffect ( ( ) => {
199+ // on the first render, we want to check the currently parsed query,
200+ // then on subsequent renders, we want to ensure the parsedQuery hasnt changed
201+ if ( ! firstRender . current && state . query === previousQuery ) {
202+ return ;
203+ }
204+ firstRender . current = false ;
205+
206+ const warnings = parsedQuery ?. filter (
207+ token => 'warning' in token && defined ( token . warning )
208+ ) ?. length ;
209+ if ( warnings ) {
210+ Sentry . metrics . distribution ( 'search-query-builder.token.warnings' , warnings , {
211+ attributes : { searchSource} ,
212+ } ) ;
213+ }
214+
215+ const invalids = parsedQuery ?. filter (
216+ token => 'invalid' in token && defined ( token . invalid )
217+ ) ?. length ;
218+ if ( invalids ) {
219+ Sentry . metrics . distribution ( 'search-query-builder.token.invalids' , invalids , {
220+ attributes : { searchSource} ,
221+ } ) ;
222+ }
223+ } , [ parsedQuery , state . query , previousQuery , searchSource ] ) ;
224+
192225 const handleSearch = useHandleSearch ( {
193226 parsedQuery,
194227 recentSearches,
0 commit comments