From 7994e39017b59ef89eeb7608f548ea35864e2b80 Mon Sep 17 00:00:00 2001 From: Atishyy27 <142108881+Atishyy27@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:49:26 +0530 Subject: [PATCH 1/2] fix(sqlalchemy): avoid IndexError in _operation_name for comment/whitespace-only statements A statement that is truthy but has no tokens after leading-comment or whitespace stripping made .split()[0] raise IndexError in _operation_name. Guard it so such a statement falls back to the db name / vendor instead of crashing. Adds a regression test. Follow-up to #4934. Signed-off-by: Atishyy27 <142108881+Atishyy27@users.noreply.github.com> --- .../instrumentation/sqlalchemy/engine.py | 8 ++++++-- .../tests/test_sqlalchemy.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py index 3185422b47..67ce599071 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py @@ -315,8 +315,12 @@ def _operation_name(self, db_name, statement): # use cases and uses the SQL statement in span name correctly as per the spec. # For some very special cases it might not record the correct statement if the SQL # dialect is too weird but in any case it shouldn't break anything. - # Strip leading comments so we get the operation name. - parts.append(self._leading_comment_remover.sub("", statement).split()[0]) + # Strip leading comments so we get the operation name. A statement that + # is truthy but has no tokens left (comment-only or whitespace-only) must + # not raise IndexError; skip adding an operation part in that case. + tokens = self._leading_comment_remover.sub("", statement).split() + if tokens: + parts.append(tokens[0]) if db_name: parts.append(db_name) if not parts: diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py index 023df92101..969750e001 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py @@ -59,6 +59,20 @@ def tearDown(self): super().tearDown() SQLAlchemyInstrumentor().uninstrument() + def test_operation_name_comment_or_whitespace_only(self): + # Regression: a comment-only or whitespace-only statement is truthy but has + # no tokens after leading-comment stripping; _operation_name must not raise + # IndexError and should fall back to the db name / vendor. + engine = create_engine("sqlite:///:memory:") + tracer = self.tracer_provider.get_tracer(__name__) + engine_tracer = EngineTracer(tracer, engine, mock.Mock()) + self.assertEqual( + engine_tracer._operation_name("mydb", "/* comment only */"), "mydb" + ) + self.assertEqual( + engine_tracer._operation_name(None, " "), engine_tracer.vendor + ) + def test_trace_integration(self): engine = create_engine("sqlite:///:memory:") SQLAlchemyInstrumentor().instrument( From 43904aac478d4f182228ca3be4e6d0938c929f2b Mon Sep 17 00:00:00 2001 From: Atishyy27 <142108881+Atishyy27@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:52:20 +0530 Subject: [PATCH 2/2] add changelog fragment for #4943 Signed-off-by: Atishyy27 <142108881+Atishyy27@users.noreply.github.com> --- .changelog/4943.fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changelog/4943.fixed diff --git a/.changelog/4943.fixed b/.changelog/4943.fixed new file mode 100644 index 0000000000..9f5cf38c26 --- /dev/null +++ b/.changelog/4943.fixed @@ -0,0 +1 @@ +`opentelemetry-instrumentation-sqlalchemy`: avoid `IndexError` in `_operation_name` for comment-only or whitespace-only statements