Skip to content

Commit 153fa0d

Browse files
committed
Merge branch 'master' into feat/span-first
2 parents fc8cd48 + 2d05f5d commit 153fa0d

3 files changed

Lines changed: 58 additions & 63 deletions

File tree

sentry_sdk/scope.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
has_tracing_enabled,
3232
has_span_streaming_enabled,
3333
is_ignored_span,
34-
make_sampling_decision,
34+
_make_sampling_decision,
35+
normalize_incoming_data,
3536
PropagationContext,
3637
)
3738
from sentry_sdk.traces import _DEFAULT_PARENT_SPAN, StreamedSpan, NoOpStreamedSpan
@@ -1252,7 +1253,7 @@ def start_streamed_span(
12521253
unsampled_reason="ignored",
12531254
)
12541255

1255-
sampled, sample_rate, sample_rand, outcome = make_sampling_decision(
1256+
sampled, sample_rate, sample_rand, outcome = _make_sampling_decision(
12561257
name,
12571258
attributes,
12581259
self,

sentry_sdk/traces.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -280,16 +280,6 @@ def __init__(
280280
self._start_timestamp = datetime.now(timezone.utc)
281281
self._timestamp: "Optional[datetime]" = None
282282

283-
try:
284-
# profiling depends on this value and requires that
285-
# it is measured in nanoseconds
286-
self._start_timestamp_monotonic_ns = nanosecond_time()
287-
except AttributeError:
288-
pass
289-
290-
self._start_timestamp = datetime.now(timezone.utc)
291-
self._timestamp: "Optional[datetime]" = None
292-
293283
try:
294284
# profiling depends on this value and requires that
295285
# it is measured in nanoseconds
@@ -393,7 +383,9 @@ def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None
393383
if isinstance(end_timestamp, datetime):
394384
self._timestamp = end_timestamp
395385
else:
396-
logger.debug("Failed to set end_timestamp. Using current time instead.")
386+
logger.debug(
387+
"[Tracing] Failed to set end_timestamp. Using current time instead."
388+
)
397389

398390
if self._timestamp is None:
399391
try:
@@ -438,7 +430,7 @@ def status(self, status: "Union[SpanStatus, str]") -> None:
438430

439431
if status not in {e.value for e in SpanStatus}:
440432
logger.debug(
441-
f'Unsupported span status {status}. Expected one of: "ok", "error"'
433+
f'[Tracing] Unsupported span status {status}. Expected one of: "ok", "error"'
442434
)
443435
return
444436

@@ -579,7 +571,10 @@ def _start_profile(self) -> None:
579571

580572

581573
class NoOpStreamedSpan(StreamedSpan):
582-
__slots__ = ("_unsampled_reason",)
574+
__slots__ = (
575+
"_finished",
576+
"_unsampled_reason",
577+
)
583578

584579
def __init__(
585580
self,
@@ -590,6 +585,7 @@ def __init__(
590585
self._unsampled_reason = unsampled_reason
591586

592587
self._segment = None # type: ignore[assignment]
588+
self._finished = False
593589

594590
self._start()
595591

@@ -621,25 +617,28 @@ def _start(self) -> None:
621617
self._previous_span_on_scope = old_span
622618

623619
def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None:
624-
client = sentry_sdk.get_client()
625-
if client and client.transport:
626-
logger.debug("Discarding span because sampled = False")
627-
client.transport.record_lost_event(
628-
reason=self._unsampled_reason or "sample_rate",
629-
data_category="span",
630-
quantity=1,
631-
)
632-
633-
if self._scope is None:
620+
if self._finished:
634621
return
635622

636-
if not hasattr(self, "_previous_span_on_scope"):
637-
return
623+
if self._unsampled_reason is not None:
624+
client = sentry_sdk.get_client()
625+
if client.is_active() and client.transport:
626+
logger.debug(
627+
f"[Tracing] Discarding span because sampled=False (reason: {self._unsampled_reason})"
628+
)
629+
client.transport.record_lost_event(
630+
reason=self._unsampled_reason,
631+
data_category="span",
632+
quantity=1,
633+
)
634+
635+
if self._scope and hasattr(self, "_previous_span_on_scope"):
636+
with capture_internal_exceptions():
637+
old_span = self._previous_span_on_scope
638+
del self._previous_span_on_scope
639+
self._scope.span = old_span
638640

639-
with capture_internal_exceptions():
640-
old_span = self._previous_span_on_scope
641-
del self._previous_span_on_scope
642-
self._scope.span = old_span
641+
self._finished = True
643642

644643
def end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None:
645644
self._end()

sentry_sdk/tracing_utils.py

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,21 +1490,19 @@ def add_sentry_baggage_to_headers(
14901490
)
14911491

14921492

1493-
def make_sampling_decision(
1493+
def _make_sampling_decision(
14941494
name: str,
14951495
attributes: "Optional[Attributes]",
14961496
scope: "sentry_sdk.Scope",
14971497
) -> "tuple[bool, Optional[float], Optional[float], Optional[str]]":
14981498
"""
14991499
Decide whether a span should be sampled.
15001500
1501-
Use traces_sampler if defined, otherwise traces_sample_rate.
1502-
15031501
Returns a tuple with:
1504-
- the sampling decision
1505-
- the effective sample rate
1506-
- the sample rand
1507-
- the reason for not sampling the span, if unsampled
1502+
1. the sampling decision
1503+
2. the effective sample rate
1504+
3. the sample rand
1505+
4. the reason for not sampling the span, if unsampled
15081506
"""
15091507
client = sentry_sdk.get_client()
15101508

@@ -1519,53 +1517,50 @@ def make_sampling_decision(
15191517
if sample_rand is None:
15201518
sample_rand = _generate_sample_rand(propagation_context.trace_id)
15211519

1522-
sampling_context = {
1523-
"name": name,
1524-
"trace_id": propagation_context.trace_id,
1525-
"parent_span_id": propagation_context.parent_span_id,
1526-
"parent_sampled": propagation_context.parent_sampled,
1527-
"attributes": attributes or {},
1528-
}
1529-
if propagation_context.custom_sampling_context:
1530-
sampling_context.update(propagation_context.custom_sampling_context)
1531-
15321520
# If there's a traces_sampler, use that; otherwise use traces_sample_rate
15331521
traces_sampler_defined = callable(client.options.get("traces_sampler"))
15341522
if traces_sampler_defined:
1523+
sampling_context = {
1524+
"name": name,
1525+
"trace_id": propagation_context.trace_id,
1526+
"parent_span_id": propagation_context.parent_span_id,
1527+
"parent_sampled": propagation_context.parent_sampled,
1528+
"attributes": dict(attributes) if attributes else {},
1529+
}
1530+
1531+
if propagation_context.custom_sampling_context:
1532+
sampling_context.update(propagation_context.custom_sampling_context)
1533+
15351534
sample_rate = client.options["traces_sampler"](sampling_context)
15361535
else:
1537-
if sampling_context["parent_sampled"] is not None:
1538-
sample_rate = sampling_context["parent_sampled"]
1536+
if propagation_context.parent_sampled is not None:
1537+
sample_rate = propagation_context.parent_sampled
15391538
else:
15401539
sample_rate = client.options["traces_sample_rate"]
15411540

15421541
# Validate whether the sample_rate we got is actually valid. Since
15431542
# traces_sampler is user-provided, it could return anything.
15441543
if not is_valid_sample_rate(sample_rate, source="Tracing"):
15451544
logger.warning(f"[Tracing] Discarding {name} because of invalid sample rate.")
1546-
return False, None, None, None
1545+
return False, None, None, "sample_rate"
15471546

15481547
sample_rate = float(sample_rate)
1549-
1550-
# Adjust sample rate if we're under backpressure
1551-
if client.monitor:
1552-
sample_rate /= 2**client.monitor.downsample_factor
1553-
1554-
outcome: "Optional[str]" = None
1555-
15561548
if not sample_rate:
15571549
if traces_sampler_defined:
15581550
reason = "traces_sampler returned 0 or False"
15591551
else:
15601552
reason = "traces_sample_rate is set to 0"
15611553

15621554
logger.debug(f"[Tracing] Discarding {name} because {reason}")
1563-
if client.monitor and client.monitor.downsample_factor > 0:
1564-
outcome = "backpressure"
1565-
else:
1566-
outcome = "sample_rate"
1555+
return False, 0.0, None, "sample_rate"
1556+
1557+
# Adjust sample rate if we're under backpressure
1558+
if client.monitor:
1559+
sample_rate /= 2**client.monitor.downsample_factor
15671560

1568-
return False, 0.0, None, outcome
1561+
if not sample_rate:
1562+
logger.debug(f"[Tracing] Discarding {name} because backpressure")
1563+
return False, 0.0, None, "backpressure"
15691564

15701565
sampled = sample_rand < sample_rate
15711566

0 commit comments

Comments
 (0)