From e6ec4724a56aa8dbfe8211fc24219c4377ae010b Mon Sep 17 00:00:00 2001 From: Ivana Kellyerova Date: Tue, 6 Feb 2024 09:18:03 +0100 Subject: [PATCH] fix(sqlalchemy): Guard against `engine.url` being `None` (#2708) --- sentry_sdk/integrations/sqlalchemy.py | 3 + .../sqlalchemy/test_sqlalchemy.py | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 579723ff08..5850237e97 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -153,6 +153,9 @@ def _set_db_data(span, conn): if db_system is not None: span.set_data(SPANDATA.DB_SYSTEM, db_system) + if conn.engine.url is None: + return + db_name = conn.engine.url.database if db_name is not None: span.set_data(SPANDATA.DB_NAME, db_name) diff --git a/tests/integrations/sqlalchemy/test_sqlalchemy.py b/tests/integrations/sqlalchemy/test_sqlalchemy.py index bea22cbcd2..3f196cd0b9 100644 --- a/tests/integrations/sqlalchemy/test_sqlalchemy.py +++ b/tests/integrations/sqlalchemy/test_sqlalchemy.py @@ -154,6 +154,62 @@ class Address(Base): ) +@pytest.mark.skipif( + sys.version_info < (3,), reason="This sqla usage seems to be broken on Py2" +) +def test_transactions_no_engine_url(sentry_init, capture_events): + sentry_init( + integrations=[SqlalchemyIntegration()], + _experiments={"record_sql_params": True}, + traces_sample_rate=1.0, + ) + events = capture_events() + + Base = declarative_base() # noqa: N806 + + class Person(Base): + __tablename__ = "person" + id = Column(Integer, primary_key=True) + name = Column(String(250), nullable=False) + + class Address(Base): + __tablename__ = "address" + id = Column(Integer, primary_key=True) + street_name = Column(String(250)) + street_number = Column(String(250)) + post_code = Column(String(250), nullable=False) + person_id = Column(Integer, ForeignKey("person.id")) + person = relationship(Person) + + engine = create_engine("sqlite:///:memory:") + engine.url = None + Base.metadata.create_all(engine) + + Session = sessionmaker(bind=engine) # noqa: N806 + session = Session() + + with start_transaction(name="test_transaction", sampled=True): + with session.begin_nested(): + session.query(Person).first() + + for _ in range(2): + with pytest.raises(IntegrityError): + with session.begin_nested(): + session.add(Person(id=1, name="bob")) + session.add(Person(id=1, name="bob")) + + with session.begin_nested(): + session.query(Person).first() + + (event,) = events + + for span in event["spans"]: + assert span["data"][SPANDATA.DB_SYSTEM] == "sqlite" + assert SPANDATA.DB_NAME not in span["data"] + assert SPANDATA.SERVER_ADDRESS not in span["data"] + assert SPANDATA.SERVER_PORT not in span["data"] + + def test_long_sql_query_preserved(sentry_init, capture_events): sentry_init( traces_sample_rate=1,