diff --git a/src/sentry/api/endpoints/organization_events_timeseries.py b/src/sentry/api/endpoints/organization_events_timeseries.py index 485b7711f483f4..4e64cdcb70494f 100644 --- a/src/sentry/api/endpoints/organization_events_timeseries.py +++ b/src/sentry/api/endpoints/organization_events_timeseries.py @@ -366,12 +366,24 @@ def serialize_stats_data( ) -> StatsResponse: # We need the current timestamp for the Ingestion Delay incomplete reason now = datetime.now().timestamp() + stats_meta = StatsMeta( + dataset=DATASET_LABELS[dataset], + start=snuba_params.start_date.timestamp() * 1000, + end=snuba_params.end_date.timestamp() * 1000, + ) + if snuba_params.debug: + debug_info = None + if isinstance(result, SnubaTSResult) and "debug_info" in result.data["meta"]: + debug_info = result.data["meta"]["debug_info"] + elif isinstance(result, dict): + debug_info = {} + for key, keyed_result in result.items(): + if "debug_info" in keyed_result.data["meta"]: + debug_info[key] = keyed_result.data["meta"]["debug_info"] + # ignore typing here cause we don't want the openapi docs to include debug_info + stats_meta["debug_info"] = debug_info # type: ignore[typeddict-unknown-key] response = StatsResponse( - meta=StatsMeta( - dataset=DATASET_LABELS[dataset], - start=snuba_params.start_date.timestamp() * 1000, - end=snuba_params.end_date.timestamp() * 1000, - ), + meta=stats_meta, timeSeries=self.serialize_result(result, axes, rollup, now), ) return response diff --git a/src/sentry/snuba/rpc_dataset_common.py b/src/sentry/snuba/rpc_dataset_common.py index 37bcdc4dade70d..582f3f9bf0fe4f 100644 --- a/src/sentry/snuba/rpc_dataset_common.py +++ b/src/sentry/snuba/rpc_dataset_common.py @@ -392,7 +392,7 @@ def _run_table_query( table_request = cls.get_table_rpc_request(query) rpc_request = table_request.rpc_request try: - rpc_response = snuba_rpc.table_rpc([rpc_request])[0] + rpc_response = snuba_rpc.table_rpc([rpc_request], debug=debug)[0] except Exception as e: # add the rpc to the error so we can include it in the response if debug: @@ -428,7 +428,9 @@ def run_table_query( @classmethod @sentry_sdk.trace - def run_bulk_table_queries(cls, queries: list[TableQuery]) -> dict[str, EAPResponse]: + def run_bulk_table_queries( + cls, queries: list[TableQuery], debug: str | bool = False + ) -> dict[str, EAPResponse]: """Validate the bulk queries""" names: set[str] = set() for query in queries: diff --git a/tests/snuba/api/endpoints/test_organization_events.py b/tests/snuba/api/endpoints/test_organization_events.py index bf521f0b6342b0..d51b4590bc88ba 100644 --- a/tests/snuba/api/endpoints/test_organization_events.py +++ b/tests/snuba/api/endpoints/test_organization_events.py @@ -6021,7 +6021,7 @@ def test_debug_param(self) -> None: ) assert response.status_code == 200, response.content # Debug should be ignored without superuser - assert "query" not in response.data["meta"] + assert "debug_info" not in response.data["meta"] self.user = self.create_user("superuser@example.com", is_superuser=True) self.create_team(organization=self.organization, members=[self.user]) diff --git a/tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py b/tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py index 056afdb5ec04a1..fe87838eea7ce7 100644 --- a/tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py +++ b/tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py @@ -103,7 +103,6 @@ def test_count(self) -> None: ], ) self.store_spans(spans) - self.user = self.create_user("superuser@example.com", is_superuser=True) response = self._do_request( data={ @@ -113,7 +112,6 @@ def test_count(self) -> None: "yAxis": "count()", "project": self.project.id, "dataset": "spans", - "debug": "wmak", }, ) assert response.status_code == 200, response.content @@ -141,6 +139,46 @@ def test_count(self) -> None: "interval": 3_600_000, } + def test_debug_param(self) -> None: + self.user = self.create_user("user@example.com", is_superuser=False) + self.create_team(organization=self.organization, members=[self.user]) + self.login_as(user=self.user) + + response = self._do_request( + { + "start": self.start, + "end": self.end, + "interval": "1h", + "yAxis": "count()", + "project": self.project.id, + "dataset": "spans", + "debug": True, + }, + ) + assert response.status_code == 200, response.content + # Debug should be ignored without superuser + assert "debug_info" not in response.data["meta"] + + self.user = self.create_user("superuser@example.com", is_superuser=True) + self.create_team(organization=self.organization, members=[self.user]) + self.login_as(user=self.user) + + response = self._do_request( + { + "start": self.start, + "end": self.end, + "interval": "1h", + "yAxis": "count()", + "project": self.project.id, + "dataset": "spans", + "debug": True, + }, + ) + assert response.status_code == 200, response.content + assert "debug_info" in response.data["meta"] + # We should get the query back in the query key + assert "expressions" in response.data["meta"]["debug_info"]["query"] + def test_handle_nans_from_snuba(self) -> None: self.store_spans( [self.create_span({"description": "foo"}, start_ts=self.start)],