Skip to content

Commit 2c0ff93

Browse files
authored
Bug fixes for FastAPI and Sentry SDK 1.10.0 (#1699)
Make sure receive/send callbacks can also be functools.partial objects (or other objects that are not having a __name__) Refs #1697
1 parent fdb7512 commit 2c0ff93

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

sentry_sdk/integrations/starlette.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,25 +103,28 @@ async def _sentry_receive(*args, **kwargs):
103103
hub = Hub.current
104104
with hub.start_span(
105105
op=OP.MIDDLEWARE_STARLETTE_RECEIVE,
106-
description=receive.__qualname__,
106+
description=getattr(receive, "__qualname__", str(receive)),
107107
) as span:
108108
span.set_tag("starlette.middleware_name", middleware_name)
109109
return await receive(*args, **kwargs)
110110

111-
receive_patched = receive.__name__ == "_sentry_receive"
111+
receive_name = getattr(receive, "__name__", str(receive))
112+
receive_patched = receive_name == "_sentry_receive"
112113
new_receive = _sentry_receive if not receive_patched else receive
113114

114115
# Creating spans for the "send" callback
115116
async def _sentry_send(*args, **kwargs):
116117
# type: (*Any, **Any) -> Any
117118
hub = Hub.current
118119
with hub.start_span(
119-
op=OP.MIDDLEWARE_STARLETTE_SEND, description=send.__qualname__
120+
op=OP.MIDDLEWARE_STARLETTE_SEND,
121+
description=getattr(send, "__qualname__", str(send)),
120122
) as span:
121123
span.set_tag("starlette.middleware_name", middleware_name)
122124
return await send(*args, **kwargs)
123125

124-
send_patched = send.__name__ == "_sentry_send"
126+
send_name = getattr(send, "__name__", str(send))
127+
send_patched = send_name == "_sentry_send"
125128
new_send = _sentry_send if not send_patched else send
126129

127130
return await old_call(app, scope, new_receive, new_send, **kwargs)

tests/integrations/starlette/test_starlette.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import base64
3+
import functools
34
import json
45
import os
56

@@ -189,6 +190,30 @@ async def __call__(self, scope, receive, send):
189190
await self.app(scope, receive, send)
190191

191192

193+
class SamplePartialReceiveSendMiddleware:
194+
def __init__(self, app):
195+
self.app = app
196+
197+
async def __call__(self, scope, receive, send):
198+
message = await receive()
199+
assert message
200+
assert message["type"] == "http.request"
201+
202+
send_output = await send({"type": "something-unimportant"})
203+
assert send_output is None
204+
205+
async def my_receive(*args, **kwargs):
206+
pass
207+
208+
async def my_send(*args, **kwargs):
209+
pass
210+
211+
partial_receive = functools.partial(my_receive)
212+
partial_send = functools.partial(my_send)
213+
214+
await self.app(scope, partial_receive, partial_send)
215+
216+
192217
@pytest.mark.asyncio
193218
async def test_starlettrequestextractor_content_length(sentry_init):
194219
with mock.patch(
@@ -659,8 +684,7 @@ def test_middleware_callback_spans(sentry_init, capture_events):
659684
idx += 1
660685

661686

662-
@pytest.mark.asyncio
663-
async def test_middleware_receive_send(sentry_init, capture_events):
687+
def test_middleware_receive_send(sentry_init, capture_events):
664688
sentry_init(
665689
traces_sample_rate=1.0,
666690
integrations=[StarletteIntegration()],
@@ -678,6 +702,79 @@ async def test_middleware_receive_send(sentry_init, capture_events):
678702
pass
679703

680704

705+
def test_middleware_partial_receive_send(sentry_init, capture_events):
706+
sentry_init(
707+
traces_sample_rate=1.0,
708+
integrations=[StarletteIntegration()],
709+
)
710+
starlette_app = starlette_app_factory(
711+
middleware=[Middleware(SamplePartialReceiveSendMiddleware)]
712+
)
713+
events = capture_events()
714+
715+
client = TestClient(starlette_app, raise_server_exceptions=False)
716+
try:
717+
client.get("/message", auth=("Gabriela", "hello123"))
718+
except Exception:
719+
pass
720+
721+
(_, transaction_event) = events
722+
723+
expected = [
724+
{
725+
"op": "middleware.starlette",
726+
"description": "ServerErrorMiddleware",
727+
"tags": {"starlette.middleware_name": "ServerErrorMiddleware"},
728+
},
729+
{
730+
"op": "middleware.starlette",
731+
"description": "SamplePartialReceiveSendMiddleware",
732+
"tags": {"starlette.middleware_name": "SamplePartialReceiveSendMiddleware"},
733+
},
734+
{
735+
"op": "middleware.starlette.receive",
736+
"description": "_ASGIAdapter.send.<locals>.receive"
737+
if STARLETTE_VERSION < (0, 21)
738+
else "_TestClientTransport.handle_request.<locals>.receive",
739+
"tags": {"starlette.middleware_name": "ServerErrorMiddleware"},
740+
},
741+
{
742+
"op": "middleware.starlette.send",
743+
"description": "ServerErrorMiddleware.__call__.<locals>._send",
744+
"tags": {"starlette.middleware_name": "SamplePartialReceiveSendMiddleware"},
745+
},
746+
{
747+
"op": "middleware.starlette.send",
748+
"description": "_ASGIAdapter.send.<locals>.send"
749+
if STARLETTE_VERSION < (0, 21)
750+
else "_TestClientTransport.handle_request.<locals>.send",
751+
"tags": {"starlette.middleware_name": "ServerErrorMiddleware"},
752+
},
753+
{
754+
"op": "middleware.starlette",
755+
"description": "ExceptionMiddleware",
756+
"tags": {"starlette.middleware_name": "ExceptionMiddleware"},
757+
},
758+
{
759+
"op": "middleware.starlette.send",
760+
"description": "functools.partial(<function SamplePartialReceiveSendMiddleware.__call__.<locals>.my_send at ",
761+
"tags": {"starlette.middleware_name": "ExceptionMiddleware"},
762+
},
763+
{
764+
"op": "middleware.starlette.send",
765+
"description": "functools.partial(<function SamplePartialReceiveSendMiddleware.__call__.<locals>.my_send at ",
766+
"tags": {"starlette.middleware_name": "ExceptionMiddleware"},
767+
},
768+
]
769+
770+
idx = 0
771+
for span in transaction_event["spans"]:
772+
assert span["op"] == expected[idx]["op"]
773+
assert span["description"].startswith(expected[idx]["description"])
774+
assert span["tags"] == expected[idx]["tags"]
775+
idx += 1
776+
777+
681778
def test_last_event_id(sentry_init, capture_events):
682779
sentry_init(
683780
integrations=[StarletteIntegration()],

0 commit comments

Comments
 (0)