Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 76 additions & 46 deletions tests/integrations/django/asgi/test_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@
@pytest.mark.asyncio
@pytest.mark.forked
async def test_basic(sentry_init, capture_events, application):
sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
sentry_init(
integrations=[DjangoIntegration()],
send_default_pii=True,
)

events = capture_events()

comm = HttpCommunicator(application, "GET", "/view-exc?test=query")
response = await comm.get_response()
await comm.wait()

assert response["status"] == 500

(event,) = events
Expand Down Expand Up @@ -67,12 +72,17 @@ async def test_basic(sentry_init, capture_events, application):
django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
)
async def test_async_views(sentry_init, capture_events, application):
sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
sentry_init(
integrations=[DjangoIntegration()],
send_default_pii=True,
)

events = capture_events()

comm = HttpCommunicator(application, "GET", "/async_message")
response = await comm.get_response()
await comm.wait()

assert response["status"] == 200

(event,) = events
Expand Down Expand Up @@ -108,17 +118,16 @@ async def test_active_thread_id(sentry_init, capture_envelopes, endpoint, applic

comm = HttpCommunicator(application, "GET", endpoint)
response = await comm.get_response()
assert response["status"] == 200, response["body"]

await comm.wait()

data = json.loads(response["body"])
envelopes = [envelope for envelope in envelopes]
assert response["status"] == 200, response["body"]
assert len(envelopes) == 1

profiles = [item for item in envelopes[0].items if item.type == "profile"]
assert len(profiles) == 1

data = json.loads(response["body"])

for profile in profiles:
transactions = profile.payload.json["transactions"]
assert len(transactions) == 1
Expand All @@ -137,7 +146,10 @@ async def test_async_views_concurrent_execution(sentry_init, settings):
settings.MIDDLEWARE = []
asgi_application.load_middleware(is_async=True)

sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
sentry_init(
integrations=[DjangoIntegration()],
send_default_pii=True,
)

comm = HttpCommunicator(
asgi_application, "GET", "/my_async_view"
Expand Down Expand Up @@ -181,7 +193,10 @@ async def test_async_middleware_that_is_function_concurrent_execution(
]
asgi_application.load_middleware(is_async=True)

sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
sentry_init(
integrations=[DjangoIntegration()],
send_default_pii=True,
)

comm = HttpCommunicator(
asgi_application, "GET", "/my_async_view"
Expand Down Expand Up @@ -233,13 +248,13 @@ async def test_async_middleware_spans(

events = capture_events()

comm = HttpCommunicator(asgi_application, "GET", "/async_message")
comm = HttpCommunicator(asgi_application, "GET", "/simple_async_view")
response = await comm.get_response()
assert response["status"] == 200

await comm.wait()

message, transaction = events
assert response["status"] == 200

(transaction,) = events

assert (
render_span_tree(transaction)
Expand All @@ -252,7 +267,7 @@ async def test_async_middleware_spans(
- op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.__acall__"
- op="middleware.django": description="tests.integrations.django.myapp.settings.TestMiddleware.__acall__"
- op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.process_view"
- op="view.render": description="async_message"
- op="view.render": description="simple_async_view"
- op="event.django": description="django.db.close_old_connections"
- op="event.django": description="django.core.cache.close_caches"
- op="event.django": description="django.core.handlers.base.reset_urlconf\""""
Expand All @@ -265,27 +280,25 @@ async def test_async_middleware_spans(
django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
)
async def test_has_trace_if_performance_enabled(sentry_init, capture_events):
sentry_init(integrations=[DjangoIntegration()], traces_sample_rate=1.0)
sentry_init(
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
)

events = capture_events()

comm = HttpCommunicator(asgi_application, "GET", "/view-exc-with-msg")
response = await comm.get_response()
assert response["status"] == 500

# ASGI Django does not create transactions per default,
# so we do not have a transaction_event here.
(msg_event, error_event) = events
await comm.wait()

assert msg_event["contexts"]["trace"]
assert "trace_id" in msg_event["contexts"]["trace"]
assert response["status"] == 500

assert error_event["contexts"]["trace"]
assert "trace_id" in error_event["contexts"]["trace"]
(msg_event, error_event, transaction_event) = events

assert (
msg_event["contexts"]["trace"]["trace_id"]
== error_event["contexts"]["trace"]["trace_id"]
== transaction_event["contexts"]["trace"]["trace_id"]
)


Expand All @@ -295,12 +308,16 @@ async def test_has_trace_if_performance_enabled(sentry_init, capture_events):
django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
)
async def test_has_trace_if_performance_disabled(sentry_init, capture_events):
sentry_init(integrations=[DjangoIntegration()])
sentry_init(
integrations=[DjangoIntegration()],
)

events = capture_events()

comm = HttpCommunicator(asgi_application, "GET", "/view-exc-with-msg")
response = await comm.get_response()
await comm.wait()

assert response["status"] == 500

(msg_event, error_event) = events
Expand All @@ -322,7 +339,10 @@ async def test_has_trace_if_performance_disabled(sentry_init, capture_events):
django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
)
async def test_trace_from_headers_if_performance_enabled(sentry_init, capture_events):
sentry_init(integrations=[DjangoIntegration()], traces_sample_rate=1.0)
sentry_init(
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
)

events = capture_events()

Expand All @@ -336,20 +356,15 @@ async def test_trace_from_headers_if_performance_enabled(sentry_init, capture_ev
headers=[(b"sentry-trace", sentry_trace_header.encode())],
)
response = await comm.get_response()
assert response["status"] == 500
await comm.wait()

# ASGI Django does not create transactions per default,
# so we do not have a transaction_event here.
(msg_event, error_event) = events
assert response["status"] == 500

assert msg_event["contexts"]["trace"]
assert "trace_id" in msg_event["contexts"]["trace"]

assert error_event["contexts"]["trace"]
assert "trace_id" in error_event["contexts"]["trace"]
(msg_event, error_event, transaction_event) = events

assert msg_event["contexts"]["trace"]["trace_id"] == trace_id
assert error_event["contexts"]["trace"]["trace_id"] == trace_id
assert transaction_event["contexts"]["trace"]["trace_id"] == trace_id


@pytest.mark.asyncio
Expand All @@ -358,7 +373,9 @@ async def test_trace_from_headers_if_performance_enabled(sentry_init, capture_ev
django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
)
async def test_trace_from_headers_if_performance_disabled(sentry_init, capture_events):
sentry_init(integrations=[DjangoIntegration()])
sentry_init(
integrations=[DjangoIntegration()],
)

events = capture_events()

Expand All @@ -372,16 +389,12 @@ async def test_trace_from_headers_if_performance_disabled(sentry_init, capture_e
headers=[(b"sentry-trace", sentry_trace_header.encode())],
)
response = await comm.get_response()
await comm.wait()

assert response["status"] == 500

(msg_event, error_event) = events

assert msg_event["contexts"]["trace"]
assert "trace_id" in msg_event["contexts"]["trace"]

assert error_event["contexts"]["trace"]
assert "trace_id" in error_event["contexts"]["trace"]

assert msg_event["contexts"]["trace"]["trace_id"] == trace_id
assert error_event["contexts"]["trace"]["trace_id"] == trace_id

Expand Down Expand Up @@ -504,10 +517,8 @@ async def test_asgi_request_body(
expected_data,
):
sentry_init(
integrations=[DjangoIntegration()],
send_default_pii=send_default_pii,
integrations=[
DjangoIntegration(),
],
)

envelopes = capture_envelopes()
Expand All @@ -520,9 +531,9 @@ async def test_asgi_request_body(
body=body,
)
response = await comm.get_response()
assert response["status"] == 200

await comm.wait()

assert response["status"] == 200
assert response["body"] == body

(envelope,) = envelopes
Expand Down Expand Up @@ -594,3 +605,22 @@ def get_response(): ...

instance = sentry_asgi_mixin(get_response)
assert not inspect.iscoroutinefunction(instance)


@pytest.mark.parametrize("application", APPS)
@pytest.mark.asyncio
async def test_async_view(sentry_init, capture_events, application):
sentry_init(
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
)

events = capture_events()

comm = HttpCommunicator(application, "GET", "/simple_async_view")
await comm.get_response()
await comm.wait()

(event,) = events
assert event["type"] == "transaction"
assert event["transaction"] == "/simple_async_view"
5 changes: 5 additions & 0 deletions tests/integrations/django/myapp/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ def path(path, *args, **kwargs):
if views.my_async_view is not None:
urlpatterns.append(path("my_async_view", views.my_async_view, name="my_async_view"))

if views.my_async_view is not None:
urlpatterns.append(
path("simple_async_view", views.simple_async_view, name="simple_async_view")
)

if views.thread_ids_async is not None:
urlpatterns.append(
path("async/thread_ids", views.thread_ids_async, name="thread_ids_async")
Expand Down
4 changes: 4 additions & 0 deletions tests/integrations/django/myapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ async def my_async_view(request):
return HttpResponse("Hello World")


async def simple_async_view(request):
return HttpResponse("Simple Hello World")


async def thread_ids_async(request):
response = json.dumps(
{
Expand Down