Skip to content

Commit 1aa2e6d

Browse files
feat(starlite): Set name and source on request span when streaming (#6552)
Call `Scope.set_transaction_name()` on isolation and current scopes instead of manually overwriting event fields in an event processor. This ensures that the span name and the `sentry.span.source` attribute are set on the segment span when the streaming trace lifecycle is enabled.
1 parent 0d9595b commit 1aa2e6d

2 files changed

Lines changed: 84 additions & 25 deletions

File tree

sentry_sdk/integrations/starlite.py

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -238,39 +238,36 @@ async def handle_wrapper(
238238

239239
request_data = await body
240240

241-
def event_processor(event: "Event", _: "Hint") -> "Event":
242-
route_handler = scope.get("route_handler")
241+
route_handler = scope.get("route_handler")
242+
243+
func = None
244+
if route_handler.name is not None:
245+
name = route_handler.name
246+
elif isinstance(route_handler.fn, Ref):
247+
func = route_handler.fn.value
248+
else:
249+
func = route_handler.fn
250+
if func is not None:
251+
name = transaction_from_function(func)
252+
253+
source = SOURCE_FOR_STYLE["endpoint"]
243254

255+
if not name:
256+
name = _DEFAULT_TRANSACTION_NAME
257+
source = TransactionSource.ROUTE
258+
259+
sentry_sdk.set_transaction_name(name, source)
260+
sentry_scope.set_transaction_name(name, source)
261+
262+
def event_processor(event: "Event", _: "Hint") -> "Event":
244263
request_info = event.get("request", {})
245264
request_info["content_length"] = len(scope.get("_body", b""))
246265
if should_send_default_pii():
247266
request_info["cookies"] = extracted_request_data["cookies"]
248267
if request_data is not None:
249268
request_info["data"] = request_data
250269

251-
func = None
252-
if route_handler.name is not None:
253-
tx_name = route_handler.name
254-
elif isinstance(route_handler.fn, Ref):
255-
func = route_handler.fn.value
256-
else:
257-
func = route_handler.fn
258-
if func is not None:
259-
tx_name = transaction_from_function(func)
260-
261-
tx_info = {"source": SOURCE_FOR_STYLE["endpoint"]}
262-
263-
if not tx_name:
264-
tx_name = _DEFAULT_TRANSACTION_NAME
265-
tx_info = {"source": TransactionSource.ROUTE}
266-
267-
event.update(
268-
{
269-
"request": deepcopy(request_info),
270-
"transaction": tx_name,
271-
"transaction_info": tx_info,
272-
}
273-
)
270+
event["request"] = deepcopy(request_info)
274271
return event
275272

276273
sentry_scope._name = StarliteIntegration.identifier

tests/integrations/starlite/test_starlite.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,68 @@ def test_catch_exceptions(
112112
assert event["exception"]["values"][0]["mechanism"]["type"] == "starlite"
113113

114114

115+
@pytest.mark.parametrize(
116+
"test_url,expected_tx_name",
117+
[
118+
(
119+
"/some_url",
120+
"tests.integrations.starlite.test_starlite.starlite_app_factory.<locals>.homepage_handler",
121+
),
122+
(
123+
"/custom_error",
124+
"custom_name",
125+
),
126+
(
127+
"/controller/error",
128+
"partial(<function tests.integrations.starlite.test_starlite.starlite_app_factory.<locals>.MyController.controller_error>)",
129+
),
130+
],
131+
)
132+
@pytest.mark.parametrize("span_streaming", [True, False])
133+
def test_transaction_name_and_source(
134+
sentry_init,
135+
capture_events,
136+
test_url,
137+
expected_tx_name,
138+
capture_items,
139+
span_streaming,
140+
):
141+
sentry_init(
142+
traces_sample_rate=1.0,
143+
integrations=[StarliteIntegration()],
144+
_experiments={
145+
"trace_lifecycle": "stream" if span_streaming else "static",
146+
},
147+
)
148+
starlite_app = starlite_app_factory()
149+
client = TestClient(starlite_app)
150+
151+
if span_streaming:
152+
items = capture_items("span")
153+
154+
try:
155+
client.get(test_url)
156+
except Exception:
157+
pass
158+
159+
sentry_sdk.flush()
160+
spans = [item.payload for item in items]
161+
spans = [span for span in spans if expected_tx_name in span["name"]]
162+
assert len(spans) == 1
163+
assert spans[0]["attributes"]["sentry.span.source"] == "component"
164+
else:
165+
events = capture_events()
166+
167+
try:
168+
client.get(test_url)
169+
except Exception:
170+
pass
171+
172+
(_, transaction) = events
173+
assert expected_tx_name in transaction["transaction"]
174+
assert transaction["transaction_info"] == {"source": "component"}
175+
176+
115177
@pytest.mark.parametrize("span_streaming", [True, False])
116178
def test_middleware_spans(sentry_init, capture_events, capture_items, span_streaming):
117179
sentry_init(

0 commit comments

Comments
 (0)