Skip to content

Commit a67125a

Browse files
authored
Fix clickhouse-driver integration spans (#3638)
1 parent 56f2113 commit a67125a

File tree

4 files changed

+149
-68
lines changed

4 files changed

+149
-68
lines changed

MIGRATION_GUIDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
1818
- A `Profile` object does not have a `.hub` property anymore.
1919
- `sentry_sdk.continue_trace` no longer returns a `Transaction` and is now a context manager.
2020
- Redis integration: In Redis pipeline spans there is no `span["data"]["redis.commands"]` that contains a dict `{"count": 3, "first_ten": ["cmd1", "cmd2", ...]}` but instead `span["data"]["redis.commands.count"]` (containing `3`) and `span["data"]["redis.commands.first_ten"]` (containing `["cmd1", "cmd2", ...]`).
21+
- clickhouse-driver integration: The query is now available under the `db.query.text` span attribute (only if `send_default_pii` is `True`).
2122

2223
### Removed
2324

sentry_sdk/integrations/clickhouse_driver.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ def _inner(*args: P.args, **kwargs: P.kwargs) -> T:
9191

9292
_set_db_data(span, connection)
9393

94-
span.set_data("query", query)
94+
if should_send_default_pii():
95+
span.set_attribute("db.query.text", query)
9596

9697
if query_id:
97-
span.set_data("db.query_id", query_id)
98+
span.set_attribute("db.query_id", query_id)
9899

99100
if params and should_send_default_pii():
100-
span.set_data("db.params", params)
101+
connection._sentry_db_params = params
102+
span.set_attribute("db.params", str(params))
101103

102104
# run the original code
103105
ret = f(*args, **kwargs)
@@ -115,12 +117,26 @@ def _inner_end(*args: P.args, **kwargs: P.kwargs) -> T:
115117

116118
if span is not None:
117119
if res is not None and should_send_default_pii():
118-
span.set_data("db.result", res)
120+
span.set_attribute("db.result", str(res))
119121

120122
with capture_internal_exceptions():
121-
span.scope.add_breadcrumb(
122-
message=span._data.pop("query"), category="query", data=span._data
123-
)
123+
query = span.get_attribute("db.query.text")
124+
if query:
125+
data = {}
126+
for attr in (
127+
"db.params",
128+
"db.result",
129+
SPANDATA.DB_SYSTEM,
130+
SPANDATA.DB_USER,
131+
SPANDATA.SERVER_ADDRESS,
132+
SPANDATA.SERVER_PORT,
133+
):
134+
if span.get_attribute(attr):
135+
data[attr] = span.get_attribute(attr)
136+
137+
sentry_sdk.add_breadcrumb(
138+
message=query, category="query", data=data
139+
)
124140

125141
span.finish()
126142

@@ -139,9 +155,15 @@ def _inner_send_data(*args: P.args, **kwargs: P.kwargs) -> T:
139155
_set_db_data(span, instance.connection)
140156

141157
if should_send_default_pii():
142-
db_params = span._data.get("db.params", [])
158+
db_params = (
159+
getattr(instance.connection, "_sentry_db_params", None) or []
160+
)
143161
db_params.extend(data)
144-
span.set_data("db.params", db_params)
162+
span.set_attribute("db.params", str(db_params))
163+
try:
164+
del instance.connection._sentry_db_params
165+
except AttributeError:
166+
pass
145167

146168
return f(*args, **kwargs)
147169

@@ -151,8 +173,8 @@ def _inner_send_data(*args: P.args, **kwargs: P.kwargs) -> T:
151173
def _set_db_data(
152174
span: Span, connection: clickhouse_driver.connection.Connection
153175
) -> None:
154-
span.set_data(SPANDATA.DB_SYSTEM, "clickhouse")
155-
span.set_data(SPANDATA.SERVER_ADDRESS, connection.host)
156-
span.set_data(SPANDATA.SERVER_PORT, connection.port)
157-
span.set_data(SPANDATA.DB_NAME, connection.database)
158-
span.set_data(SPANDATA.DB_USER, connection.user)
176+
span.set_attribute(SPANDATA.DB_SYSTEM, "clickhouse")
177+
span.set_attribute(SPANDATA.SERVER_ADDRESS, connection.host)
178+
span.set_attribute(SPANDATA.SERVER_PORT, connection.port)
179+
span.set_attribute(SPANDATA.DB_NAME, connection.database)
180+
span.set_attribute(SPANDATA.DB_USER, connection.user)

sentry_sdk/tracing.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,18 +1279,12 @@ def __exit__(self, ty, value, tb):
12791279
self.finish()
12801280
context.detach(self._ctx_token)
12811281

1282-
def _get_attribute(self, name):
1283-
# type: (str) -> Optional[Any]
1284-
if not isinstance(self._otel_span, ReadableSpan):
1285-
return None
1286-
return self._otel_span.attributes.get(name)
1287-
12881282
@property
12891283
def description(self):
12901284
# type: () -> Optional[str]
12911285
from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute
12921286

1293-
return self._get_attribute(SentrySpanAttribute.DESCRIPTION)
1287+
return self.get_attribute(SentrySpanAttribute.DESCRIPTION)
12941288

12951289
@description.setter
12961290
def description(self, value):
@@ -1305,7 +1299,7 @@ def origin(self):
13051299
# type: () -> Optional[str]
13061300
from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute
13071301

1308-
return self._get_attribute(SentrySpanAttribute.ORIGIN)
1302+
return self.get_attribute(SentrySpanAttribute.ORIGIN)
13091303

13101304
@origin.setter
13111305
def origin(self, value):
@@ -1378,7 +1372,7 @@ def op(self):
13781372
# type: () -> Optional[str]
13791373
from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute
13801374

1381-
return self._get_attribute(SentrySpanAttribute.OP)
1375+
return self.get_attribute(SentrySpanAttribute.OP)
13821376

13831377
@op.setter
13841378
def op(self, value):
@@ -1393,7 +1387,7 @@ def name(self):
13931387
# type: () -> Optional[str]
13941388
from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute
13951389

1396-
return self._get_attribute(SentrySpanAttribute.NAME)
1390+
return self.get_attribute(SentrySpanAttribute.NAME)
13971391

13981392
@name.setter
13991393
def name(self, value):
@@ -1509,6 +1503,12 @@ def set_data(self, key, value):
15091503
# TODO-neel-potel we cannot add dicts here
15101504
self.set_attribute(key, value)
15111505

1506+
def get_attribute(self, name):
1507+
# type: (str) -> Optional[Any]
1508+
if not isinstance(self._otel_span, ReadableSpan):
1509+
return None
1510+
return self._otel_span.attributes.get(name)
1511+
15121512
def set_attribute(self, key, value):
15131513
# type: (str, Any) -> None
15141514
self._otel_span.set_attribute(key, value)

0 commit comments

Comments
 (0)