diff --git a/instana/instrumentation/sqlalchemy.py b/instana/instrumentation/sqlalchemy.py index 7b6f795e..831793b9 100644 --- a/instana/instrumentation/sqlalchemy.py +++ b/instana/instrumentation/sqlalchemy.py @@ -73,6 +73,9 @@ def _set_error_tags(context, exception_string, scope_string): @event.listens_for(Engine, error_event, named=True) def receive_handle_db_error(**kw): + if get_active_tracer() is None: + return + # support older db error event if error_event == "dbapi_error": context = kw.get('context') diff --git a/tests/clients/test_sqlalchemy.py b/tests/clients/test_sqlalchemy.py index 7dcbd698..fbf92120 100644 --- a/tests/clients/test_sqlalchemy.py +++ b/tests/clients/test_sqlalchemy.py @@ -8,6 +8,7 @@ from ..helpers import testenv from instana.singletons import tracer from sqlalchemy.orm import sessionmaker +from sqlalchemy.exc import OperationalError from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, create_engine @@ -181,3 +182,29 @@ def test_error_logging(self): self.assertIsNotNone(sql_span.stack) self.assertTrue(type(sql_span.stack) is list) self.assertGreater(len(sql_span.stack), 0) + + def test_error_before_tracing(self): + """Test the scenario, in which instana is loaded, + but connection fails before tracing begins. + This is typical in test container scenario, + where it is "normal" to just start hammering a database container + which is still starting and not ready to handle requests yet. + In this scenario it is important that we get + an sqlalachemy exception, and not something else + like an AttributeError. Because testcontainer has a logic + to retry in case of certain sqlalchemy exceptions but it + can't handle an AttributeError.""" + # https://github.com/instana/python-sensor/issues/362 + + self.assertIsNone(tracer.active_span) + + invalid_connection_url = 'postgresql://user1:pwd1@localhost:9999/mydb1' + with self.assertRaisesRegex( + OperationalError, + r'\(psycopg2.OperationalError\) connection .* failed.*' + ) as context_manager: + engine = create_engine(invalid_connection_url) + version, = engine.execute("select version()").fetchone() + + the_exception = context_manager.exception + self.assertFalse(the_exception.connection_invalidated) diff --git a/tests/conftest.py b/tests/conftest.py index 48b66f38..57199dbf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,6 +26,7 @@ collect_ignore_glob.append("*test_grpc*") collect_ignore_glob.append("*test_boto3*") collect_ignore_glob.append("*test_stan_recorder*") + collect_ignore_glob.append("*test_sqlalchemy*") if "ASYNQP_TEST" not in os.environ: # if LooseVersion(sys.version) < LooseVersion('3.5.3') or LooseVersion(sys.version) >= LooseVersion('3.8.0'):