Skip to content

Commit 57b8106

Browse files
authored
Fix AttributeError: __aexit__ for aiopg.connect and aiopg.create_pool (#235)
1 parent cb01a6b commit 57b8106

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5353
([#259](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/259))
5454
- `opentelemetry-exporter-datadog` Fix unintentional type change of span trace flags
5555
([#261](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/261))
56+
- `opentelemetry-instrumentation-aiopg` Fix AttributeError `__aexit__` when `aiopg.connect` and `aio[g].create_pool` used with async context manager
57+
([#235](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/235))
5658

5759
## [0.16b1](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.16b1) - 2020-11-26
5860

instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import aiopg
3636
import wrapt
37+
from aiopg.utils import _ContextManager, _PoolContextManager
3738

3839
from opentelemetry.instrumentation.aiopg.aiopg_integration import (
3940
AiopgIntegration,
@@ -99,7 +100,7 @@ def wrap_connect(
99100
"""
100101

101102
# pylint: disable=unused-argument
102-
async def wrap_connect_(
103+
def wrap_connect_(
103104
wrapped: typing.Callable[..., typing.Any],
104105
instance: typing.Any,
105106
args: typing.Tuple[typing.Any, typing.Any],
@@ -113,7 +114,9 @@ async def wrap_connect_(
113114
version=version,
114115
tracer_provider=tracer_provider,
115116
)
116-
return await db_integration.wrapped_connection(wrapped, args, kwargs)
117+
return _ContextManager(
118+
db_integration.wrapped_connection(wrapped, args, kwargs)
119+
)
117120

118121
try:
119122
wrapt.wrap_function_wrapper(aiopg, "connect", wrap_connect_)
@@ -191,7 +194,7 @@ def wrap_create_pool(
191194
tracer_provider: typing.Optional[TracerProvider] = None,
192195
):
193196
# pylint: disable=unused-argument
194-
async def wrap_create_pool_(
197+
def wrap_create_pool_(
195198
wrapped: typing.Callable[..., typing.Any],
196199
instance: typing.Any,
197200
args: typing.Tuple[typing.Any, typing.Any],
@@ -205,7 +208,9 @@ async def wrap_create_pool_(
205208
version=version,
206209
tracer_provider=tracer_provider,
207210
)
208-
return await db_integration.wrapped_pool(wrapped, args, kwargs)
211+
return _PoolContextManager(
212+
db_integration.wrapped_pool(wrapped, args, kwargs)
213+
)
209214

210215
try:
211216
wrapt.wrap_function_wrapper(aiopg, "create_pool", wrap_create_pool_)

instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py

+50
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,26 @@ def test_instrumentor_connect(self):
7979
spans_list = self.memory_exporter.get_finished_spans()
8080
self.assertEqual(len(spans_list), 1)
8181

82+
def test_instrumentor_connect_ctx_manager(self):
83+
async def _ctx_manager_connect():
84+
AiopgInstrumentor().instrument()
85+
86+
async with aiopg.connect(database="test") as cnx:
87+
async with cnx.cursor() as cursor:
88+
query = "SELECT * FROM test"
89+
await cursor.execute(query)
90+
91+
spans_list = self.memory_exporter.get_finished_spans()
92+
self.assertEqual(len(spans_list), 1)
93+
span = spans_list[0]
94+
95+
# Check version and name in span's instrumentation info
96+
self.check_span_instrumentation_info(
97+
span, opentelemetry.instrumentation.aiopg
98+
)
99+
100+
async_call(_ctx_manager_connect())
101+
82102
def test_instrumentor_create_pool(self):
83103
AiopgInstrumentor().instrument()
84104

@@ -110,6 +130,27 @@ def test_instrumentor_create_pool(self):
110130
spans_list = self.memory_exporter.get_finished_spans()
111131
self.assertEqual(len(spans_list), 1)
112132

133+
def test_instrumentor_create_pool_ctx_manager(self):
134+
async def _ctx_manager_pool():
135+
AiopgInstrumentor().instrument()
136+
137+
async with aiopg.create_pool(database="test") as pool:
138+
async with pool.acquire() as cnx:
139+
async with cnx.cursor() as cursor:
140+
query = "SELECT * FROM test"
141+
await cursor.execute(query)
142+
143+
spans_list = self.memory_exporter.get_finished_spans()
144+
self.assertEqual(len(spans_list), 1)
145+
span = spans_list[0]
146+
147+
# Check version and name in span's instrumentation info
148+
self.check_span_instrumentation_info(
149+
span, opentelemetry.instrumentation.aiopg
150+
)
151+
152+
async_call(_ctx_manager_pool())
153+
113154
def test_custom_tracer_provider_connect(self):
114155
resource = resources.Resource.create({})
115156
result = self.create_tracer_provider(resource=resource)
@@ -428,6 +469,12 @@ async def _acquire(self):
428469
)
429470
return connect
430471

472+
def close(self):
473+
pass
474+
475+
async def wait_closed(self):
476+
pass
477+
431478

432479
class MockPsycopg2Connection:
433480
def __init__(self, database, server_port, server_host, user):
@@ -471,6 +518,9 @@ async def callproc(self, query, params=None, throw_exception=False):
471518
if throw_exception:
472519
raise Exception("Test Exception")
473520

521+
def close(self):
522+
pass
523+
474524

475525
class AiopgConnectionMock:
476526
_conn = MagicMock()

0 commit comments

Comments
 (0)