From e26a8023792ea18d47f3d6613067a1b0fa9e4595 Mon Sep 17 00:00:00 2001 From: William Mak Date: Thu, 20 Nov 2025 15:57:50 -0500 Subject: [PATCH] feat(events): Add logging to debug queries - Also add error logging to top events - This adds a log event on events queries --- src/sentry/snuba/rpc_dataset_common.py | 33 ++++++++-- ..._organization_events_stats_span_indexed.py | 62 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/sentry/snuba/rpc_dataset_common.py b/src/sentry/snuba/rpc_dataset_common.py index 08a67c6fcc358c..28d528f5b3d21d 100644 --- a/src/sentry/snuba/rpc_dataset_common.py +++ b/src/sentry/snuba/rpc_dataset_common.py @@ -108,6 +108,18 @@ def check_timeseries_has_data(timeseries: SnubaData, y_axes: list[str]): return False +def log_rpc_request(message: str, rpc_request): + rpc_debug_json = json.loads(MessageToJson(rpc_request)) + logger.info( + message, + extra={ + "rpc_query": rpc_debug_json, + "referrer": rpc_request.meta.referrer, + "trace_item_type": rpc_request.meta.trace_item_type, + }, + ) + + class RPCBase: """Utility Methods""" @@ -322,6 +334,8 @@ def _run_table_query( """Run the query""" table_request = cls.get_table_rpc_request(query) rpc_request = table_request.rpc_request + if debug: + log_rpc_request("Running a table query with debug on", rpc_request) try: rpc_response = snuba_rpc.table_rpc([rpc_request])[0] except Exception as e: @@ -531,6 +545,8 @@ def update_timestamps( def _run_timeseries_rpc( self, debug: bool, rpc_request: TimeSeriesRequest ) -> TimeSeriesResponse: + if debug: + log_rpc_request("Running a timeseries query with debug on", rpc_request) try: return snuba_rpc.timeseries_rpc([rpc_request])[0] except Exception as e: @@ -793,10 +809,19 @@ def run_top_events_timeseries_query( requests.append(other_request) """Run the query""" - timeseries_rpc_response = snuba_rpc.timeseries_rpc(requests) - rpc_response = timeseries_rpc_response[0] - if len(timeseries_rpc_response) > 1: - other_response = timeseries_rpc_response[1] + if params.debug: + for rpc_request in requests: + log_rpc_request("Running a top events query with debug on", rpc_request) + try: + timeseries_rpc_response = snuba_rpc.timeseries_rpc(requests) + rpc_response = timeseries_rpc_response[0] + if len(timeseries_rpc_response) > 1: + other_response = timeseries_rpc_response[1] + except Exception as e: + # add the rpc to the error so we can include it in the response + if params.debug: + setattr(e, "debug", MessageToJson(rpc_request)) + raise """Process the results""" map_result_key_to_timeseries = defaultdict(list) diff --git a/tests/snuba/api/endpoints/test_organization_events_stats_span_indexed.py b/tests/snuba/api/endpoints/test_organization_events_stats_span_indexed.py index cec0b200a0de6f..4c0e365be68edb 100644 --- a/tests/snuba/api/endpoints/test_organization_events_stats_span_indexed.py +++ b/tests/snuba/api/endpoints/test_organization_events_stats_span_indexed.py @@ -2442,6 +2442,68 @@ def test_debug_param(self) -> None: ] ) + def test_debug_with_top_events(self) -> None: + self.store_spans( + [ + self.create_span( + {"sentry_tags": {"transaction": "foo", "status": "success"}}, + start_ts=self.day_ago + timedelta(minutes=1), + duration=2000, + ), + self.create_span( + {"sentry_tags": {"transaction": "bar", "status": "success"}}, + start_ts=self.day_ago + timedelta(minutes=1), + duration=2000, + ), + ], + is_eap=True, + ) + + 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( + data={ + "start": self.day_ago, + "end": self.day_ago + timedelta(minutes=4), + "interval": "1m", + "query": "", + "yAxis": ["count()"], + "field": ["transaction"], + "project": self.project.id, + "dataset": "spans", + "topEvents": 2, + "debug": True, + }, + ) + + assert response.status_code == 200, response.content + + assert ( + "FUNCTION_COUNT" + == response.data["bar"]["meta"]["debug_info"]["query"]["expressions"][0]["aggregation"][ + "aggregate" + ] + ) + + response = self._do_request( + data={ + "start": self.day_ago, + "end": self.day_ago + timedelta(minutes=4), + "interval": "1m", + "query": "", + "yAxis": ["count()"], + "field": ["transaction"], + "project": self.project.id, + "dataset": "spans", + "topEvents": 2, + }, + ) + + assert response.status_code == 200, response.content + assert "debug_info" not in response.data["bar"]["meta"] + @patch("sentry.utils.snuba_rpc.timeseries_rpc") def test_debug_param_with_error(self, mock_query) -> None: self.user = self.create_user("superuser@example.com", is_superuser=True)