Skip to content

Commit 3bc68cf

Browse files
ridhahaotianw465
authored andcommitted
Add patch support for pg8000 (Pure python driver) (#115)
* Add patch support for pg8000 * pg8000: add unpatch
1 parent 3b2df2a commit 3bc68cf

File tree

7 files changed

+120
-1
lines changed

7 files changed

+120
-1
lines changed

aws_xray_sdk/core/patcher.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'httplib',
1313
'pymongo',
1414
'psycopg2',
15+
'pg8000',
1516
)
1617

1718
NO_DOUBLE_PATCH = (
@@ -22,6 +23,7 @@
2223
'mysql',
2324
'pymongo',
2425
'psycopg2',
26+
'pg8000',
2527
)
2628

2729
_PATCHED_MODULES = set()

aws_xray_sdk/ext/pg8000/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .patch import patch, unpatch
2+
3+
4+
__all__ = ['patch', 'unpatch']

aws_xray_sdk/ext/pg8000/patch.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import pg8000
2+
import wrapt
3+
4+
from aws_xray_sdk.ext.dbapi2 import XRayTracedConn
5+
from aws_xray_sdk.core.patcher import _PATCHED_MODULES
6+
from aws_xray_sdk.ext.util import unwrap
7+
8+
9+
def patch():
10+
11+
wrapt.wrap_function_wrapper(
12+
'pg8000',
13+
'connect',
14+
_xray_traced_connect
15+
)
16+
17+
18+
def _xray_traced_connect(wrapped, instance, args, kwargs):
19+
20+
conn = wrapped(*args, **kwargs)
21+
meta = {
22+
'database_type': 'PostgreSQL',
23+
'user': conn.user.decode('utf-8'),
24+
'driver_version': 'Pg8000'
25+
}
26+
27+
if hasattr(conn, '_server_version'):
28+
version = getattr(conn, '_server_version')
29+
if version:
30+
meta['database_version'] = str(version)
31+
32+
return XRayTracedConn(conn, meta)
33+
34+
35+
def unpatch():
36+
"""
37+
Unpatch any previously patched modules.
38+
This operation is idempotent.
39+
"""
40+
_PATCHED_MODULES.discard('pg8000')
41+
unwrap(pg8000, 'connect')

tests/ext/pg8000/__init__.py

Whitespace-only changes.

tests/ext/pg8000/test_pg8000.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import pg8000
2+
3+
import pytest
4+
import testing.postgresql
5+
6+
from aws_xray_sdk.core import patch
7+
from aws_xray_sdk.core import xray_recorder
8+
from aws_xray_sdk.core.context import Context
9+
from aws_xray_sdk.ext.pg8000 import unpatch
10+
11+
12+
@pytest.fixture(autouse=True)
13+
def construct_ctx():
14+
"""
15+
Clean up context storage on each test run and begin a segment
16+
so that later subsegment can be attached. After each test run
17+
it cleans up context storage again.
18+
"""
19+
patch(('pg8000',))
20+
xray_recorder.configure(service='test', sampling=False, context=Context())
21+
xray_recorder.clear_trace_entities()
22+
xray_recorder.begin_segment('name')
23+
yield
24+
xray_recorder.clear_trace_entities()
25+
unpatch()
26+
27+
28+
def test_execute_dsn_kwargs():
29+
q = 'SELECT 1'
30+
with testing.postgresql.Postgresql() as postgresql:
31+
dsn = postgresql.dsn()
32+
conn = pg8000.connect(database=dsn['database'],
33+
user=dsn['user'],
34+
password='',
35+
host=dsn['host'],
36+
port=dsn['port'])
37+
cur = conn.cursor()
38+
cur.execute(q)
39+
40+
subsegment = xray_recorder.current_segment().subsegments[-1]
41+
assert subsegment.name == 'execute'
42+
sql = subsegment.sql
43+
assert sql['database_type'] == 'PostgreSQL'
44+
assert sql['user'] == dsn['user']
45+
assert sql['database_version']
46+
47+
48+
def test_execute_bad_query():
49+
q = 'SELECT blarg'
50+
with testing.postgresql.Postgresql() as postgresql:
51+
dsn = postgresql.dsn()
52+
conn = pg8000.connect(database=dsn['database'],
53+
user=dsn['user'],
54+
password='',
55+
host=dsn['host'],
56+
port=dsn['port'])
57+
cur = conn.cursor()
58+
try:
59+
cur.execute(q)
60+
except Exception:
61+
pass
62+
63+
subsegment = xray_recorder.current_segment().subsegments[-1]
64+
assert subsegment.name == 'execute'
65+
sql = subsegment.sql
66+
assert sql['database_type'] == 'PostgreSQL'
67+
assert sql['user'] == dsn['user']
68+
assert sql['database_version']
69+
70+
exception = subsegment.cause['exceptions'][0]
71+
assert exception.type == 'ProgrammingError'

tests/ext/psycopg2/test_psycopg2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,4 @@ def test_register_extensions():
157157
' port=' + str(dsn['port']) +
158158
' user=' + dsn['user'])
159159
assert psycopg2.extras.register_uuid(None, conn)
160-
assert psycopg2.extras.register_uuid(None, conn.cursor())
160+
assert psycopg2.extras.register_uuid(None, conn.cursor())

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ deps =
2020
django >= 1.10, <2.0
2121
pynamodb >= 3.3.1
2222
psycopg2
23+
pg8000
2324
testing.postgresql
2425

2526
# Python2 only deps

0 commit comments

Comments
 (0)