Skip to content

Commit 6b000f4

Browse files
committed
opentelemetry-instrumentation-pymongo: fix invalid mongodb collection attribute type
1 parent 3b97e36 commit 6b000f4

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def started(self, event: monitoring.CommandStartedEvent):
138138
command_name = event.command_name
139139
span_name = f"{event.database_name}.{command_name}"
140140
statement = self._get_statement_by_command_name(command_name, event)
141-
collection = event.command.get(event.command_name)
141+
collection = _get_command_collection_name(event)
142142

143143
try:
144144
span = self._tracer.start_span(span_name, kind=SpanKind.CLIENT)
@@ -226,6 +226,19 @@ def _get_statement_by_command_name(
226226
return statement
227227

228228

229+
def _get_command_collection_name(event: CommandEvent) -> str | None:
230+
collection_name = event.command.get(event.command_name)
231+
if (
232+
not collection_name
233+
or not isinstance(collection_name, str)
234+
or ".." in collection_name
235+
or collection_name[0] == "."
236+
or collection_name[-1] == "."
237+
):
238+
return None
239+
return collection_name
240+
241+
229242
def _get_span_dict_key(
230243
event: CommandEvent,
231244
) -> int | tuple[int, tuple[str, int | None]]:

instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,46 @@ def test_capture_statement_disabled_aggregate(self):
278278
span.attributes[SpanAttributes.DB_STATEMENT], "aggregate"
279279
)
280280

281+
def test_collection_name_attribute(self):
282+
scenarios = [
283+
(
284+
{
285+
"command_name": "find",
286+
"find": "test_collection",
287+
},
288+
"test_collection",
289+
),
290+
({"command_name": "find"}, None),
291+
({"command_name": "find", "find": b'invalid'}, None),
292+
({"command_name": "find", "find": ".invalid"}, None),
293+
({"command_name": "find", "find": "invalid."}, None),
294+
({"command_name": "find", "find": "invalid..invalid"}, None),
295+
]
296+
for command_attrs, expected in scenarios:
297+
with self.subTest(command_attrs=command_attrs, expected=expected):
298+
mock_event = MockEvent(command_attrs)
299+
300+
command_tracer = CommandTracer(
301+
self.tracer, capture_statement=True
302+
)
303+
command_tracer.started(event=mock_event)
304+
command_tracer.succeeded(event=mock_event)
305+
306+
spans_list = self.memory_exporter.get_finished_spans()
307+
308+
self.assertEqual(len(spans_list), 1)
309+
span = spans_list[0]
310+
311+
self.assertEqual(
312+
span.attributes[SpanAttributes.DB_STATEMENT], "find"
313+
)
314+
315+
self.assertEqual(
316+
span.attributes.get(SpanAttributes.DB_MONGODB_COLLECTION),
317+
expected,
318+
)
319+
self.memory_exporter.clear()
320+
281321

282322
class MockCommand:
283323
def __init__(self, command_attrs):

0 commit comments

Comments
 (0)