diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index c320904ae3..a9fa9f0188 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -290,7 +290,7 @@ def __init__( max_value_length=DEFAULT_MAX_VALUE_LENGTH, # type: int enable_backpressure_handling=True, # type: bool error_sampler=None, # type: Optional[Callable[[Event, Hint], Union[float, bool]]] - enable_db_query_source=False, # type: bool + enable_db_query_source=True, # type: bool db_query_source_threshold_ms=100, # type: int spotlight=None, # type: Optional[Union[bool, str]] ): diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index f6d8acabb2..bc0ddc51d5 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -180,7 +180,7 @@ def add_query_source(hub, span): if span.timestamp is None or span.start_timestamp is None: return - should_add_query_source = client.options.get("enable_db_query_source", False) + should_add_query_source = client.options.get("enable_db_query_source", True) if not should_add_query_source: return diff --git a/tests/integrations/asyncpg/test_asyncpg.py b/tests/integrations/asyncpg/test_asyncpg.py index b9d96e1718..705ac83dbc 100644 --- a/tests/integrations/asyncpg/test_asyncpg.py +++ b/tests/integrations/asyncpg/test_asyncpg.py @@ -472,17 +472,13 @@ async def test_connection_pool(sentry_init, capture_events) -> None: @pytest.mark.asyncio -@pytest.mark.parametrize("enable_db_query_source", [None, False]) -async def test_query_source_disabled( - sentry_init, capture_events, enable_db_query_source -): +async def test_query_source_disabled(sentry_init, capture_events): sentry_options = { "integrations": [AsyncPGIntegration()], "enable_tracing": True, + "enable_db_query_source": False, + "db_query_source_threshold_ms": 0, } - if enable_db_query_source is not None: - sentry_options["enable_db_query_source"] = enable_db_query_source - sentry_options["db_query_source_threshold_ms"] = 0 sentry_init(**sentry_options) @@ -510,6 +506,45 @@ async def test_query_source_disabled( assert SPANDATA.CODE_FUNCTION not in data +@pytest.mark.asyncio +@pytest.mark.parametrize("enable_db_query_source", [None, True]) +async def test_query_source_enabled( + sentry_init, capture_events, enable_db_query_source +): + sentry_options = { + "integrations": [AsyncPGIntegration()], + "enable_tracing": True, + "db_query_source_threshold_ms": 0, + } + if enable_db_query_source is not None: + sentry_options["enable_db_query_source"] = enable_db_query_source + + sentry_init(**sentry_options) + + events = capture_events() + + with start_transaction(name="test_transaction", sampled=True): + conn: Connection = await connect(PG_CONNECTION_URI) + + await conn.execute( + "INSERT INTO users(name, password, dob) VALUES ('Alice', 'secret', '1990-12-25')", + ) + + await conn.close() + + (event,) = events + + span = event["spans"][-1] + assert span["description"].startswith("INSERT INTO") + + data = span.get("data", {}) + + assert SPANDATA.CODE_LINENO in data + assert SPANDATA.CODE_NAMESPACE in data + assert SPANDATA.CODE_FILEPATH in data + assert SPANDATA.CODE_FUNCTION in data + + @pytest.mark.asyncio async def test_query_source(sentry_init, capture_events): sentry_init( diff --git a/tests/integrations/django/test_db_query_data.py b/tests/integrations/django/test_db_query_data.py index d773a3486a..cf2ef57358 100644 --- a/tests/integrations/django/test_db_query_data.py +++ b/tests/integrations/django/test_db_query_data.py @@ -35,18 +35,14 @@ def client(): @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("enable_db_query_source", [None, False]) -def test_query_source_disabled( - sentry_init, client, capture_events, enable_db_query_source -): +def test_query_source_disabled(sentry_init, client, capture_events): sentry_options = { "integrations": [DjangoIntegration()], "send_default_pii": True, "traces_sample_rate": 1.0, + "enable_db_query_source": False, + "db_query_source_threshold_ms": 0, } - if enable_db_query_source is not None: - sentry_options["enable_db_query_source"] = enable_db_query_source - sentry_options["db_query_source_threshold_ms"] = 0 sentry_init(**sentry_options) @@ -75,6 +71,50 @@ def test_query_source_disabled( raise AssertionError("No db span found") +@pytest.mark.forked +@pytest_mark_django_db_decorator(transaction=True) +@pytest.mark.parametrize("enable_db_query_source", [None, True]) +def test_query_source_enabled( + sentry_init, client, capture_events, enable_db_query_source +): + sentry_options = { + "integrations": [DjangoIntegration()], + "send_default_pii": True, + "traces_sample_rate": 1.0, + "db_query_source_threshold_ms": 0, + } + + if enable_db_query_source is not None: + sentry_options["enable_db_query_source"] = enable_db_query_source + + sentry_init(**sentry_options) + + if "postgres" not in connections: + pytest.skip("postgres tests disabled") + + # trigger Django to open a new connection by marking the existing one as None. + connections["postgres"].connection = None + + events = capture_events() + + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" + + (event,) = events + for span in event["spans"]: + if span.get("op") == "db" and "auth_user" in span.get("description"): + data = span.get("data", {}) + + assert SPANDATA.CODE_LINENO in data + assert SPANDATA.CODE_NAMESPACE in data + assert SPANDATA.CODE_FILEPATH in data + assert SPANDATA.CODE_FUNCTION in data + + break + else: + raise AssertionError("No db span found") + + @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) def test_query_source(sentry_init, client, capture_events): diff --git a/tests/integrations/sqlalchemy/test_sqlalchemy.py b/tests/integrations/sqlalchemy/test_sqlalchemy.py index 292e4026b7..bea22cbcd2 100644 --- a/tests/integrations/sqlalchemy/test_sqlalchemy.py +++ b/tests/integrations/sqlalchemy/test_sqlalchemy.py @@ -235,15 +235,13 @@ def test_engine_name_not_string(sentry_init): con.execute(text("SELECT 0")) -@pytest.mark.parametrize("enable_db_query_source", [None, False]) -def test_query_source_disabled(sentry_init, capture_events, enable_db_query_source): +def test_query_source_disabled(sentry_init, capture_events): sentry_options = { "integrations": [SqlalchemyIntegration()], "enable_tracing": True, + "enable_db_query_source": False, + "db_query_source_threshold_ms": 0, } - if enable_db_query_source is not None: - sentry_options["enable_db_query_source"] = enable_db_query_source - sentry_options["db_query_source_threshold_ms"] = 0 sentry_init(**sentry_options) @@ -285,6 +283,56 @@ class Person(Base): raise AssertionError("No db span found") +@pytest.mark.parametrize("enable_db_query_source", [None, True]) +def test_query_source_enabled(sentry_init, capture_events, enable_db_query_source): + sentry_options = { + "integrations": [SqlalchemyIntegration()], + "enable_tracing": True, + "db_query_source_threshold_ms": 0, + } + if enable_db_query_source is not None: + sentry_options["enable_db_query_source"] = enable_db_query_source + + sentry_init(**sentry_options) + + events = capture_events() + + with start_transaction(name="test_transaction", sampled=True): + Base = declarative_base() # noqa: N806 + + class Person(Base): + __tablename__ = "person" + id = Column(Integer, primary_key=True) + name = Column(String(250), nullable=False) + + engine = create_engine("sqlite:///:memory:") + Base.metadata.create_all(engine) + + Session = sessionmaker(bind=engine) # noqa: N806 + session = Session() + + bob = Person(name="Bob") + session.add(bob) + + assert session.query(Person).first() == bob + + (event,) = events + + for span in event["spans"]: + if span.get("op") == "db" and span.get("description").startswith( + "SELECT person" + ): + data = span.get("data", {}) + + assert SPANDATA.CODE_LINENO in data + assert SPANDATA.CODE_NAMESPACE in data + assert SPANDATA.CODE_FILEPATH in data + assert SPANDATA.CODE_FUNCTION in data + break + else: + raise AssertionError("No db span found") + + def test_query_source(sentry_init, capture_events): sentry_init( integrations=[SqlalchemyIntegration()],