Skip to content

Commit e8d47bf

Browse files
Rm instrument_connection is-instrumented check; use dict to store cnx
1 parent a2fa981 commit e8d47bf

File tree

2 files changed

+40
-44
lines changed

2 files changed

+40
-44
lines changed

instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class Psycopg2Instrumentor(BaseInstrumentor):
146146

147147
_DATABASE_SYSTEM = "postgresql"
148148

149-
_otel_cursor_factory = None
149+
_otel_cursor_factories = {}
150150

151151
def instrumentation_dependencies(self) -> Collection[str]:
152152
return _instruments
@@ -193,30 +193,25 @@ def instrument_connection(
193193
Returns:
194194
An instrumented psycopg2 connection object.
195195
"""
196-
if self._is_instrumented_by_opentelemetry:
197-
# _instrument (via BaseInstrumentor) or instrument_connection (this)
198-
# was already called
199-
_logger.warning(
200-
"Attempting to instrument Psycopg2 connection while already instrumented"
201-
)
202-
self._is_instrumented_by_opentelemetry = True
203-
return connection
196+
# TODO Add check for attempt to instrument a connection when already instrumented
197+
# https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3138
204198

205-
# Save cursor_factory at instrumentor level because
199+
# Save cursor_factory in instrumentor map because
206200
# psycopg2 connection type does not allow arbitrary attrs
207-
self._otel_cursor_factory = connection.cursor_factory
201+
self._otel_cursor_factories[connection] = connection.cursor_factory
208202
connection.cursor_factory = _new_cursor_factory(
209203
base_factory=connection.cursor_factory,
210204
tracer_provider=tracer_provider,
211205
)
212-
self._is_instrumented_by_opentelemetry = True
206+
_logger.warning("factories: %s", self._otel_cursor_factories)
213207

214208
return connection
215209

216210
# TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql
217211
def uninstrument_connection(self, connection):
218-
self._is_instrumented_by_opentelemetry = False
219-
connection.cursor_factory = self._otel_cursor_factory
212+
connection.cursor_factory = self._otel_cursor_factories.pop(
213+
connection, None
214+
)
220215
return connection
221216

222217

instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from unittest import mock
1717

1818
import psycopg2
19-
import pytest
2019

2120
import opentelemetry.instrumentation.psycopg2
2221
from opentelemetry import trace
@@ -69,10 +68,6 @@ def get_dsn_parameters(self): # pylint: disable=no-self-use
6968

7069

7170
class TestPostgresqlIntegration(TestBase):
72-
@pytest.fixture(autouse=True)
73-
def inject_fixtures(self, caplog):
74-
self.caplog = caplog # pylint: disable=attribute-defined-outside-init
75-
7671
def setUp(self):
7772
super().setUp()
7873
self.cursor_mock = mock.patch(
@@ -200,9 +195,8 @@ def test_instrument_connection(self):
200195
instrumentor = Psycopg2Instrumentor()
201196
original_cursor_factory = cnx.cursor_factory
202197
cnx = instrumentor.instrument_connection(cnx)
203-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
204198
self.assertEqual(
205-
instrumentor._otel_cursor_factory, original_cursor_factory
199+
instrumentor._otel_cursor_factories[cnx], original_cursor_factory
206200
)
207201
cursor = cnx.cursor()
208202
cursor.execute(query)
@@ -222,22 +216,27 @@ def test_instrument_connection_with_instrument(self):
222216

223217
instrumentor = Psycopg2Instrumentor()
224218
instrumentor.instrument()
225-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
226219

227220
cnx = psycopg2.connect(database="test")
221+
original_cursor_factory = cnx.cursor_factory
222+
orig_cnx = cnx
228223
cnx = Psycopg2Instrumentor().instrument_connection(cnx)
224+
225+
# TODO Should not set cursor_factory if already instrumented
226+
# https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3138
227+
# self.assertEqual(instrumentor._otel_cursor_factories[cnx], None)
229228
self.assertEqual(
230-
self.caplog.records[0].getMessage(),
231-
"Attempting to instrument Psycopg2 connection while already instrumented",
229+
instrumentor._otel_cursor_factories.get(orig_cnx),
230+
original_cursor_factory,
232231
)
233-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
234-
# Will not set cursor_factory if already instrumented
235-
self.assertEqual(instrumentor._otel_cursor_factory, None)
236232
cursor = cnx.cursor()
237233
cursor.execute(query)
238234

239235
spans_list = self.memory_exporter.get_finished_spans()
240-
self.assertEqual(len(spans_list), 1)
236+
# TODO Add check for attempt to instrument a connection when already instrumented
237+
# https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3138
238+
# self.assertEqual(len(spans_list), 1)
239+
self.assertEqual(len(spans_list), 2)
241240

242241
def test_instrument_connection_with_instrument_connection(self):
243242
cnx = psycopg2.connect(database="test")
@@ -251,26 +250,29 @@ def test_instrument_connection_with_instrument_connection(self):
251250
cnx = psycopg2.connect(database="test")
252251
original_cursor_factory = cnx.cursor_factory
253252
instrumentor = Psycopg2Instrumentor()
253+
orig_cnx = cnx
254254
cnx = instrumentor.instrument_connection(cnx)
255-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
256255
self.assertEqual(
257-
instrumentor._otel_cursor_factory, original_cursor_factory
256+
instrumentor._otel_cursor_factories.get(orig_cnx),
257+
original_cursor_factory,
258258
)
259259

260-
cnx = Psycopg2Instrumentor().instrument_connection(cnx)
261-
self.assertEqual(
262-
self.caplog.records[0].getMessage(),
263-
"Attempting to instrument Psycopg2 connection while already instrumented",
264-
)
265-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
260+
orig_cnx = cnx
261+
original_cursor_factory = cnx.cursor_factory
262+
instrumentor = Psycopg2Instrumentor()
263+
cnx = instrumentor.instrument_connection(cnx)
266264
self.assertEqual(
267-
instrumentor._otel_cursor_factory, original_cursor_factory
265+
instrumentor._otel_cursor_factories.get(orig_cnx),
266+
original_cursor_factory,
268267
)
269268
cursor = cnx.cursor()
270269
cursor.execute(query)
271270

272271
spans_list = self.memory_exporter.get_finished_spans()
273-
self.assertEqual(len(spans_list), 1)
272+
# TODO Add check for attempt to instrument a connection when already instrumented
273+
# https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3138
274+
# self.assertEqual(len(spans_list), 1)
275+
self.assertEqual(len(spans_list), 2)
274276

275277
# pylint: disable=unused-argument
276278
def test_uninstrument_connection_with_instrument(self):
@@ -283,15 +285,13 @@ def test_uninstrument_connection_with_instrument(self):
283285

284286
spans_list = self.memory_exporter.get_finished_spans()
285287
self.assertEqual(len(spans_list), 1)
286-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
287288

288289
cnx = Psycopg2Instrumentor().uninstrument_connection(cnx)
289290
cursor = cnx.cursor()
290291
cursor.execute(query)
291292

292293
spans_list = self.memory_exporter.get_finished_spans()
293294
self.assertEqual(len(spans_list), 1)
294-
self.assertFalse(instrumentor._is_instrumented_by_opentelemetry)
295295

296296
# pylint: disable=unused-argument
297297
def test_uninstrument_connection_with_instrument_connection(self):
@@ -305,19 +305,20 @@ def test_uninstrument_connection_with_instrument_connection(self):
305305

306306
spans_list = self.memory_exporter.get_finished_spans()
307307
self.assertEqual(len(spans_list), 1)
308-
self.assertTrue(instrumentor._is_instrumented_by_opentelemetry)
309308
self.assertEqual(
310-
instrumentor._otel_cursor_factory, original_cursor_factory
309+
instrumentor._otel_cursor_factories[cnx], original_cursor_factory
311310
)
312311

312+
orig_cnx = cnx
313313
cnx = Psycopg2Instrumentor().uninstrument_connection(cnx)
314314
cursor = cnx.cursor()
315315
cursor.execute(query)
316316

317317
spans_list = self.memory_exporter.get_finished_spans()
318318
self.assertEqual(len(spans_list), 1)
319-
self.assertFalse(instrumentor._is_instrumented_by_opentelemetry)
320-
self.assertEqual(instrumentor._otel_cursor_factory, None)
319+
self.assertEqual(
320+
instrumentor._otel_cursor_factories.get(orig_cnx), None
321+
)
321322

322323
@mock.patch("opentelemetry.instrumentation.dbapi.wrap_connect")
323324
def test_sqlcommenter_enabled(self, event_mocked):

0 commit comments

Comments
 (0)