Skip to content

Commit 6a8d5c5

Browse files
committed
feat(discover): Prevent calling Snuba with an empty list of projects
1 parent 34d9222 commit 6a8d5c5

File tree

5 files changed

+39
-7
lines changed

5 files changed

+39
-7
lines changed

src/sentry/search/events/builder/discover.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,13 +583,17 @@ def resolve_params(self) -> list[WhereType]:
583583
if self.end:
584584
conditions.append(Condition(self.column("timestamp"), Op.LT, self.end))
585585

586-
conditions.append(
587-
Condition(
588-
self.column("project_id"),
589-
Op.IN,
590-
self.params.project_ids,
586+
# The clause will prevent calling Snuba with an empty list of projects, thus, returning
587+
# no data. It will not instead complain with:
588+
# sentry.utils.snuba.UnqualifiedQueryError: validation failed for entity events: missing required conditions for project_id
589+
if self.params.project_ids:
590+
conditions.append(
591+
Condition(
592+
self.column("project_id"),
593+
Op.IN,
594+
self.params.project_ids,
595+
)
591596
)
592-
)
593597

594598
if len(self.params.environments) > 0:
595599
term = event_search.SearchFilter(

src/sentry/utils/snuba.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,8 @@ def _bulk_snuba_query(
10221022
raise RateLimitExceeded(error["message"])
10231023
elif error["type"] == "schema":
10241024
raise SchemaValidationError(error["message"])
1025+
elif error["type"] == "invalid_query":
1026+
raise UnqualifiedQueryError(error["message"])
10251027
elif error["type"] == "clickhouse":
10261028
raise clickhouse_error_codes_map.get(error["code"], QueryExecutionError)(
10271029
error["message"]

tests/sentry/api/endpoints/test_organization_dashboard_widget_details.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,8 @@ def test_save_with_invalid_orderby_not_from_columns_or_aggregates(self):
638638
assert "queries" in response.data, response.data
639639

640640
def test_save_with_total_count(self):
641+
# We cannot query the Discover entity without a project being defined for the org
642+
self.create_project()
641643
data = {
642644
"title": "Test Query",
643645
"displayType": "table",

tests/sentry/dynamic_sampling/tasks/test_custom_rule_notifications.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def test_get_num_samples(self):
4949
"""
5050
Tests that the num_samples function returns the correct number of samples
5151
"""
52+
# We cannot query the discover_transactions entity without a project being defined for the org
53+
self.create_project()
5254
num_samples = get_num_samples(self.rule)
5355
assert num_samples == 0
5456
self.create_transaction()

tests/sentry/search/events/builder/test_discover.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
from sentry.search.events.builder import QueryBuilder
1717
from sentry.search.events.types import ParamsType, QueryBuilderConfig
1818
from sentry.snuba.dataset import Dataset
19+
from sentry.snuba.referrer import Referrer
1920
from sentry.testutils.cases import TestCase
20-
from sentry.utils.snuba import QueryOutsideRetentionError
21+
from sentry.utils.snuba import QueryOutsideRetentionError, UnqualifiedQueryError, bulk_snuba_queries
2122
from sentry.utils.validators import INVALID_ID_DETAILS
2223

2324
pytestmark = pytest.mark.sentry_metrics
@@ -67,6 +68,27 @@ def test_simple_query(self):
6768
)
6869
query.get_snql_query().validate()
6970

71+
def test_query_without_project_ids(self):
72+
params: ParamsType = {
73+
"start": self.params["start"],
74+
"end": self.params["end"],
75+
"organization_id": self.organization.id,
76+
}
77+
with pytest.raises(UnqualifiedQueryError):
78+
query = QueryBuilder(Dataset.Discover, params, query="foo", selected_columns=["id"])
79+
bulk_snuba_queries([query.get_snql_query()], referrer=Referrer.TESTING_TEST.value)
80+
81+
def test_query_with_empty_project_ids(self):
82+
params: ParamsType = {
83+
"start": self.params["start"],
84+
"end": self.params["end"],
85+
"project_id": [], # We add an empty project_id list
86+
"organization_id": self.organization.id,
87+
}
88+
with pytest.raises(UnqualifiedQueryError):
89+
query = QueryBuilder(Dataset.Discover, params, query="foo", selected_columns=["id"])
90+
bulk_snuba_queries([query.get_snql_query()], referrer=Referrer.TESTING_TEST.value)
91+
7092
def test_simple_orderby(self):
7193
query = QueryBuilder(
7294
Dataset.Discover,

0 commit comments

Comments
 (0)