Skip to content

ref: Support outgoing trace propagation in span first (18)#5638

Merged
sentrivana merged 129 commits intomasterfrom
ivana/span-first-18-trace-propagation
Mar 16, 2026
Merged

ref: Support outgoing trace propagation in span first (18)#5638
sentrivana merged 129 commits intomasterfrom
ivana/span-first-18-trace-propagation

Conversation

@sentrivana
Copy link
Contributor

@sentrivana sentrivana commented Mar 11, 2026

Couple things going on in this PR. Bear with me, this is probably the most all over the place span first PR because the outgoing trace propagation changes make mypy complain about things elsewhere in the sdk.

1. Outgoing trace propagation

Support getting trace propagation information from the span with _get_traceparent, _get_baggage, _iter_headers, etc. These mirror the old Span class to make integrating StreamedSpans with the rest of the SDK easier (since they're used throughout), with one difference: they're explicitly private, while the corresponding Span methods were public. Added aliases to them so that we can use the private methods everywhere.

There is definite clean up potential here once we get rid of the old spans and we no longer have to make the streaming span interface work with the existing helper scope methods.

2. Addressing cascading mypy issues

Now that we're officially allowing StreamedSpans to be set on the scope, a LOT of type hints need updating all over the SDK. In many places, I've added explicit guards against functionality that doesn't exist in span first mode. This should prevent folks from using the wrong APIs in the wrong SDK mode (tracing vs. static) as well as make mypy happy.

@sentrivana sentrivana marked this pull request as ready for review March 12, 2026 13:15
@sentrivana sentrivana requested a review from a team as a code owner March 12, 2026 13:15
@sentrivana sentrivana marked this pull request as draft March 12, 2026 15:26
@sentrivana sentrivana marked this pull request as ready for review March 13, 2026 09:34
Add the `gen_ai.system` span attribute (set to `"anthropic"`) to the
Anthropic integration.

Other AI integrations (OpenAI, Langchain, Google GenAI, LiteLLM,
Pydantic AI) already set this attribute, but it was missing from the
Anthropic integration. The attribute is set in `_set_input_data()` which
is called for every span (streaming/non-streaming, sync/async).

Refs PY-2135
Closes #5657
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Early return skips _transaction_info source update
    • Replaced the NoOpStreamedSpan early return with a no-op branch so set_transaction_name(..., source=...) always reaches the scope-level _transaction_info["source"] update.

Create PR

Or push these changes by commenting:

@cursor push 6ca52a0405
Preview (6ca52a0405)
diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py
--- a/sentry_sdk/scope.py
+++ b/sentry_sdk/scope.py
@@ -842,7 +842,7 @@
         self._transaction = name
         if self._span:
             if isinstance(self._span, NoOpStreamedSpan):
-                return
+                pass
 
             elif isinstance(self._span, StreamedSpan):
                 self._span._segment.name = name

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

elif isinstance(span, StreamedSpan):
span.status = SpanStatus.ERROR
if span._segment is not None:
span._segment.status = SpanStatus.ERROR
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_span_errored crashes on NoOpStreamedSpan accessing unset _segment

High Severity

When set_span_errored is called and the current span is a NoOpStreamedSpan, the isinstance(span, StreamedSpan) check passes (since NoOpStreamedSpan inherits from StreamedSpan), but accessing span._segment on the next line raises AttributeError. NoOpStreamedSpan.__init__ never assigns _segment because it doesn't call super().__init__(). This crashes whenever an error occurs while an unsampled or ignored span is active in span streaming mode.

Fix in Cursor Fix in Web

@sentrivana sentrivana enabled auto-merge (squash) March 16, 2026 07:20

if not client.is_active():
return Baggage(sentry_items)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The populate_from_segment function will crash with a TypeError when called on a child span because segment._sample_rand can be None but is formatted as a float.
Severity: HIGH

Suggested Fix

In populate_from_segment, add a check to ensure segment._sample_rand is not None before attempting to format it and add it to the sentry_items dictionary.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: sentry_sdk/tracing_utils.py#L781

Potential issue: The function `populate_from_segment` attempts to format
`segment._sample_rand` as a float. However, for child spans created via
`scope.start_streamed_span`, the `_sample_rand` attribute is not initialized and remains
`None`. This results in a `TypeError` when any function that relies on baggage
information, such as `scope.get_baggage()` or `scope.iter_trace_propagation_headers()`,
is called on a child span. This will cause a runtime crash during normal trace
propagation for outgoing requests involving child spans.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.



BAGGAGE_HEADER_NAME = "baggage"
SENTRY_TRACE_HEADER_NAME = "sentry-trace"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate header name constants across traces.py and tracing.py

Low Severity

BAGGAGE_HEADER_NAME and SENTRY_TRACE_HEADER_NAME are now defined identically in both traces.py and tracing.py. These duplicate definitions can drift out of sync and add maintenance burden. One module could import from the other, or they could be extracted to a shared location.

Fix in Cursor Fix in Web

@sentrivana sentrivana merged commit 0c4a75d into master Mar 16, 2026
158 checks passed
@sentrivana sentrivana deleted the ivana/span-first-18-trace-propagation branch March 16, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants