Skip to content

Commit f7a6c1f

Browse files
committed
Fix rust tracing
1 parent 4c07934 commit f7a6c1f

File tree

3 files changed

+55
-70
lines changed

3 files changed

+55
-70
lines changed

sentry_sdk/integrations/rust_tracing.py

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@
3737
import sentry_sdk
3838
from sentry_sdk.integrations import Integration
3939
from sentry_sdk.scope import should_send_default_pii
40-
from sentry_sdk.tracing import Span as SentrySpan
40+
from sentry_sdk.tracing import POTelSpan as SentrySpan
4141
from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE
4242

43-
TraceState = Optional[Tuple[Optional[SentrySpan], SentrySpan]]
44-
4543

4644
class RustTracingLevel(Enum):
4745
Trace: str = "TRACE"
@@ -171,7 +169,7 @@ def _include_tracing_fields(self) -> bool:
171169
else self.include_tracing_fields
172170
)
173171

174-
def on_event(self, event: str, _span_state: TraceState) -> None:
172+
def on_event(self, event: str, _span_state: Optional[SentrySpan]) -> None:
175173
deserialized_event = json.loads(event)
176174
metadata = deserialized_event.get("metadata", {})
177175

@@ -185,7 +183,7 @@ def on_event(self, event: str, _span_state: TraceState) -> None:
185183
elif event_type == EventTypeMapping.Event:
186184
process_event(deserialized_event)
187185

188-
def on_new_span(self, attrs: str, span_id: str) -> TraceState:
186+
def on_new_span(self, attrs: str, span_id: str) -> Optional[SentrySpan]:
189187
attrs = json.loads(attrs)
190188
metadata = attrs.get("metadata", {})
191189

@@ -205,48 +203,31 @@ def on_new_span(self, attrs: str, span_id: str) -> TraceState:
205203
else:
206204
sentry_span_name = "<unknown>"
207205

208-
kwargs = {
209-
"op": "function",
210-
"name": sentry_span_name,
211-
"origin": self.origin,
212-
}
213-
214-
scope = sentry_sdk.get_current_scope()
215-
parent_sentry_span = scope.span
216-
if parent_sentry_span:
217-
sentry_span = parent_sentry_span.start_child(**kwargs)
218-
else:
219-
sentry_span = scope.start_span(**kwargs)
206+
span = sentry_sdk.start_span(op="function", name=sentry_span_name, origin=self.origin, only_if_parent=True)
207+
span.__enter__()
220208

221209
fields = metadata.get("fields", [])
222210
for field in fields:
223211
if self._include_tracing_fields():
224-
sentry_span.set_data(field, attrs.get(field))
212+
span.set_data(field, attrs.get(field))
225213
else:
226-
sentry_span.set_data(field, SENSITIVE_DATA_SUBSTITUTE)
227-
228-
scope.span = sentry_span
229-
return (parent_sentry_span, sentry_span)
214+
span.set_data(field, SENSITIVE_DATA_SUBSTITUTE)
230215

231-
def on_close(self, span_id: str, span_state: TraceState) -> None:
232-
if span_state is None:
233-
return
216+
return span
234217

235-
parent_sentry_span, sentry_span = span_state
236-
sentry_span.finish()
237-
sentry_sdk.get_current_scope().span = parent_sentry_span
218+
def on_close(self, span_id: str, span: Optional[SentrySpan]) -> None:
219+
if span is not None:
220+
span.__exit__(None, None, None)
238221

239-
def on_record(self, span_id: str, values: str, span_state: TraceState) -> None:
240-
if span_state is None:
241-
return
242-
_parent_sentry_span, sentry_span = span_state
243222

244-
deserialized_values = json.loads(values)
245-
for key, value in deserialized_values.items():
246-
if self._include_tracing_fields():
247-
sentry_span.set_data(key, value)
248-
else:
249-
sentry_span.set_data(key, SENSITIVE_DATA_SUBSTITUTE)
223+
def on_record(self, span_id: str, values: str, span: Optional[SentrySpan]) -> None:
224+
if span is not None:
225+
deserialized_values = json.loads(values)
226+
for key, value in deserialized_values.items():
227+
if self._include_tracing_fields():
228+
span.set_data(key, value)
229+
else:
230+
span.set_data(key, SENSITIVE_DATA_SUBSTITUTE)
250231

251232

252233
class RustTracingIntegration(Integration):

sentry_sdk/tracing.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import uuid
23
import random
34
import time
@@ -1631,8 +1632,13 @@ def finish(self, end_timestamp=None):
16311632

16321633
def to_json(self):
16331634
# type: () -> dict[str, Any]
1634-
# TODO-neel-potel for sampling context
1635-
pass
1635+
"""
1636+
Only meant for testing. Not used internally anymore.
1637+
"""
1638+
if not isinstance(self._otel_span, ReadableSpan):
1639+
return {}
1640+
return json.loads(self._otel_span.to_json())
1641+
16361642

16371643
def get_trace_context(self):
16381644
# type: () -> dict[str, Any]

tests/integrations/rust_tracing/test_rust_tracing.py

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
RustTracingLevel,
1212
EventTypeMapping,
1313
)
14-
from sentry_sdk import start_transaction, capture_message
14+
from sentry_sdk import start_span, capture_message
15+
from tests.conftest import ApproxDict
1516

1617

1718
def _test_event_type_mapping(metadata: Dict[str, object]) -> EventTypeMapping:
@@ -74,11 +75,11 @@ def test_on_new_span_on_close(sentry_init, capture_events):
7475
sentry_init(integrations=[integration], traces_sample_rate=1.0)
7576

7677
events = capture_events()
77-
with start_transaction():
78+
with start_span():
7879
rust_tracing.new_span(RustTracingLevel.Info, 3)
7980

8081
sentry_first_rust_span = sentry_sdk.get_current_span()
81-
_, rust_first_rust_span = rust_tracing.spans[3]
82+
rust_first_rust_span = rust_tracing.spans[3]
8283

8384
assert sentry_first_rust_span == rust_first_rust_span
8485

@@ -102,7 +103,7 @@ def test_on_new_span_on_close(sentry_init, capture_events):
102103
data = span["data"]
103104
assert data["use_memoized"]
104105
assert data["index"] == 10
105-
assert data["version"] is None
106+
assert "version" not in data
106107

107108

108109
def test_nested_on_new_span_on_close(sentry_init, capture_events):
@@ -115,23 +116,20 @@ def test_nested_on_new_span_on_close(sentry_init, capture_events):
115116
sentry_init(integrations=[integration], traces_sample_rate=1.0)
116117

117118
events = capture_events()
118-
with start_transaction():
119+
with start_span():
119120
original_sentry_span = sentry_sdk.get_current_span()
120121

121122
rust_tracing.new_span(RustTracingLevel.Info, 3, index_arg=10)
122123
sentry_first_rust_span = sentry_sdk.get_current_span()
123-
_, rust_first_rust_span = rust_tracing.spans[3]
124+
rust_first_rust_span = rust_tracing.spans[3]
124125

125126
# Use a different `index_arg` value for the inner span to help
126127
# distinguish the two at the end of the test
127128
rust_tracing.new_span(RustTracingLevel.Info, 5, index_arg=9)
128129
sentry_second_rust_span = sentry_sdk.get_current_span()
129-
rust_parent_span, rust_second_rust_span = rust_tracing.spans[5]
130+
rust_second_rust_span = rust_tracing.spans[5]
130131

131132
assert rust_second_rust_span == sentry_second_rust_span
132-
assert rust_parent_span == sentry_first_rust_span
133-
assert rust_parent_span == rust_first_rust_span
134-
assert rust_parent_span != rust_second_rust_span
135133

136134
rust_tracing.close_span(5)
137135

@@ -171,12 +169,12 @@ def test_nested_on_new_span_on_close(sentry_init, capture_events):
171169
first_span_data = first_span["data"]
172170
assert first_span_data["use_memoized"]
173171
assert first_span_data["index"] == 10
174-
assert first_span_data["version"] is None
172+
assert "version" not in first_span_data
175173

176174
second_span_data = second_span["data"]
177175
assert second_span_data["use_memoized"]
178176
assert second_span_data["index"] == 9
179-
assert second_span_data["version"] is None
177+
assert "version" not in second_span_data
180178

181179

182180
def test_on_new_span_without_transaction(sentry_init):
@@ -207,7 +205,7 @@ def test_on_event_exception(sentry_init, capture_events):
207205
events = capture_events()
208206
sentry_sdk.get_isolation_scope().clear_breadcrumbs()
209207

210-
with start_transaction():
208+
with start_span():
211209
rust_tracing.new_span(RustTracingLevel.Info, 3)
212210

213211
# Mapped to Exception
@@ -243,7 +241,7 @@ def test_on_event_breadcrumb(sentry_init, capture_events):
243241
events = capture_events()
244242
sentry_sdk.get_isolation_scope().clear_breadcrumbs()
245243

246-
with start_transaction():
244+
with start_span():
247245
rust_tracing.new_span(RustTracingLevel.Info, 3)
248246

249247
# Mapped to Breadcrumb
@@ -274,7 +272,7 @@ def test_on_event_event(sentry_init, capture_events):
274272
events = capture_events()
275273
sentry_sdk.get_isolation_scope().clear_breadcrumbs()
276274

277-
with start_transaction():
275+
with start_span():
278276
rust_tracing.new_span(RustTracingLevel.Info, 3)
279277

280278
# Mapped to Event
@@ -311,7 +309,7 @@ def test_on_event_ignored(sentry_init, capture_events):
311309
events = capture_events()
312310
sentry_sdk.get_isolation_scope().clear_breadcrumbs()
313311

314-
with start_transaction():
312+
with start_span():
315313
rust_tracing.new_span(RustTracingLevel.Info, 3)
316314

317315
# Ignored
@@ -344,7 +342,7 @@ def span_filter(metadata: Dict[str, object]) -> bool:
344342
sentry_init(integrations=[integration], traces_sample_rate=1.0)
345343

346344
events = capture_events()
347-
with start_transaction():
345+
with start_span():
348346
original_sentry_span = sentry_sdk.get_current_span()
349347

350348
# Span is not ignored
@@ -377,16 +375,16 @@ def test_record(sentry_init):
377375
)
378376
sentry_init(integrations=[integration], traces_sample_rate=1.0)
379377

380-
with start_transaction():
378+
with start_span():
381379
rust_tracing.new_span(RustTracingLevel.Info, 3)
382380

383381
span_before_record = sentry_sdk.get_current_span().to_json()
384-
assert span_before_record["data"]["version"] is None
382+
assert "version" not in span_before_record["attributes"]
385383

386384
rust_tracing.record(3)
387385

388386
span_after_record = sentry_sdk.get_current_span().to_json()
389-
assert span_after_record["data"]["version"] == "memoized"
387+
assert span_after_record["attributes"]["version"] == "memoized"
390388

391389

392390
def test_record_in_ignored_span(sentry_init):
@@ -403,18 +401,18 @@ def span_filter(metadata: Dict[str, object]) -> bool:
403401
)
404402
sentry_init(integrations=[integration], traces_sample_rate=1.0)
405403

406-
with start_transaction():
404+
with start_span():
407405
rust_tracing.new_span(RustTracingLevel.Info, 3)
408406

409407
span_before_record = sentry_sdk.get_current_span().to_json()
410-
assert span_before_record["data"]["version"] is None
408+
assert "version" not in span_before_record["attributes"]
411409

412410
rust_tracing.new_span(RustTracingLevel.Trace, 5)
413411
rust_tracing.record(5)
414412

415413
# `on_record()` should not do anything to the current Sentry span if the associated Rust span was ignored
416414
span_after_record = sentry_sdk.get_current_span().to_json()
417-
assert span_after_record["data"]["version"] is None
415+
assert "version" not in span_after_record["attributes"]
418416

419417

420418
@pytest.mark.parametrize(
@@ -443,33 +441,33 @@ def test_include_tracing_fields(
443441
traces_sample_rate=1.0,
444442
send_default_pii=send_default_pii,
445443
)
446-
with start_transaction():
444+
with start_span():
447445
rust_tracing.new_span(RustTracingLevel.Info, 3)
448446

449447
span_before_record = sentry_sdk.get_current_span().to_json()
450448
if tracing_fields_expected:
451-
assert span_before_record["data"]["version"] is None
449+
assert "version" not in span_before_record["attributes"]
452450
else:
453-
assert span_before_record["data"]["version"] == "[Filtered]"
451+
assert span_before_record["attributes"]["version"] == "[Filtered]"
454452

455453
rust_tracing.record(3)
456454

457455
span_after_record = sentry_sdk.get_current_span().to_json()
458456

459457
if tracing_fields_expected:
460-
assert span_after_record["data"] == {
458+
assert span_after_record["attributes"] == ApproxDict({
461459
"thread.id": mock.ANY,
462460
"thread.name": mock.ANY,
463461
"use_memoized": True,
464462
"version": "memoized",
465463
"index": 10,
466-
}
464+
})
467465

468466
else:
469-
assert span_after_record["data"] == {
467+
assert span_after_record["attributes"] == ApproxDict({
470468
"thread.id": mock.ANY,
471469
"thread.name": mock.ANY,
472470
"use_memoized": "[Filtered]",
473471
"version": "[Filtered]",
474472
"index": "[Filtered]",
475-
}
473+
})

0 commit comments

Comments
 (0)