Repository: DataDog/dd-trace-py

Issue:
Instrumenting ambiguity: Integrate with SQLAlchemy or not when underlying psycopg2 used
<!--
Thanks for taking the time for reporting an issue!

Before reporting an issue on dd-trace-py, please be sure to provide all
necessary information.

If you're hitting a bug, make sure that you're using the latest version of this
library.
-->

### Summary of problem

It's not immediately clear from documentation if going through the trouble of patching and instrumenting SQLAlchemy provides any additional details over the auto-instrumented psycopg2 via `ddtrace-run`.

I currently have a Flask app using SQLAlchemy by hand (not Flask-SQLAlchemy) which connects to a Postgres database via psycopg2. Running my app with `ddtrace-run` in gunicorn successfully reports the Flask and Postgres services to APM. However upon seeing that ddtrace additionally has an [integration to SQLAlchemy](https://ddtrace.readthedocs.io/en/v1.7.1/integrations.html#sqlalchemy), I'm curious if it provides any added benefit on top of the auto instrumentation. Is it meant to be complimentary? Or is it meant to be an alternative/replacement mechanism for instrumenting the database/what psycopg2 integration would report.

I ending up debugging into `ddtrace.contrib.sqlalchemy.engine.EngineTracer` in my application to see what `Pin.get_from(self.engine)` would report without any overrides. It gave me:

```
Pin(service=postgres, tags=None, tracer=<ddtrace.tracer.Tracer object at 0xffff8bf3e580>)
```

which leads me to believe manual patching and integrating with SQLAlchemy is redundant if I'm using pscopg2 and `ddtrace-run`. Eyeballing the `EngineTracer` source code _appears_ to indicate it adds no additional benefit over psychopg2's auto-instrumentation.

Documentation should be updated (hell, I'd love a confirmatory answer here 😃 ) on whether or not one should even bother going to the trouble of manually patching SQLAlchemy in this context if they already have/use/configure SQLAlchemy's engine to connect to a postgres DB provided by psycopg2. Something to the effect, in SQLAlchemy's section:

> # SQLAlchemy
> 
> Integrating with SQLAlchemy is not necessary if you're integrating psycopg and SQLAlchemy connects to a Postgres database.
>
> To trace sqlalchemy queries, add instrumentation to the engine class using the patch method that must be called before importing sqlalchemy:
> ...

### Which version of dd-trace-py are you using?

1.7.1

### Which version of pip are you using?

22.3.1

### Which libraries and their versions are you using?

```
Flask==1.1.1
SQLAlchemy==1.3.11
ddtrace==1.7.1
psycopg2-binary==2.9.1
```

### How can we reproduce your problem?

N/A

### What is the result that you get?

N/A

### What is the result that you expected?

N/A


Discussion:
> which leads me to believe manual patching and integrating with SQLAlchemy is redundant if I'm using pscopg2 and ddtrace-run. Eyeballing the EngineTracer source code appears to indicate it adds no additional benefit over psychopg2's auto-instrumentation.

Yup! You have it correct! the integration is there just for if the underlying engine does not have instrumentation. This is why we have it off by default.


I think updating the documentation would be great, is that something you want to contribute?

This is where the docs for SQLAlchemy live: https://github.com/DataDog/dd-trace-py/blob/5728a880b4d7b49b3dfbba987c5f132a127d0b5a/ddtrace/contrib/sqlalchemy/__init__.py#L1

The only caveat I have to your suggestion is this is the same if you use a different but supported database engine as well, like pymysql, mysql-connector-python, etc. So maybe we want something a little more generic:

> Enabling the SQLAlchemy integration is only necessary if there is no instrumentation available for the database engine used.

(.... maybe... ish?)

Resolving patch:
diff --git a/ddtrace/contrib/sqlalchemy/__init__.py b/ddtrace/contrib/sqlalchemy/__init__.py
--- a/ddtrace/contrib/sqlalchemy/__init__.py
+++ b/ddtrace/contrib/sqlalchemy/__init__.py
@@ -1,4 +1,8 @@
 """
+Enabling the SQLAlchemy integration is only necessary if there is no
+instrumentation available or enabled for the underlying database engine (e.g.
+pymysql, psycopg, mysql-connector, etc.).
+
 To trace sqlalchemy queries, add instrumentation to the engine class
 using the patch method that **must be called before** importing sqlalchemy::
 


Test patch: