Skip to content

Commit 7f3a081

Browse files
authored
chore(search): Remove snuba-first-search logic and tests (#95586)
1 parent 6327d5a commit 7f3a081

File tree

7 files changed

+254
-2657
lines changed

7 files changed

+254
-2657
lines changed

src/sentry/features/temporary.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,6 @@ def register_temporary_features(manager: FeatureManager):
159159
manager.add("organizations:issue-detection-sort-spans", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
160160
# Whether to allow issue only search on the issue list
161161
manager.add("organizations:issue-search-allow-postgres-only-search", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
162-
# Whether to make a side/parallel query against events -> group_attributes when searching issues
163-
manager.add("organizations:issue-search-group-attributes-side-query", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
164-
# Enable issue stream performance improvements
165-
manager.add("organizations:issue-search-snuba", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
166162
# Enable the new issue category mapping
167163
manager.add("organizations:issue-taxonomy", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
168164
manager.add("organizations:metric-issue-poc", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)

src/sentry/issues/endpoints/organization_group_index.py

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from datetime import datetime, timedelta
44
from typing import Any
55

6-
import sentry_sdk
76
from django.utils import timezone
87
from drf_spectacular.utils import extend_schema
98
from rest_framework.exceptions import ParseError, PermissionDenied
@@ -61,7 +60,7 @@
6160
from sentry.models.project import Project
6261
from sentry.search.events.constants import EQUALITY_OPERATORS
6362
from sentry.search.snuba.backend import assigned_or_suggested_filter
64-
from sentry.search.snuba.executors import FIRST_RELEASE_FILTERS, get_search_filter
63+
from sentry.search.snuba.executors import get_search_filter
6564
from sentry.utils.cursors import Cursor, CursorResult
6665
from sentry.utils.validators import normalize_event_id
6766

@@ -195,36 +194,7 @@ def _search(
195194
query_kwargs.pop("sort_by")
196195
result = inbox_search(**query_kwargs)
197196
else:
198-
199-
def use_group_snuba_dataset() -> bool:
200-
# if useGroupSnubaDataset is present, override the flag so we can test the new dataset
201-
# XXX: This query param is omitted from the API docs as it is currently internal.
202-
req_param_value: str | None = request.GET.get("useGroupSnubaDataset")
203-
if req_param_value and req_param_value.lower() == "true":
204-
return True
205-
206-
if not features.has("organizations:issue-search-snuba", organization):
207-
return False
208-
209-
# haven't migrated trends
210-
if query_kwargs["sort_by"] == "trends":
211-
return False
212-
213-
# check for the first_release search filters, which require postgres if the environment is specified
214-
if environments:
215-
return all(
216-
sf.key.name not in FIRST_RELEASE_FILTERS
217-
for sf in query_kwargs.get("search_filters", [])
218-
)
219-
220-
return True
221-
222197
query_kwargs["referrer"] = "search.group_index"
223-
query_kwargs["use_group_snuba_dataset"] = use_group_snuba_dataset()
224-
sentry_sdk.set_tag(
225-
"search.use_group_snuba_dataset", query_kwargs["use_group_snuba_dataset"]
226-
)
227-
228198
result = search.backend.query(**query_kwargs)
229199
return result, query_kwargs
230200

src/sentry/search/snuba/backend.py

Lines changed: 9 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
from __future__ import annotations
22

3-
import atexit
43
import functools
54
import logging
65
from abc import ABCMeta, abstractmethod
76
from collections import defaultdict
87
from collections.abc import Callable, Mapping, Sequence
9-
from concurrent.futures import ThreadPoolExecutor
108
from datetime import datetime, timedelta
119
from typing import Any
1210

1311
from django.db.models import Q
1412
from django.utils import timezone
1513
from django.utils.functional import SimpleLazyObject
1614

17-
from sentry import features, quotas
15+
from sentry import quotas
1816
from sentry.api.event_search import SearchFilter
1917
from sentry.db.models.manager.base_query_set import BaseQuerySet
2018
from sentry.exceptions import InvalidSearchQuery
@@ -33,9 +31,7 @@
3331
from sentry.search.base import SearchBackend
3432
from sentry.search.events.constants import EQUALITY_OPERATORS, OPERATOR_TO_DJANGO
3533
from sentry.search.snuba.executors import (
36-
POSTGRES_ONLY_SEARCH_FIELDS,
3734
AbstractQueryExecutor,
38-
InvalidQueryForExecutor,
3935
PostgresSnubaQueryExecutor,
4036
TrendsSortWeights,
4137
)
@@ -286,147 +282,6 @@ def seer_actionability_filter(trigger_values: list[float]) -> Q:
286282
return query
287283

288284

289-
_side_query_pool = ThreadPoolExecutor(max_workers=10)
290-
291-
atexit.register(_side_query_pool.shutdown, False)
292-
293-
294-
def _group_attributes_side_query(
295-
events_only_search_results: CursorResult[Group],
296-
builder: Callable[[], BaseQuerySet[Group, Group]],
297-
projects: Sequence[Project],
298-
retention_window_start: datetime | None,
299-
group_queryset: BaseQuerySet[Group, Group],
300-
environments: Sequence[Environment] | None = None,
301-
sort_by: str = "date",
302-
limit: int = 100,
303-
cursor: Cursor | None = None,
304-
count_hits: bool = False,
305-
paginator_options: Mapping[str, Any] | None = None,
306-
search_filters: Sequence[SearchFilter] | None = None,
307-
date_from: datetime | None = None,
308-
date_to: datetime | None = None,
309-
max_hits: int | None = None,
310-
referrer: str | None = None,
311-
actor: Any | None = None,
312-
aggregate_kwargs: TrendsSortWeights | None = None,
313-
) -> None:
314-
def __run_joined_query_and_log_metric(
315-
events_only_search_results: CursorResult[Group],
316-
builder: Callable[[], BaseQuerySet[Group, Group]],
317-
projects: Sequence[Project],
318-
retention_window_start: datetime | None,
319-
group_queryset: BaseQuerySet[Group, Group],
320-
environments: Sequence[Environment] | None = None,
321-
sort_by: str = "date",
322-
limit: int = 100,
323-
cursor: Cursor | None = None,
324-
count_hits: bool = False,
325-
paginator_options: Mapping[str, Any] | None = None,
326-
search_filters: Sequence[SearchFilter] | None = None,
327-
date_from: datetime | None = None,
328-
date_to: datetime | None = None,
329-
max_hits: int | None = None,
330-
referrer: str | None = None,
331-
actor: Any | None = None,
332-
aggregate_kwargs: TrendsSortWeights | None = None,
333-
) -> None:
334-
from sentry.utils import metrics
335-
336-
try:
337-
from sentry.search.snuba.executors import GroupAttributesPostgresSnubaQueryExecutor
338-
339-
executor = GroupAttributesPostgresSnubaQueryExecutor()
340-
with metrics.timer("snuba.search.group_attributes_joined.duration"):
341-
cursor_results = executor.query(
342-
projects,
343-
retention_window_start,
344-
builder(),
345-
environments,
346-
sort_by,
347-
limit,
348-
cursor,
349-
count_hits,
350-
paginator_options,
351-
search_filters,
352-
date_from,
353-
date_to,
354-
max_hits,
355-
referrer,
356-
actor,
357-
aggregate_kwargs,
358-
)
359-
joined_hits = len(cursor_results.results)
360-
events_only_search_hits = len(events_only_search_results.results)
361-
if events_only_search_hits > 0:
362-
if joined_hits == events_only_search_hits:
363-
comparison = "equal"
364-
elif joined_hits > events_only_search_hits:
365-
comparison = "greater"
366-
else:
367-
# the joined query shouldn't have fewer hits since the query is deliberately less restrictive
368-
comparison = "less"
369-
370-
metrics.incr(
371-
"snuba.search.group_attributes_joined.events_compared",
372-
tags={"comparison": comparison},
373-
)
374-
375-
metrics.incr("snuba.search.group_attributes_joined.query", tags={"exception": "none"})
376-
except InvalidQueryForExecutor as e:
377-
logger.info(
378-
"unsupported query received in GroupAttributesPostgresSnubaQueryExecutor",
379-
exc_info=True,
380-
)
381-
metrics.incr(
382-
"snuba.search.group_attributes_joined.query",
383-
tags={
384-
"exception": f"{type(e).__module__}.{type(e).__qualname__}",
385-
},
386-
)
387-
except Exception as e:
388-
logger.warning(
389-
"failed to load side query from _group_attributes_side_query", exc_info=True
390-
)
391-
metrics.incr(
392-
"snuba.search.group_attributes_joined.query",
393-
tags={
394-
"exception": f"{type(e).__module__}.{type(e).__qualname__}",
395-
},
396-
)
397-
finally:
398-
# since this code is running in a thread and django establishes a connection per thread, we need to
399-
# explicitly close the connection assigned to this thread to avoid linger connections
400-
from django.db import connection
401-
402-
connection.close()
403-
404-
try:
405-
_side_query_pool.submit(
406-
__run_joined_query_and_log_metric,
407-
events_only_search_results,
408-
builder,
409-
projects,
410-
retention_window_start,
411-
group_queryset,
412-
environments,
413-
sort_by,
414-
limit,
415-
cursor,
416-
count_hits,
417-
paginator_options,
418-
search_filters,
419-
date_from,
420-
date_to,
421-
max_hits,
422-
referrer,
423-
actor,
424-
aggregate_kwargs,
425-
)
426-
except Exception:
427-
logger.exception("failed to submit group-attributes search side-query to pool")
428-
429-
430285
class Condition:
431286
"""\
432287
Adds a single filter to a ``QuerySet`` object. Used with
@@ -520,7 +375,6 @@ def query(
520375
referrer: str | None = None,
521376
actor: Any | None = None,
522377
aggregate_kwargs: TrendsSortWeights | None = None,
523-
use_group_snuba_dataset: bool = False,
524378
) -> CursorResult[Group]:
525379
search_filters = search_filters if search_filters is not None else []
526380
# ensure projects are from same org
@@ -537,22 +391,14 @@ def query(
537391
else:
538392
retention_window_start = None
539393

540-
if use_group_snuba_dataset:
541-
# we need to handle two cases fo the group queryset:
542-
# 1. Limit results to groups that are not pending deletion or merge
543-
# 2. Handle queries snuba doesn't support such as bookmarked_by, linked, subscribed_by, etc
544-
# For the second case, we hit postgres before Snuba to get the group ids
545-
group_queryset = self._build_limited_group_queryset(projects, search_filters)
546-
547-
else:
548-
group_queryset = self._build_group_queryset(
549-
projects=projects,
550-
environments=environments,
551-
search_filters=search_filters,
552-
retention_window_start=retention_window_start,
553-
date_from=date_from,
554-
date_to=date_to,
555-
)
394+
group_queryset = self._build_group_queryset(
395+
projects=projects,
396+
environments=environments,
397+
search_filters=search_filters,
398+
retention_window_start=retention_window_start,
399+
date_from=date_from,
400+
date_to=date_to,
401+
)
556402

557403
query_executor = self._get_query_executor(
558404
group_queryset=group_queryset,
@@ -561,7 +407,6 @@ def query(
561407
search_filters=search_filters,
562408
date_from=date_from,
563409
date_to=date_to,
564-
use_group_snuba_dataset=use_group_snuba_dataset,
565410
)
566411

567412
# ensure sort strategy is supported by executor
@@ -588,69 +433,8 @@ def query(
588433
aggregate_kwargs=aggregate_kwargs,
589434
)
590435

591-
if len(projects) > 0 and features.has(
592-
"organizations:issue-search-group-attributes-side-query", projects[0].organization
593-
):
594-
new_group_queryset = self._build_group_queryset(
595-
projects=projects,
596-
environments=environments,
597-
search_filters=search_filters,
598-
retention_window_start=retention_window_start,
599-
date_from=date_from,
600-
date_to=date_to,
601-
)
602-
603-
builder = functools.partial(
604-
self._build_group_queryset,
605-
projects=projects,
606-
environments=environments,
607-
search_filters=search_filters,
608-
retention_window_start=retention_window_start,
609-
date_from=date_from,
610-
date_to=date_to,
611-
)
612-
613-
_group_attributes_side_query(
614-
events_only_search_results=query_results,
615-
builder=builder,
616-
projects=projects,
617-
retention_window_start=retention_window_start,
618-
group_queryset=new_group_queryset,
619-
environments=environments,
620-
sort_by=sort_by,
621-
limit=limit,
622-
cursor=cursor,
623-
count_hits=count_hits,
624-
paginator_options=paginator_options,
625-
search_filters=search_filters,
626-
date_from=date_from,
627-
date_to=date_to,
628-
max_hits=max_hits,
629-
referrer=referrer,
630-
actor=actor,
631-
aggregate_kwargs=aggregate_kwargs,
632-
)
633-
634436
return query_results
635437

636-
def _build_limited_group_queryset(
637-
self, projects: Sequence[Project], search_filters: Sequence[SearchFilter]
638-
) -> BaseQuerySet[Group, Group]:
639-
"""
640-
Builds a group queryset to handle joins for data that doesn't exist in Clickhouse on the group_attributes dataset
641-
"""
642-
# Filter search_filters to only include 'bookmarked_by', 'linked', 'subscribed_by'
643-
filtered_search_filters = [
644-
sf for sf in search_filters if sf.key.name in POSTGRES_ONLY_SEARCH_FIELDS
645-
]
646-
# Use the filtered search filters for further processing
647-
return self._build_group_queryset(
648-
projects=projects,
649-
environments=None,
650-
search_filters=filtered_search_filters,
651-
retention_window_start=None,
652-
)
653-
654438
def _build_group_queryset(
655439
self,
656440
projects: Sequence[Project],
@@ -721,7 +505,6 @@ def _get_query_executor(
721505
search_filters: Sequence[SearchFilter],
722506
date_from: datetime | None,
723507
date_to: datetime | None,
724-
use_group_snuba_dataset: bool,
725508
) -> AbstractQueryExecutor:
726509
"""This method should return an implementation of the AbstractQueryExecutor
727510
We will end up calling .query() on the class returned by this method"""
@@ -730,10 +513,6 @@ def _get_query_executor(
730513

731514
class EventsDatasetSnubaSearchBackend(SnubaSearchBackendBase):
732515
def _get_query_executor(self, *args: Any, **kwargs: Any) -> AbstractQueryExecutor:
733-
if kwargs.get("use_group_snuba_dataset"):
734-
from sentry.search.snuba.executors import GroupAttributesPostgresSnubaQueryExecutor
735-
736-
return GroupAttributesPostgresSnubaQueryExecutor()
737516
return PostgresSnubaQueryExecutor()
738517

739518
def _get_queryset_conditions(

0 commit comments

Comments
 (0)