Skip to content

feat(tornado): Support span streaming#6206

Open
sl0thentr0py wants to merge 5 commits into
masterfrom
neel/span-first/tornado
Open

feat(tornado): Support span streaming#6206
sl0thentr0py wants to merge 5 commits into
masterfrom
neel/span-first/tornado

Conversation

@sl0thentr0py
Copy link
Copy Markdown
Member

Issues

@sl0thentr0py sl0thentr0py requested a review from a team as a code owner May 5, 2026 13:32
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 5, 2026

@sl0thentr0py sl0thentr0py changed the title ref(tornado): migrate to span-first ref(tornado): migrate to span first May 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Codecov Results 📊

13 passed | Total: 13 | Pass Rate: 100% | Execution Time: 10.05s

All tests are passing successfully.

❌ Patch coverage is 19.12%. Project has 16272 uncovered lines.

Files with missing lines (2)
File Patch % Lines
tornado.py 10.91% ⚠️ 147 Missing
consts.py 99.50% ⚠️ 2 Missing

Generated by Codecov Action

@sl0thentr0py sl0thentr0py changed the title ref(tornado): migrate to span first feat(tornado): Support span streaming May 5, 2026
Copy link
Copy Markdown
Contributor

@alexander-alderman-webb alexander-alderman-webb left a comment

Choose a reason for hiding this comment

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

Comment not blocking, looks good to me!

Comment thread sentry_sdk/integrations/tornado.py Outdated
Comment thread tests/integrations/tornado/test_tornado.py Outdated
Comment thread tests/integrations/tornado/test_tornado.py Outdated
span.status = "error" if status_int >= 400 else "ok"


def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are we still capturing the request body in the streaming path? See https://getsentry.github.io/sentry-conventions/attributes/http/#http-request-body-data

For prior art IIRC @ericapisani did this for another integration, not sure which exactly

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

starlette and aiohttp were the couple that I worked on that had this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added req body

Comment thread sentry_sdk/integrations/tornado.py Outdated
Comment thread sentry_sdk/integrations/tornado.py Outdated
span.status = "error" if status_int >= 400 else "ok"


def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

starlette and aiohttp were the couple that I worked on that had this

Comment thread sentry_sdk/integrations/tornado.py
@sl0thentr0py sl0thentr0py force-pushed the neel/span-first/tornado branch from 82de412 to a58538d Compare May 7, 2026 13:05
Comment thread sentry_sdk/integrations/tornado.py
Comment thread sentry_sdk/integrations/tornado.py Outdated
Comment thread sentry_sdk/integrations/tornado.py
@sl0thentr0py sl0thentr0py force-pushed the neel/span-first/tornado branch from 036b60a to 4f36419 Compare May 15, 2026 12:34
Comment thread sentry_sdk/integrations/tornado.py Outdated
Comment thread sentry_sdk/integrations/tornado.py Outdated
Comment thread sentry_sdk/integrations/tornado.py
@sl0thentr0py sl0thentr0py force-pushed the neel/span-first/tornado branch 3 times, most recently from 4d430e9 to 2106ec2 Compare May 15, 2026 13:06
@sl0thentr0py sl0thentr0py force-pushed the neel/span-first/tornado branch 3 times, most recently from e390c87 to ec6fd01 Compare May 15, 2026 13:14
Comment thread sentry_sdk/integrations/tornado.py Outdated
Copy link
Copy Markdown

@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.

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit 1fa438a. Configure here.

Comment thread sentry_sdk/integrations/tornado.py
sl0thentr0py and others added 5 commits May 15, 2026 15:52
Add span-streaming support to the Tornado integration. When span
streaming is enabled, the request handler emits a StreamedSpan with
HTTP request attributes (method, headers, query, URL, client address)
and sets the response status on completion. The legacy transaction
path is preserved for non-streaming mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sl0thentr0py sl0thentr0py force-pushed the neel/span-first/tornado branch from 4d4e44e to 4c597a4 Compare May 15, 2026 13:52
Comment thread sentry_sdk/integrations/tornado.py
scope.set_custom_sampling_context({"tornado_request": self.request})

span_ctx = sentry_sdk.traces.start_span(
name=_DEFAULT_TRANSACTION_NAME,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

_DEFAULT_TRANSACTION_NAME is a bit strange to read in the context of streamed spans where there is no longer a "transaction".

I'm ok with either leaving this as-is until we remove the transaction v1 spans and updating this then, or doing a rename that indicates that this name is the default for a "root" span.

Comment on lines +163 to +165
if isinstance(span, StreamedSpan) and not isinstance(
span, NoOpStreamedSpan
):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can be made a bit more concise with type(span) is StreamedSpan:

Suggested change
if isinstance(span, StreamedSpan) and not isinstance(
span, NoOpStreamedSpan
):
if type(span) is StreamedSpan:

Comment on lines +178 to +180
span.set_attribute(
"sentry.span.source",
SegmentSource.COMPONENT,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a reason why setting this attribute is being gated by whether or not a span_name exists? This looks like something that we could set regardless.

if not body:
return None

if not request_body_within_bounds(sentry_sdk.get_client(), len(body)):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is the body at this point in time the "realized" result? For example, the result of request.json()?

I'm also wondering if using the content-length header - does tornado set this automatically for incoming requests?

def test_transactions(tornado_testcase, sentry_init, capture_events, handler, code):
sentry_init(integrations=[TornadoIntegration()], traces_sample_rate=1.0)
events = capture_events()
def test_transactions(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this is now testing both segments and transactions, this test name should be updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate tornado to span first

4 participants