Repository: open-telemetry/opentelemetry-python-contrib

Issue:
SQLAlchemy Instrumentation: `enable_commenter` can't be disabled.
Based on the [documentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/sqlalchemy/sqlalchemy.html#usage), you'd assume that:

```python
SQLAlchemyInstrumentor().instrument(enable_commenter=False)
```

Would enable instrumentation but disable the statement commenter, but it doesn't work. It looks like you can't disable the sql commenter unless you are providing the `engine` keyword as well, which requires you to have already created the engine at that point in your code path.

It looks like the `enable_commenter` and related kwargs need to be passed to the `_wrap_create_engine` function?


Discussion:
>It looks like the enable_commenter and related kwargs need to be passed to the _wrap_create_engine function?

Correct, and pass it to `EngineTracer` which enables commenter by default.
hi, can you assign this to me? thanks :)

Resolving patch:
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py
@@ -136,11 +136,16 @@ def _instrument(self, **kwargs):
             An instrumented engine if passed in as an argument or list of instrumented engines, None otherwise.
         """
         tracer_provider = kwargs.get("tracer_provider")
-        _w("sqlalchemy", "create_engine", _wrap_create_engine(tracer_provider))
+        enable_commenter = kwargs.get("enable_commenter", False)
+        _w(
+            "sqlalchemy",
+            "create_engine",
+            _wrap_create_engine(tracer_provider, enable_commenter),
+        )
         _w(
             "sqlalchemy.engine",
             "create_engine",
-            _wrap_create_engine(tracer_provider),
+            _wrap_create_engine(tracer_provider, enable_commenter),
         )
         _w(
             "sqlalchemy.engine.base",
@@ -151,7 +156,7 @@ def _instrument(self, **kwargs):
             _w(
                 "sqlalchemy.ext.asyncio",
                 "create_async_engine",
-                _wrap_create_async_engine(tracer_provider),
+                _wrap_create_async_engine(tracer_provider, enable_commenter),
             )
         if kwargs.get("engine") is not None:
             return EngineTracer(
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
+++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
@@ -49,27 +49,29 @@ def _get_tracer(tracer_provider=None):
     )
 
 
-def _wrap_create_async_engine(tracer_provider=None):
+def _wrap_create_async_engine(tracer_provider=None, enable_commenter=False):
     # pylint: disable=unused-argument
     def _wrap_create_async_engine_internal(func, module, args, kwargs):
         """Trace the SQLAlchemy engine, creating an `EngineTracer`
         object that will listen to SQLAlchemy events.
         """
         engine = func(*args, **kwargs)
-        EngineTracer(_get_tracer(tracer_provider), engine.sync_engine)
+        EngineTracer(
+            _get_tracer(tracer_provider), engine.sync_engine, enable_commenter
+        )
         return engine
 
     return _wrap_create_async_engine_internal
 
 
-def _wrap_create_engine(tracer_provider=None):
+def _wrap_create_engine(tracer_provider=None, enable_commenter=False):
     # pylint: disable=unused-argument
     def _wrap_create_engine_internal(func, module, args, kwargs):
         """Trace the SQLAlchemy engine, creating an `EngineTracer`
         object that will listen to SQLAlchemy events.
         """
         engine = func(*args, **kwargs)
-        EngineTracer(_get_tracer(tracer_provider), engine)
+        EngineTracer(_get_tracer(tracer_provider), engine, enable_commenter)
         return engine
 
     return _wrap_create_engine_internal
@@ -94,7 +96,7 @@ def _wrap_connect_internal(func, module, args, kwargs):
 
 class EngineTracer:
     def __init__(
-        self, tracer, engine, enable_commenter=True, commenter_options=None
+        self, tracer, engine, enable_commenter=False, commenter_options=None
     ):
         self.tracer = tracer
         self.engine = engine


Test patch:
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
+++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
@@ -77,3 +77,30 @@ def test_sqlcommenter_flask_integration(self):
             self.caplog.records[-2].getMessage(),
             r"SELECT  1 /\*db_driver='(.*)',flask=1,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
         )
+
+    def test_sqlcommenter_enabled_create_engine_after_instrumentation(self):
+        SQLAlchemyInstrumentor().instrument(
+            tracer_provider=self.tracer_provider,
+            enable_commenter=True,
+        )
+        from sqlalchemy import create_engine  # pylint: disable-all
+
+        engine = create_engine("sqlite:///:memory:")
+        cnx = engine.connect()
+        cnx.execute("SELECT 1;").fetchall()
+        self.assertRegex(
+            self.caplog.records[-2].getMessage(),
+            r"SELECT 1 /\*db_driver='(.*)',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
+        )
+
+    def test_sqlcommenter_disabled_create_engine_after_instrumentation(self):
+        SQLAlchemyInstrumentor().instrument(
+            tracer_provider=self.tracer_provider,
+            enable_commenter=False,
+        )
+        from sqlalchemy import create_engine  # pylint: disable-all
+
+        engine = create_engine("sqlite:///:memory:")
+        cnx = engine.connect()
+        cnx.execute("SELECT 1;").fetchall()
+        self.assertEqual(self.caplog.records[-2].getMessage(), "SELECT 1;")