Skip to content

Commit 5570ed9

Browse files
committed
feat(tortoiseorm): replace db.statement.parameters with db.query.parameter.<key>
tortoiseorm has its own parameter capture implementation independent of dbapi. Update it to use the shared `db_query_parameter_attributes` helper and emit individual `db.query.parameter.<key>` attributes.
1 parent 42554e1 commit 5570ed9

2 files changed

Lines changed: 32 additions & 7 deletions

File tree

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from opentelemetry.instrumentation.tortoiseorm.package import _instruments
5050
from opentelemetry.instrumentation.tortoiseorm.version import __version__
5151
from opentelemetry.instrumentation.utils import (
52+
db_query_parameter_attributes,
5253
is_instrumentation_enabled,
5354
unwrap,
5455
)
@@ -268,7 +269,9 @@ def _hydrate_span_from_args(self, connection, query, parameters) -> dict:
268269

269270
if self.capture_parameters:
270271
if parameters is not None and len(parameters) > 0:
271-
span_attributes["db.statement.parameters"] = str(parameters)
272+
span_attributes.update(
273+
db_query_parameter_attributes(parameters)
274+
)
272275

273276
return span_attributes
274277

@@ -286,7 +289,7 @@ async def _do_execute(self, func, instance, args, kwargs):
286289
span_attributes = self._hydrate_span_from_args(
287290
instance,
288291
args[0],
289-
args[1:],
292+
args[1] if len(args) > 1 else None,
290293
)
291294
for attribute, value in span_attributes.items():
292295
span.set_attribute(attribute, value)

instrumentation/opentelemetry-instrumentation-tortoiseorm/tests/test_tortoiseorm_instrumentation.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from opentelemetry.instrumentation.utils import suppress_instrumentation
2222
from opentelemetry.semconv._incubating.attributes.db_attributes import (
2323
DB_NAME,
24+
DB_QUERY_PARAMETER_TEMPLATE,
2425
DB_STATEMENT,
2526
DB_SYSTEM,
2627
)
@@ -30,6 +31,7 @@
3031
class MockModel(models.Model):
3132
id = fields.IntField(pk=True)
3233
name = fields.TextField()
34+
description = fields.TextField(default="")
3335

3436
def __str__(self):
3537
return self.name
@@ -87,15 +89,35 @@ def test_capture_parameters(self):
8789

8890
async def run():
8991
await self._init_tortoise()
90-
await MockModel.create(name="Test Parameterized")
92+
await MockModel.create(
93+
name="Test Capture Params", description="Multiple Params"
94+
)
9195

9296
self._async_call(run())
9397
spans = self.memory_exporter.get_finished_spans()
9498
insert_span = next(s for s in spans if s.name == "INSERT")
95-
self.assertIn("db.statement.parameters", insert_span.attributes)
96-
self.assertIn(
97-
"Test Parameterized",
98-
insert_span.attributes["db.statement.parameters"],
99+
self.assertEqual(
100+
insert_span.attributes[f"{DB_QUERY_PARAMETER_TEMPLATE}.0"],
101+
"'Test Capture Params'",
102+
)
103+
self.assertEqual(
104+
insert_span.attributes[f"{DB_QUERY_PARAMETER_TEMPLATE}.1"],
105+
"'Multiple Params'",
106+
)
107+
108+
def test_capture_no_parameters(self):
109+
TortoiseORMInstrumentor().uninstrument()
110+
TortoiseORMInstrumentor().instrument(capture_parameters=True)
111+
112+
async def run():
113+
await self._init_tortoise()
114+
await MockModel.all()
115+
116+
self._async_call(run())
117+
spans = self.memory_exporter.get_finished_spans()
118+
select_span = next(s for s in spans if s.name == "SELECT")
119+
self.assertNotIn(
120+
f"{DB_QUERY_PARAMETER_TEMPLATE}.0", select_span.attributes
99121
)
100122

101123
def test_uninstrument(self):

0 commit comments

Comments
 (0)