|
19 | 19 |
|
20 | 20 | from sentry_sdk import capture_message, capture_exception, configure_scope |
21 | 21 | from sentry_sdk.integrations.django import DjangoIntegration |
| 22 | +from functools import partial |
22 | 23 |
|
23 | 24 | from tests.integrations.django.myapp.wsgi import application |
24 | 25 |
|
25 | 26 | # Hack to prevent from experimental feature introduced in version `4.3.0` in `pytest-django` that |
26 | 27 | # requires explicit database allow from failing the test |
27 | | -pytest_mark_django_db_decorator = pytest.mark.django_db |
| 28 | +pytest_mark_django_db_decorator = partial(pytest.mark.django_db) |
28 | 29 | try: |
29 | 30 | pytest_version = tuple(map(int, pytest_django.__version__.split("."))) |
30 | 31 | if pytest_version > (4, 2, 0): |
31 | | - pytest_mark_django_db_decorator = pytest.mark.django_db(databases="__all__") |
| 32 | + pytest_mark_django_db_decorator = partial( |
| 33 | + pytest.mark.django_db, databases="__all__" |
| 34 | + ) |
32 | 35 | except ValueError: |
33 | 36 | if "dev" in pytest_django.__version__: |
34 | | - pytest_mark_django_db_decorator = pytest.mark.django_db(databases="__all__") |
| 37 | + pytest_mark_django_db_decorator = partial( |
| 38 | + pytest.mark.django_db, databases="__all__" |
| 39 | + ) |
35 | 40 | except AttributeError: |
36 | 41 | pass |
37 | 42 |
|
@@ -259,7 +264,7 @@ def test_sql_queries(sentry_init, capture_events, with_integration): |
259 | 264 |
|
260 | 265 |
|
261 | 266 | @pytest.mark.forked |
262 | | -@pytest_mark_django_db_decorator |
| 267 | +@pytest_mark_django_db_decorator() |
263 | 268 | def test_sql_dict_query_params(sentry_init, capture_events): |
264 | 269 | sentry_init( |
265 | 270 | integrations=[DjangoIntegration()], |
@@ -304,7 +309,7 @@ def test_sql_dict_query_params(sentry_init, capture_events): |
304 | 309 | ], |
305 | 310 | ) |
306 | 311 | @pytest.mark.forked |
307 | | -@pytest_mark_django_db_decorator |
| 312 | +@pytest_mark_django_db_decorator() |
308 | 313 | def test_sql_psycopg2_string_composition(sentry_init, capture_events, query): |
309 | 314 | sentry_init( |
310 | 315 | integrations=[DjangoIntegration()], |
@@ -337,7 +342,7 @@ def test_sql_psycopg2_string_composition(sentry_init, capture_events, query): |
337 | 342 |
|
338 | 343 |
|
339 | 344 | @pytest.mark.forked |
340 | | -@pytest_mark_django_db_decorator |
| 345 | +@pytest_mark_django_db_decorator() |
341 | 346 | def test_sql_psycopg2_placeholders(sentry_init, capture_events): |
342 | 347 | sentry_init( |
343 | 348 | integrations=[DjangoIntegration()], |
@@ -397,6 +402,72 @@ def test_sql_psycopg2_placeholders(sentry_init, capture_events): |
397 | 402 | ] |
398 | 403 |
|
399 | 404 |
|
| 405 | +@pytest.mark.forked |
| 406 | +@pytest_mark_django_db_decorator(transaction=True) |
| 407 | +def test_django_connect_trace(sentry_init, client, capture_events, render_span_tree): |
| 408 | + """ |
| 409 | + Verify we record a span when opening a new database. |
| 410 | + """ |
| 411 | + sentry_init( |
| 412 | + integrations=[DjangoIntegration()], |
| 413 | + send_default_pii=True, |
| 414 | + traces_sample_rate=1.0, |
| 415 | + ) |
| 416 | + |
| 417 | + from django.db import connections |
| 418 | + |
| 419 | + if "postgres" not in connections: |
| 420 | + pytest.skip("postgres tests disabled") |
| 421 | + |
| 422 | + # trigger Django to open a new connection by marking the existing one as None. |
| 423 | + connections["postgres"].connection = None |
| 424 | + |
| 425 | + events = capture_events() |
| 426 | + |
| 427 | + content, status, headers = client.get(reverse("postgres_select")) |
| 428 | + assert status == "200 OK" |
| 429 | + |
| 430 | + assert '- op="db": description="connect"' in render_span_tree(events[0]) |
| 431 | + |
| 432 | + |
| 433 | +@pytest.mark.forked |
| 434 | +@pytest_mark_django_db_decorator(transaction=True) |
| 435 | +def test_django_connect_breadcrumbs( |
| 436 | + sentry_init, client, capture_events, render_span_tree |
| 437 | +): |
| 438 | + """ |
| 439 | + Verify we record a breadcrumb when opening a new database. |
| 440 | + """ |
| 441 | + sentry_init( |
| 442 | + integrations=[DjangoIntegration()], |
| 443 | + send_default_pii=True, |
| 444 | + ) |
| 445 | + |
| 446 | + from django.db import connections |
| 447 | + |
| 448 | + if "postgres" not in connections: |
| 449 | + pytest.skip("postgres tests disabled") |
| 450 | + |
| 451 | + # trigger Django to open a new connection by marking the existing one as None. |
| 452 | + connections["postgres"].connection = None |
| 453 | + |
| 454 | + events = capture_events() |
| 455 | + |
| 456 | + cursor = connections["postgres"].cursor() |
| 457 | + cursor.execute("select 1") |
| 458 | + |
| 459 | + # trigger recording of event. |
| 460 | + capture_message("HI") |
| 461 | + (event,) = events |
| 462 | + for crumb in event["breadcrumbs"]["values"]: |
| 463 | + del crumb["timestamp"] |
| 464 | + |
| 465 | + assert event["breadcrumbs"]["values"][-2:] == [ |
| 466 | + {"message": "connect", "category": "query", "type": "default"}, |
| 467 | + {"message": "select 1", "category": "query", "data": {}, "type": "default"}, |
| 468 | + ] |
| 469 | + |
| 470 | + |
400 | 471 | @pytest.mark.parametrize( |
401 | 472 | "transaction_style,expected_transaction", |
402 | 473 | [ |
|
0 commit comments