diff --git a/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py index 38a6264c6d..6e9c7b82f1 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py @@ -183,6 +183,7 @@ def _instrument(self, **kwargs: Any): enable_attribute_commenter = kwargs.get( "enable_attribute_commenter", False ) + capture_parameters = kwargs.get("capture_parameters", False) dbapi.wrap_connect( __name__, psycopg, @@ -195,6 +196,7 @@ def _instrument(self, **kwargs: Any): enable_commenter=enable_sqlcommenter, commenter_options=commenter_options, enable_attribute_commenter=enable_attribute_commenter, + capture_parameters=capture_parameters, ) dbapi.wrap_connect( @@ -209,6 +211,7 @@ def _instrument(self, **kwargs: Any): enable_commenter=enable_sqlcommenter, commenter_options=commenter_options, enable_attribute_commenter=enable_attribute_commenter, + capture_parameters=capture_parameters, ) dbapi.wrap_connect( __name__, @@ -222,6 +225,7 @@ def _instrument(self, **kwargs: Any): enable_commenter=enable_sqlcommenter, commenter_options=commenter_options, enable_attribute_commenter=enable_attribute_commenter, + capture_parameters=capture_parameters, ) def _uninstrument(self, **kwargs: Any): diff --git a/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py b/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py index 6c9bcf2d4b..dcc66c84f9 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py @@ -258,6 +258,25 @@ def test_span_name(self): self.assertEqual(spans_list[6].name, "postgresql") self.assertEqual(spans_list[7].name, "--") + def test_span_params_attribute(self): + PsycopgInstrumentor().instrument(capture_parameters=True) + cnx = psycopg.connect(database="test") + query = "SELECT * FROM mytable WHERE myparam1 = %s AND myparam2 = %s" + params = ("test", 42) + + cursor = cnx.cursor() + + cursor.execute(query, params) + spans_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans_list), 1) + self.assertEqual(spans_list[0].name, "SELECT") + assert spans_list[0].attributes is not None + self.assertEqual(spans_list[0].attributes["db.statement"], query) + self.assertEqual( + spans_list[0].attributes["db.statement.parameters"], + str(params) + ) + # pylint: disable=unused-argument def test_not_recording(self): mock_tracer = mock.Mock() @@ -473,6 +492,25 @@ async def test_span_name_async(self): self.assertEqual(spans_list[4].name, "query") self.assertEqual(spans_list[5].name, "query") + async def test_span_params_attribute(self): + PsycopgInstrumentor().instrument(capture_parameters=True) + cnx = await psycopg.AsyncConnection.connect("test") + query = "SELECT * FROM mytable WHERE myparam1 = %s AND myparam2 = %s" + params = ("test", 42) + async with cnx.cursor() as cursor: + + await cursor.execute(query, params) + + spans_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans_list), 1) + self.assertEqual(spans_list[0].name, "SELECT") + assert spans_list[0].attributes is not None + self.assertEqual(spans_list[0].attributes["db.statement"], query) + self.assertEqual( + spans_list[0].attributes["db.statement.parameters"], + str(params) + ) + # pylint: disable=unused-argument async def test_not_recording_async(self): mock_tracer = mock.Mock()