docs(python): Draft New Spans and Migration Guide pages#18456
docs(python): Draft New Spans and Migration Guide pages#18456inventarSarah wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
ericapisani
left a comment
There was a problem hiding this comment.
Looking good so far!
I have questions about the use of the term "service span" vs "segment span" as the latter is what we've been using thus far.
Additionally, should we keep the term "service", referring to these spans as "service entry points" could be a point of confusion because I can see this being mixed up with entry points for a request in the context of a web framework, even though these could be placed/started anywhere (which one of the examples in the documentation show).
| --- | ||
|
|
||
| By default, the Sentry Python SDK collects all spans in memory and sends them to Sentry as a single transaction once the root span ends. This is called transaction mode. | ||
| Stream mode changes this by sending spans to Sentry in batches as they finish. Service spans, which represent a service's entry point, replace transactions as the main grouping for each service. |
There was a problem hiding this comment.
Service spans, which represent a service's entry point, replace transactions as the main grouping for each service.
This is my first time seeing the term "service" used for what we've been calling "segments". I'm not sure if this is a term that we plan on using for user-facing comms going forward, but wanted to highlight the discrepency.
I'm also not sure that the main grouping of spans is always a service's entry point. If we refer to transactions in the same way, then leave as-is, but would want to double check with @sentrivana or @alexander-alderman-webb
There was a problem hiding this comment.
I thought I brought this up in some sync (😇), but service span is the canonical, user facing term of these kind of spans.
| <Expandable title="Why use stream mode?"> | ||
|
|
||
| - **No 1,000-span limit.** In transaction mode, transactions are capped at 1,000 spans. Stream mode has no upper limit since spans are sent in batches. | ||
| - **Lower memory usage.** Spans are flushed periodically and don't need to be held in memory until the root span ends. This is especially useful for long-running processes like queue consumers or cron jobs. |
There was a problem hiding this comment.
I think it could be worth calling out the benefits for AI monitoring since generative AI spans emitted by our SDKs are one of the main beneficiaries of this change
| To start a service span (the equivalent of a transaction), set `parent_span=None`: | ||
|
|
||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| ```python | ||
| import sentry_sdk | ||
|
|
||
| with sentry_sdk.traces.start_span(name="task-name", parent_span=None) as span: | ||
| do_work() | ||
| ``` |
There was a problem hiding this comment.
This example is why I think referring to what are currently called "segment spans" as "service entry points" above will be a bit confusing since this code snippet could be placed anywhere, not just at an "entry point" in a web framework/service.
| </SplitSection> | ||
| </SplitLayout> | ||
|
|
||
| Find more examples in our <PlatformLink to="/tracing/span-metrics/">Sending Span Metrics</PlatformLink> documentation. |
There was a problem hiding this comment.
I wonder if it's worth mentioning our Sentry Convention/Attribute docs to users here.
These are attributes that we may set within the SDK that users will want to be aware of so they don't accidentally overwrite them when setting their own attributes (unless that's what they want 😄 )
| + service_span = span._segment | ||
| ``` | ||
|
|
||
| `_segment` returns the service span of the current trace (the equivalent of what used to be the transaction). It is a private API — prefer restructuring the code to avoid needing the service span where possible. |
There was a problem hiding this comment.
This part is confusing. A private API is returning service span data? Or will this data become unavailable. Let's reword this to make it clearer, and remove reference to private APIs if we can, since customers won't be able to use it.
| # Getting the service span (formerly the transaction) | ||
| - scope = sentry_sdk.get_current_scope() | ||
| - transaction = scope.transaction | ||
| + service_span = sentry_sdk.traces.get_current_span()._segment |
There was a problem hiding this comment.
There should be no references to underscored things from our SDK (single leading underscore).
These are private, which means we can change them whenver and however we want. If users are relying on _ prefixed stuff, it's a world of pain for them in the future.
There was a problem hiding this comment.
That doesn't include _experiments, which is fine to advertise to users.
| + span_id = span.span_id | ||
| ``` | ||
|
|
||
| If you genuinely need the full trace context dict, for example to pass it to an external system, use the private `span._get_trace_context()` method instead. Prefer the direct properties where possible. |
There was a problem hiding this comment.
Same here, please don't advertise _get_trace_context().
For many of the wacky things possible in transaction land there is no alternative.
| ) | ||
| ``` | ||
|
|
||
| Both `ignore_spans` and `before_send_span` only have access to the span name and attributes set at creation time — not attributes added later in the span's lifetime, like an HTTP status code set after the request completes. If your `before_send_transaction` logic depended on that kind of late-set data, it can't be replicated in stream mode. Consider server-side filtering with Sentry inbound data filters or Relay rules instead. |
There was a problem hiding this comment.
"Consider server-side filtering with Sentry inbound data filters or Relay rules instead." <-- let's link to these, if we have documentation on them.
DESCRIBE YOUR PR
This PR adds the initial docs for Python span streaming: a New Spans page (intro to stream mode) and a Migration Guide (how to update existing custom instrumentation).
Context
For Python, the new Span API and stream mode ship together, so migrating to stream mode means migrating to the new Span API at the same time abd there's no way to use the new API while staying in transaction mode.
Because of that, putting the migration steps into the New Spans was way too much content and I split that content out into a new Migration guide. This guide is basically a human-readable version of the migration content from the engineering skill file.
Considerations
IS YOUR CHANGE URGENT?
Help us prioritize incoming PRs by letting us know when the change needs to go live.
SLA
Thanks in advance for your help!
PRE-MERGE CHECKLIST
Make sure you've checked the following before merging your changes:
LEGAL BOILERPLATE
Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
EXTRA RESOURCES