feat(tornado): Support span streaming#6206
Conversation
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)
Generated by Codecov Action |
alexander-alderman-webb
left a comment
There was a problem hiding this comment.
Comment not blocking, looks good to me!
| span.status = "error" if status_int >= 400 else "ok" | ||
|
|
||
|
|
||
| def _get_request_attributes(request: "Any") -> "Dict[str, Any]": |
There was a problem hiding this comment.
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
| span.status = "error" if status_int >= 400 else "ok" | ||
|
|
||
|
|
||
| def _get_request_attributes(request: "Any") -> "Dict[str, Any]": |
82de412 to
a58538d
Compare
036b60a to
4f36419
Compare
4d430e9 to
2106ec2
Compare
e390c87 to
ec6fd01
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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.
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>
4d4e44e to
4c597a4
Compare
| scope.set_custom_sampling_context({"tornado_request": self.request}) | ||
|
|
||
| span_ctx = sentry_sdk.traces.start_span( | ||
| name=_DEFAULT_TRANSACTION_NAME, |
There was a problem hiding this comment.
_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.
| if isinstance(span, StreamedSpan) and not isinstance( | ||
| span, NoOpStreamedSpan | ||
| ): |
There was a problem hiding this comment.
This can be made a bit more concise with type(span) is StreamedSpan:
| if isinstance(span, StreamedSpan) and not isinstance( | |
| span, NoOpStreamedSpan | |
| ): | |
| if type(span) is StreamedSpan: |
| span.set_attribute( | ||
| "sentry.span.source", | ||
| SegmentSource.COMPONENT, |
There was a problem hiding this comment.
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)): |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
Since this is now testing both segments and transactions, this test name should be updated

Issues