Skip to content

Commit e39424c

Browse files
authored
feat(clickhouse_driver): Respect data_collection.database_query_data option (#6938)
The ClickHouse driver integration now respects the experimental `data_collection.database_query_data` option when deciding whether to attach `db.params` and `db.result` to spans and breadcrumbs. When the option is set, it takes precedence over `send_default_pii`: `database_query_data: True` attaches query params and results even without PII enabled, and `database_query_data: False` suppresses them even when `send_default_pii=True`. When the option is not set, behavior is unchanged and falls back to the existing `send_default_pii` check. Refs PY-2587 Refs #6747
1 parent 91ec64b commit e39424c

2 files changed

Lines changed: 541 additions & 6 deletions

File tree

sentry_sdk/integrations/clickhouse_driver.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from sentry_sdk.traces import StreamedSpan
99
from sentry_sdk.tracing import Span
1010
from sentry_sdk.tracing_utils import has_span_streaming_enabled
11-
from sentry_sdk.utils import capture_internal_exceptions
11+
from sentry_sdk.utils import capture_internal_exceptions, has_data_collection_enabled
1212

1313
# Hack to get new Python features working in older versions
1414
# without introducing a hard dependency on `typing_extensions`
@@ -107,8 +107,12 @@ def _inner(*args: "P.args", **kwargs: "P.kwargs") -> "T":
107107
if query_id:
108108
span.set_data("db.query_id", query_id)
109109

110-
if params and should_send_default_pii():
111-
span.set_data("db.params", params)
110+
if params:
111+
if has_data_collection_enabled(client.options):
112+
if client.options["data_collection"]["database_query_data"]:
113+
span.set_data("db.params", params)
114+
elif should_send_default_pii():
115+
span.set_data("db.params", params)
112116

113117
connection._sentry_span = span # type: ignore[attr-defined]
114118

@@ -135,8 +139,13 @@ def _inner_end(*args: "P.args", **kwargs: "P.kwargs") -> "T":
135139
if isinstance(span, StreamedSpan):
136140
span.end()
137141
else:
138-
if res is not None and should_send_default_pii():
139-
span.set_data("db.result", res)
142+
if res is not None:
143+
client_options = sentry_sdk.get_client().options
144+
if has_data_collection_enabled(client_options):
145+
if client_options["data_collection"]["database_query_data"]:
146+
span.set_data("db.result", res)
147+
elif should_send_default_pii():
148+
span.set_data("db.result", res)
140149

141150
with capture_internal_exceptions():
142151
span.scope.add_breadcrumb(
@@ -167,7 +176,29 @@ def _inner_send_data( # type: ignore[no-untyped-def] # clickhouse-driver does n
167176
if span is not None:
168177
_set_db_data(span, self.connection)
169178

170-
if should_send_default_pii():
179+
client_options = sentry_sdk.get_client().options
180+
if has_data_collection_enabled(client_options):
181+
if client_options["data_collection"]["database_query_data"]:
182+
db_params = span._data.get("db.params", [])
183+
if isinstance(data, (list, tuple)):
184+
db_params.extend(data)
185+
186+
else: # data is a generic iterator
187+
orig_data = data
188+
189+
# Wrap the generator to add items to db.params as they are yielded.
190+
# This allows us to send the params to Sentry without needing to allocate
191+
# memory for the entire generator at once.
192+
def wrapped_generator() -> "Iterator[Any]":
193+
for item in orig_data:
194+
db_params.append(item)
195+
yield item
196+
197+
# Replace the original iterator with the wrapped one.
198+
data = wrapped_generator()
199+
200+
span.set_data("db.params", db_params)
201+
elif should_send_default_pii():
171202
db_params = span._data.get("db.params", [])
172203

173204
if isinstance(data, (list, tuple)):

0 commit comments

Comments
 (0)