Skip to content

Commit 9b46459

Browse files
committed
Merge branch 'potel-base' into potel-base-run-all-tests
2 parents c9ddc34 + 78cea8b commit 9b46459

File tree

8 files changed

+62
-104
lines changed

8 files changed

+62
-104
lines changed

sentry_sdk/integrations/opentelemetry/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import datetime, timezone
44

55
from urllib3.util import parse_url as urlparse
6-
from urllib.parse import quote
6+
from urllib.parse import quote, unquote
77
from opentelemetry.trace import (
88
Span as AbstractSpan,
99
SpanKind,
@@ -354,7 +354,7 @@ def dsc_from_trace_state(trace_state):
354354
for k, v in trace_state.items():
355355
if Baggage.SENTRY_PREFIX_REGEX.match(k):
356356
key = re.sub(Baggage.SENTRY_PREFIX_REGEX, "", k)
357-
dsc[key] = v
357+
dsc[unquote(key)] = unquote(v)
358358
return dsc
359359

360360

sentry_sdk/scope.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,10 @@ def generate_propagation_context(self, incoming_data=None):
480480
def get_dynamic_sampling_context(self):
481481
# type: () -> Optional[Dict[str, str]]
482482
"""
483-
Returns the Dynamic Sampling Context from the Propagation Context.
483+
Returns the Dynamic Sampling Context from the baggage or populates one.
484484
"""
485-
return (
486-
self._propagation_context.dynamic_sampling_context
487-
if self._propagation_context
488-
else None
489-
)
485+
baggage = self.get_baggage()
486+
return baggage.dynamic_sampling_context() if baggage else None
490487

491488
def get_traceparent(self, *args, **kwargs):
492489
# type: (Any, Any) -> Optional[str]

sentry_sdk/tracing.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,8 +1253,10 @@ def __init__(
12531253

12541254
# Prepopulate some attrs so that they're accessible in traces_sampler
12551255
attributes = attributes or {}
1256-
attributes[SentrySpanAttribute.OP] = op
1257-
attributes[SentrySpanAttribute.SOURCE] = source
1256+
if op is not None:
1257+
attributes[SentrySpanAttribute.OP] = op
1258+
if source is not None:
1259+
attributes[SentrySpanAttribute.SOURCE] = source
12581260
if sampled is not None:
12591261
attributes[SentrySpanAttribute.CUSTOM_SAMPLED] = sampled
12601262

@@ -1403,6 +1405,19 @@ def sampled(self):
14031405
# type: () -> Optional[bool]
14041406
return self._otel_span.get_span_context().trace_flags.sampled
14051407

1408+
@property
1409+
def sample_rate(self):
1410+
# type: () -> Optional[float]
1411+
from sentry_sdk.integrations.opentelemetry.consts import (
1412+
TRACESTATE_SAMPLE_RATE_KEY,
1413+
)
1414+
1415+
sample_rate = self._otel_span.get_span_context().trace_state.get(
1416+
TRACESTATE_SAMPLE_RATE_KEY
1417+
)
1418+
sample_rate = cast("Optional[str]", sample_rate)
1419+
return float(sample_rate) if sample_rate is not None else None
1420+
14061421
@property
14071422
def op(self):
14081423
# type: () -> Optional[str]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def get_file_text(file_name):
7171
"openfeature": ["openfeature-sdk>=0.7.1"],
7272
"opentelemetry": ["opentelemetry-distro>=0.35b0"],
7373
"opentelemetry-experimental": ["opentelemetry-distro"],
74-
"pure_eval": ["pure_eval", "executing", "asttokens"],
74+
"pure-eval": ["pure_eval", "executing", "asttokens"],
7575
"pymongo": ["pymongo>=3.1"],
7676
"pyspark": ["pyspark>=2.4.4"],
7777
"quart": ["quart>=0.16.1", "blinker>=1.1"],

tests/test_breadcrumbs.py

Lines changed: 13 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from unittest import mock
22

33
import sentry_sdk
4-
from sentry_sdk.consts import OP
54

65

76
def test_breadcrumbs(sentry_init, capture_events):
@@ -26,7 +25,7 @@ def test_breadcrumbs(sentry_init, capture_events):
2625
},
2726
}
2827

29-
with sentry_sdk.start_transaction(name="trx-breadcrumbs"):
28+
with sentry_sdk.start_span(name="trx-breadcrumbs"):
3029
sentry_sdk.add_breadcrumb(message="breadcrumb0", **add_breadcrumbs_kwargs)
3130

3231
with sentry_sdk.start_span(name="span1", op="function"):
@@ -37,41 +36,25 @@ def test_breadcrumbs(sentry_init, capture_events):
3736
message="breadcrumb2", **add_breadcrumbs_kwargs
3837
)
3938

40-
# Spans that create breadcrumbs automatically
41-
with sentry_sdk.start_span(name="span3", op=OP.DB_REDIS) as span3:
42-
span3.set_data("span3_data", "data on the redis span")
43-
span3.set_tag("span3_tag", "tag on the redis span")
44-
45-
with sentry_sdk.start_span(name="span4", op=OP.HTTP_CLIENT) as span4:
46-
span4.set_data("span4_data", "data on the http.client span")
47-
span4.set_tag("span4_tag", "tag on the http.client span")
48-
49-
with sentry_sdk.start_span(name="span5", op=OP.SUBPROCESS) as span5:
50-
span5.set_data("span5_data", "data on the subprocess span")
51-
span5.set_tag("span5_tag", "tag on the subprocess span")
52-
53-
with sentry_sdk.start_span(name="span6", op="function") as span6:
54-
# This data on the span is not added to custom breadcrumbs.
55-
# Data from the span is only added to automatic breadcrumbs shown above
56-
span6.set_data("span6_data", "data on span6")
57-
span6.set_tag("span6_tag", "tag on the span6")
39+
with sentry_sdk.start_span(name="span3", op="function"):
5840
sentry_sdk.add_breadcrumb(
59-
message="breadcrumb6", **add_breadcrumbs_kwargs
41+
message="breadcrumb3", **add_breadcrumbs_kwargs
6042
)
6143

6244
try:
6345
1 / 0
6446
except ZeroDivisionError as ex:
6547
sentry_sdk.capture_exception(ex)
6648

67-
(error,) = events
49+
assert len(events) == 2
50+
error = events[0]
6851

6952
breadcrumbs = error["breadcrumbs"]["values"]
7053

7154
for crumb in breadcrumbs:
7255
print(crumb)
7356

74-
assert len(breadcrumbs) == 7
57+
assert len(breadcrumbs) == 4
7558

7659
# Check for my custom breadcrumbs
7760
for i in range(0, 3):
@@ -88,53 +71,16 @@ def test_breadcrumbs(sentry_init, capture_events):
8871
}
8972
assert breadcrumbs[i]["timestamp"] == mock.ANY
9073

91-
# Check automatic redis breadcrumbs
92-
assert breadcrumbs[3]["message"] == "span3"
93-
assert breadcrumbs[3]["type"] == "redis"
94-
assert breadcrumbs[3]["category"] == "redis"
95-
assert "level" not in breadcrumbs[3]
96-
assert "origin" not in breadcrumbs[3]
74+
# Check for custom breadcrumbs on span3
75+
assert breadcrumbs[3]["message"] == "breadcrumb3"
76+
assert breadcrumbs[3]["type"] == "navigation"
77+
assert breadcrumbs[3]["category"] == "unit_tests.breadcrumbs"
78+
assert breadcrumbs[3]["level"] == "fatal"
79+
assert breadcrumbs[3]["origin"] == "unit-tests"
9780
assert breadcrumbs[3]["data"] == {
98-
"span3_tag": "tag on the redis span",
99-
}
100-
assert breadcrumbs[3]["timestamp"] == mock.ANY
101-
102-
# Check automatic http.client breadcrumbs
103-
assert "message" not in breadcrumbs[4]
104-
assert breadcrumbs[4]["type"] == "http"
105-
assert breadcrumbs[4]["category"] == "httplib"
106-
assert "level" not in breadcrumbs[4]
107-
assert "origin" not in breadcrumbs[4]
108-
assert breadcrumbs[4]["data"] == {
109-
"thread.id": mock.ANY,
110-
"thread.name": mock.ANY,
111-
"span4_data": "data on the http.client span",
112-
}
113-
assert breadcrumbs[4]["timestamp"] == mock.ANY
114-
115-
# Check automatic subprocess breadcrumbs
116-
assert breadcrumbs[5]["message"] == "span5"
117-
assert breadcrumbs[5]["type"] == "subprocess"
118-
assert breadcrumbs[5]["category"] == "subprocess"
119-
assert "level" not in breadcrumbs[5]
120-
assert "origin" not in breadcrumbs[5]
121-
assert breadcrumbs[5]["data"] == {
122-
"thread.id": mock.ANY,
123-
"thread.name": mock.ANY,
124-
"span5_data": "data on the subprocess span",
125-
}
126-
assert breadcrumbs[5]["timestamp"] == mock.ANY
127-
128-
# Check for custom breadcrumbs on span6
129-
assert breadcrumbs[6]["message"] == "breadcrumb6"
130-
assert breadcrumbs[6]["type"] == "navigation"
131-
assert breadcrumbs[6]["category"] == "unit_tests.breadcrumbs"
132-
assert breadcrumbs[6]["level"] == "fatal"
133-
assert breadcrumbs[6]["origin"] == "unit-tests"
134-
assert breadcrumbs[6]["data"] == {
13581
"string": "foobar",
13682
"number": 4.2,
13783
"array": [1, 2, 3],
13884
"dict": {"foo": "bar"},
13985
}
140-
assert breadcrumbs[6]["timestamp"] == mock.ANY
86+
assert breadcrumbs[3]["timestamp"] == mock.ANY

tests/test_dsc.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def test_dsc_head_of_trace(sentry_init, capture_envelopes):
2727
)
2828
envelopes = capture_envelopes()
2929

30-
# We start a new transaction
31-
with sentry_sdk.start_transaction(name="foo"):
30+
# We start a new root_span
31+
with sentry_sdk.start_span(name="foo"):
3232
pass
3333

3434
assert len(envelopes) == 1
@@ -95,10 +95,10 @@ def test_dsc_continuation_of_trace(sentry_init, capture_envelopes):
9595
"HTTP_BAGGAGE": baggage,
9696
}
9797

98-
# We continue the incoming trace and start a new transaction
99-
transaction = sentry_sdk.continue_trace(incoming_http_headers)
100-
with sentry_sdk.start_transaction(transaction, name="foo"):
101-
pass
98+
# We continue the incoming trace and start a new root span
99+
with sentry_sdk.continue_trace(incoming_http_headers):
100+
with sentry_sdk.start_span(name="foo"):
101+
pass
102102

103103
assert len(envelopes) == 1
104104

@@ -145,7 +145,7 @@ def test_dsc_issue(sentry_init, capture_envelopes):
145145
)
146146
envelopes = capture_envelopes()
147147

148-
# No transaction is started, just an error is captured
148+
# No root span is started, just an error is captured
149149
try:
150150
1 / 0
151151
except ZeroDivisionError as exp:
@@ -181,8 +181,8 @@ def test_dsc_issue(sentry_init, capture_envelopes):
181181

182182
def test_dsc_issue_with_tracing(sentry_init, capture_envelopes):
183183
"""
184-
Our service has tracing enabled and an error occurs in an transaction.
185-
Envelopes containing errors also have the same DSC than the transaction envelopes.
184+
Our service has tracing enabled and an error occurs in an root span.
185+
Envelopes containing errors also have the same DSC than the root span envelopes.
186186
"""
187187
sentry_init(
188188
dsn="https://[email protected]/12312012",
@@ -192,8 +192,8 @@ def test_dsc_issue_with_tracing(sentry_init, capture_envelopes):
192192
)
193193
envelopes = capture_envelopes()
194194

195-
# We start a new transaction and an error occurs
196-
with sentry_sdk.start_transaction(name="foo"):
195+
# We start a new root span and an error occurs
196+
with sentry_sdk.start_span(name="foo"):
197197
try:
198198
1 / 0
199199
except ZeroDivisionError as exp:
@@ -239,7 +239,7 @@ def test_dsc_issue_with_tracing(sentry_init, capture_envelopes):
239239
"traces_sample_rate",
240240
[
241241
0, # no traces will be started, but if incoming traces will be continued (by our instrumentations, not happening in this test)
242-
None, # no tracing at all. This service will never create transactions.
242+
None, # no tracing at all. This service will never create root spans.
243243
],
244244
)
245245
def test_dsc_issue_twp(sentry_init, capture_envelopes, traces_sample_rate):
@@ -278,14 +278,14 @@ def test_dsc_issue_twp(sentry_init, capture_envelopes, traces_sample_rate):
278278
}
279279

280280
# We continue the trace (meaning: saving the incoming trace information on the scope)
281-
# but in this test, we do not start a transaction.
282-
sentry_sdk.continue_trace(incoming_http_headers)
281+
# but in this test, we do not start a root span.
282+
with sentry_sdk.continue_trace(incoming_http_headers):
283283

284-
# No transaction is started, just an error is captured
285-
try:
286-
1 / 0
287-
except ZeroDivisionError as exp:
288-
sentry_sdk.capture_exception(exp)
284+
# No root span is started, just an error is captured
285+
try:
286+
1 / 0
287+
except ZeroDivisionError as exp:
288+
sentry_sdk.capture_exception(exp)
289289

290290
assert len(envelopes) == 1
291291

tests/test_monitor.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_monitor_unhealthy(sentry_init):
5555
assert monitor.downsample_factor == (i + 1 if i < 10 else 10)
5656

5757

58-
def test_transaction_uses_downsample_rate(
58+
def test_root_span_uses_downsample_rate(
5959
sentry_init, capture_envelopes, capture_record_lost_event_calls, monkeypatch
6060
):
6161
sentry_init(
@@ -78,16 +78,14 @@ def test_transaction_uses_downsample_rate(
7878
assert monitor.is_healthy() is False
7979
assert monitor.downsample_factor == 1
8080

81-
with sentry_sdk.start_transaction(name="foobar") as transaction:
81+
with sentry_sdk.start_span(name="foobar") as root_span:
8282
with sentry_sdk.start_span(name="foospan"):
8383
with sentry_sdk.start_span(name="foospan2"):
8484
with sentry_sdk.start_span(name="foospan3"):
8585
...
8686

87-
assert transaction.sampled is False
88-
assert (
89-
transaction.sample_rate == 0.5
90-
) # TODO: this fails until we put the sample_rate in the POTelSpan
87+
assert root_span.sampled is False
88+
assert root_span.sample_rate == 0.5
9189

9290
assert len(envelopes) == 0
9391

@@ -104,7 +102,7 @@ def test_transaction_uses_downsample_rate(
104102
"span",
105103
None,
106104
1,
107-
), # Only one span (the transaction itself) is counted, since we did not record any spans in the first place.
105+
), # Only one span (the root span itself) is counted, since we did not record any spans in the first place.
108106
]
109107
)
110108

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,8 @@ deps =
641641
spark-v3.1: pyspark~=3.1.0
642642
spark-v3.3: pyspark~=3.3.0
643643
spark-v3.5: pyspark~=3.5.0
644+
# TODO: update to ~=4.0.0 once stable is out
645+
spark-v4.0: pyspark==4.0.0.dev2
644646
spark-latest: pyspark
645647

646648
# Starlette

0 commit comments

Comments
 (0)