-
Notifications
You must be signed in to change notification settings - Fork 641
feat(starlette): Support span streaming #6123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f50e1ab
32286b8
50352ea
6eacecc
943c3d4
4493974
92b4121
29de949
48415ad
3ae7b8a
35c6906
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
When span streaming is enabled, attach the request body (serialized via a JSON default that unwraps AnnotatedValue) to the active segment span as `http.request.body.data` inside `patch_request_response`. This mirrors the body capture that the legacy request-event processor does, so streamed spans carry the same payload context without relying on transaction events. PII scrubbing is intentionally not applied here — under span streaming, sanitization is expected to happen in `before_send_span` hooks. Tests cover the unscrubbed passthrough, a top-level AnnotatedValue (raw bytes), and a nested AnnotatedValue inside a multipart form upload. Refs PY-2362 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import asyncio | ||
| import functools | ||
| import json | ||
| import warnings | ||
| from collections.abc import Set | ||
| from copy import deepcopy | ||
|
|
@@ -233,6 +234,16 @@ async def _sentry_send(*args: "Any", **kwargs: "Any") -> "Any": | |
| return middleware_class | ||
|
|
||
|
|
||
| def _serialize_body_data(data: "Any") -> str: | ||
| # data may be a JSON-serializable value, an AnnotatedValue, or a dict with AnnotatedValue values | ||
| def _default(value: "Any") -> "Any": | ||
| if isinstance(value, AnnotatedValue): | ||
| return {"value": value.value, "metadata": value.metadata} | ||
| return str(value) | ||
|
|
||
| return json.dumps(data, default=_default) | ||
|
Comment on lines
+237
to
+244
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the data here have I hope we can just get rid of the whole
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It can when a raw value is present, or if the request body exceeds the size limit set by the Both of these occur within the
From this thread, sanitization, at least for the request body, will be the user's responsibility using the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gotcha. In that case looks good -- but in case of Stamping this already to unblock. |
||
|
|
||
|
|
||
| @ensure_integration_enabled(StarletteIntegration) | ||
| def _capture_exception(exception: BaseException, handled: "Any" = False) -> None: | ||
| event, hint = event_from_exception( | ||
|
|
@@ -500,6 +511,23 @@ def event_processor( | |
| _make_request_event_processor(request, integration) | ||
| ) | ||
|
ericapisani marked this conversation as resolved.
|
||
|
|
||
| client = sentry_sdk.get_client() | ||
| is_span_streaming_enabled = has_span_streaming_enabled(client.options) | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| if is_span_streaming_enabled: | ||
| current_span = sentry_sdk.get_current_span() | ||
|
|
||
| if ( | ||
| info | ||
| and "data" in info | ||
| and isinstance(current_span, StreamedSpan) | ||
| and not isinstance(current_span, NoOpStreamedSpan) | ||
| ): | ||
| data = info["data"] | ||
| current_span.set_attribute( | ||
| "http.request.body.data", | ||
| _serialize_body_data(data), | ||
| ) | ||
|
cursor[bot] marked this conversation as resolved.
Outdated
cursor[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| return await old_func(*args, **kwargs) | ||
|
|
||
| func = _sentry_async_func | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.