Skip to content

Commit dbb14af

Browse files
authored
add wrappers for psycopg2's connection/cursor context managers (#580)
this ensures that the connection/cursor used in the context manager are wrapped instances fixes #577
1 parent 8dd1384 commit dbb14af

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
### Bugfixes
77
* fixed an issue with http server_url and `'VERIFY_SERVER_CERT': False` (#570, #578)
8+
* fixed instrumenting of psycopg2 when using their context manager interface (#577, #580)
89
* fixed zerorpc tests (#581)
910

1011
## v5.1.1

elasticapm/instrumentation/packages/psycopg2.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,16 @@ def _bake_sql(self, sql):
5151
def extract_signature(self, sql):
5252
return extract_signature(sql)
5353

54+
def __enter__(self):
55+
return PGCursorProxy(self.__wrapped__.__enter__())
56+
5457

5558
class PGConnectionProxy(ConnectionProxy):
5659
cursor_proxy = PGCursorProxy
5760

61+
def __enter__(self):
62+
return PGConnectionProxy(self.__wrapped__.__enter__())
63+
5864

5965
class Psycopg2Instrumentation(DbApi2Instrumentation):
6066
name = "psycopg2"

tests/instrumentation/psycopg2_tests.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,18 @@
5454
has_postgres_configured = "POSTGRES_DB" in os.environ
5555

5656

57+
def connect_kwargs():
58+
return {
59+
"database": os.environ.get("POSTGRES_DB", "elasticapm_test"),
60+
"user": os.environ.get("POSTGRES_USER", "postgres"),
61+
"host": os.environ.get("POSTGRES_HOST", None),
62+
"port": os.environ.get("POSTGRES_PORT", None),
63+
}
64+
65+
5766
@pytest.yield_fixture(scope="function")
5867
def postgres_connection(request):
59-
conn = psycopg2.connect(
60-
database=os.environ.get("POSTGRES_DB", "elasticapm_test"),
61-
user=os.environ.get("POSTGRES_USER", "postgres"),
62-
host=os.environ.get("POSTGRES_HOST", None),
63-
port=os.environ.get("POSTGRES_PORT", None),
64-
)
68+
conn = psycopg2.connect(**connect_kwargs())
6569
cursor = conn.cursor()
6670
cursor.execute(
6771
"CREATE TABLE test(id int, name VARCHAR(5) NOT NULL);"
@@ -376,3 +380,22 @@ def test_psycopg2_call_stored_procedure(instrument, postgres_connection, elastic
376380
span = elasticapm_client.spans_for_transaction(transactions[0])[0]
377381
assert span["name"] == "squareme()"
378382
assert span["action"] == "exec"
383+
384+
385+
@pytest.mark.integrationtest
386+
@pytest.mark.skipif(not has_postgres_configured, reason="PostgresSQL not configured")
387+
def test_psycopg_context_manager(instrument, elasticapm_client):
388+
elasticapm_client.begin_transaction("test")
389+
with psycopg2.connect(**connect_kwargs()) as conn:
390+
with conn.cursor() as curs:
391+
curs.execute("SELECT 1;")
392+
curs.fetchall()
393+
elasticapm_client.end_transaction("test", "OK")
394+
transactions = elasticapm_client.events[TRANSACTION]
395+
spans = elasticapm_client.spans_for_transaction(transactions[0])
396+
assert len(spans) == 2
397+
assert spans[0]["subtype"] == "postgresql"
398+
assert spans[0]["action"] == "connect"
399+
400+
assert spans[1]["subtype"] == "postgresql"
401+
assert spans[1]["action"] == "query"

0 commit comments

Comments
 (0)