Skip to content

Commit 302ffe2

Browse files
StefanoOvusxrmx
andauthored
missing capture_parameters in instrumentation psycopg (open-telemetry#3676)
* missing capture_parameters in instrumentation psycopg * added tests for psycopg capture params * add changelog * ruff format * rebase, mod changelog unreleased * Update CHANGELOG.md --------- Co-authored-by: Riccardo Magliocchetti <[email protected]>
1 parent 9f393c7 commit 302ffe2

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
([#3777](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3777))
2727
- `opentelemetry-exporter-credential-provider-gcp`: create this package which provides support for supplying your machine's Application Default
2828
Credentials (https://cloud.google.com/docs/authentication/application-default-credentials) to the OTLP Exporters created automatically by OpenTelemetry Python's auto instrumentation. These credentials authorize OTLP traces to be sent to `telemetry.googleapis.com`. [#3766](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3766).
29+
- `opentelemetry-instrumentation-psycopg` Add missing parameter `capture_parameters` to instrumentor.
30+
([#3676](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3676))
2931

3032
## Version 1.37.0/0.58b0 (2025-09-11)
3133

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def _instrument(self, **kwargs: Any):
184184
enable_attribute_commenter = kwargs.get(
185185
"enable_attribute_commenter", False
186186
)
187+
capture_parameters = kwargs.get("capture_parameters", False)
187188
dbapi.wrap_connect(
188189
__name__,
189190
psycopg,
@@ -196,6 +197,7 @@ def _instrument(self, **kwargs: Any):
196197
enable_commenter=enable_sqlcommenter,
197198
commenter_options=commenter_options,
198199
enable_attribute_commenter=enable_attribute_commenter,
200+
capture_parameters=capture_parameters,
199201
)
200202

201203
dbapi.wrap_connect(
@@ -210,6 +212,7 @@ def _instrument(self, **kwargs: Any):
210212
enable_commenter=enable_sqlcommenter,
211213
commenter_options=commenter_options,
212214
enable_attribute_commenter=enable_attribute_commenter,
215+
capture_parameters=capture_parameters,
213216
)
214217
dbapi.wrap_connect(
215218
__name__,
@@ -223,6 +226,7 @@ def _instrument(self, **kwargs: Any):
223226
enable_commenter=enable_sqlcommenter,
224227
commenter_options=commenter_options,
225228
enable_attribute_commenter=enable_attribute_commenter,
229+
capture_parameters=capture_parameters,
226230
)
227231

228232
def _uninstrument(self, **kwargs: Any):

instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,24 @@ def test_span_name(self):
264264
self.assertEqual(spans_list[6].name, "postgresql")
265265
self.assertEqual(spans_list[7].name, "--")
266266

267+
def test_span_params_attribute(self):
268+
PsycopgInstrumentor().instrument(capture_parameters=True)
269+
cnx = psycopg.connect(database="test")
270+
query = "SELECT * FROM mytable WHERE myparam1 = %s AND myparam2 = %s"
271+
params = ("test", 42)
272+
273+
cursor = cnx.cursor()
274+
275+
cursor.execute(query, params)
276+
spans_list = self.memory_exporter.get_finished_spans()
277+
self.assertEqual(len(spans_list), 1)
278+
self.assertEqual(spans_list[0].name, "SELECT")
279+
assert spans_list[0].attributes is not None
280+
self.assertEqual(spans_list[0].attributes["db.statement"], query)
281+
self.assertEqual(
282+
spans_list[0].attributes["db.statement.parameters"], str(params)
283+
)
284+
267285
# pylint: disable=unused-argument
268286
def test_not_recording(self):
269287
mock_tracer = mock.Mock()
@@ -479,6 +497,23 @@ async def test_span_name_async(self):
479497
self.assertEqual(spans_list[4].name, "query")
480498
self.assertEqual(spans_list[5].name, "query")
481499

500+
async def test_span_params_attribute(self):
501+
PsycopgInstrumentor().instrument(capture_parameters=True)
502+
cnx = await psycopg.AsyncConnection.connect("test")
503+
query = "SELECT * FROM mytable WHERE myparam1 = %s AND myparam2 = %s"
504+
params = ("test", 42)
505+
async with cnx.cursor() as cursor:
506+
await cursor.execute(query, params)
507+
508+
spans_list = self.memory_exporter.get_finished_spans()
509+
self.assertEqual(len(spans_list), 1)
510+
self.assertEqual(spans_list[0].name, "SELECT")
511+
assert spans_list[0].attributes is not None
512+
self.assertEqual(spans_list[0].attributes["db.statement"], query)
513+
self.assertEqual(
514+
spans_list[0].attributes["db.statement.parameters"], str(params)
515+
)
516+
482517
# pylint: disable=unused-argument
483518
async def test_not_recording_async(self):
484519
mock_tracer = mock.Mock()

0 commit comments

Comments
 (0)