Skip to content

Commit f134b47

Browse files
committed
PYTHON-6036 Trim the unified tracing runner comments and docstrings
Cut each to the invariant a reader needs, dropping spec references and restatements of the code.
1 parent 96127ac commit f134b47

3 files changed

Lines changed: 32 additions & 82 deletions

File tree

test/asynchronous/unified_format.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,8 @@ def __init__(self, test_class):
242242
self._entities: dict[str, Any] = {}
243243
self._listeners: dict[str, EventListenerUtil] = {}
244244
self._session_lsids: dict[str, Mapping[str, Any]] = {}
245-
# The id of the (at most one, today) client entity created with
246-
# observeTracingMessages. Spans carry no attribute identifying which
247-
# client emitted them, so multi-client tracing correlation isn't
248-
# supported; _create_entity fails loudly if a second one appears.
245+
# The one client entity created with observeTracingMessages. Spans carry
246+
# no attribute identifying their client, so a second one is rejected.
249247
self._tracing_client_id: Optional[str] = None
250248
self.test: UnifiedSpecTestMixinV1 = test_class
251249

@@ -341,9 +339,7 @@ async def _create_entity(self, entity_spec, uri=None):
341339
enable_payload = observe_tracing.get("enableCommandPayload", False)
342340
kwargs["tracing"] = {
343341
"enabled": True,
344-
# Tests asserting db.query.text match the full, untruncated
345-
# command, so an effectively-unlimited length avoids
346-
# truncating and failing that assertion.
342+
# Tests match the full command, so never truncate.
347343
"query_text_max_length": 1_000_000 if enable_payload else None,
348344
}
349345

@@ -564,10 +560,8 @@ async def insert_initial_data(self, initial_data):
564560

565561
@classmethod
566562
def setUpClass(cls) -> None:
567-
# Only register a span exporter (and the shared SDK TracerProvider it
568-
# depends on) for test files that actually use observeTracingMessages,
569-
# to avoid needlessly accumulating span processors on the process-wide
570-
# provider for the (vast majority of) unified-format suites that don't.
563+
# Only for test files that use observeTracingMessages: span processors
564+
# accumulate on the process-wide provider and can never be removed.
571565
cls._tracing_exporter = None
572566
uses_tracing = any(
573567
"observeTracingMessages" in entity.get("client", {})
@@ -593,12 +587,8 @@ def setUpClass(cls) -> None:
593587
@classmethod
594588
def tearDownClass(cls) -> None:
595589
cls.knobs.disable()
596-
# The exporter's span processor can never be removed from the shared process-wide
597-
# TracerProvider (see _shared_test_provider), so without this, every span emitted by any
598-
# client anywhere in the process for the rest of the test run keeps getting appended to this
599-
# (otherwise dead) class's exporter: an unbounded memory leak across a full test run, and
600-
# needless per-span export overhead for every other tracing-enabled test class that runs
601-
# afterwards. shutdown() makes further export() calls into this exporter no-ops.
590+
# The span processor can never be removed from the shared process-wide
591+
# TracerProvider, so without this the exporter accumulates every span.
602592
if cls._tracing_exporter is not None:
603593
cls._tracing_exporter.shutdown()
604594

@@ -639,9 +629,6 @@ def maybe_skip_test(self, spec):
639629
self.skipTest("PyMongo does not support the symbol type")
640630
if "timeoutms applied to entire download" in description:
641631
self.skipTest("PyMongo's open_download_stream does not cap the stream's lifetime")
642-
# Removed API: PyMongo no longer exposes map_reduce/inline_map_reduce at
643-
# all (mapReduce is deprecated server-side), so there's no code path left
644-
# that could send this command; this operation can never be exercised.
645632
if class_name == "testoperationmapreduce" and description == "mapreduce":
646633
self.skipTest(
647634
"PyMongo removed the map_reduce/inline_map_reduce Collection methods "
@@ -1535,9 +1522,8 @@ def format_logs(log_list):
15351522
self.match_evaluator.match_result(expected_msg, actual_msg)
15361523

15371524
async def check_tracing_messages(self, operations, spec):
1538-
# Like expectLogMessages/expectEvents, expectTracingMessages is a list of
1539-
# per-client blocks (even though only one client with
1540-
# observeTracingMessages is currently supported, see entity.py above).
1525+
# A list of per-client blocks, like expectLogMessages, though only one
1526+
# client with observeTracingMessages is supported.
15411527
exporter = self._tracing_exporter
15421528
if exporter is None:
15431529
self.fail(
@@ -1548,23 +1534,17 @@ async def check_tracing_messages(self, operations, spec):
15481534
await self.run_operations(operations)
15491535
finished_spans = exporter.get_finished_spans()
15501536

1551-
# Reconstruct the parent/child span tree from the flat, finish-ordered
1552-
# list the in-memory exporter records, keyed by each span's parent id.
1537+
# Rebuild the parent/child tree from the exporter's flat, finish-ordered list.
15531538
children_by_parent_id = defaultdict(list)
15541539
for span in finished_spans:
15551540
parent_id = span.parent.span_id if span.parent is not None else None
15561541
children_by_parent_id[parent_id].append(span)
15571542

15581543
def check_span_list(expected_list, actual_list, ignore_extra_spans):
15591544
if ignore_extra_spans:
1560-
# Per the unified-test-format spec, "additional unexpected spans
1561-
# are allowed". Unlike ignoreExtraEvents (which only tolerates
1562-
# a trailing tail), spans from concurrent/out-of-band activity
1563-
# (e.g. a testRunner-issued configureFailPoint command) can
1564-
# finish interleaved anywhere among the expected ones, not just
1565-
# at the end. Filter down to just the spans that line up (by
1566-
# name, in order) with the expected list, dropping anything
1567-
# else, instead of naively truncating the tail.
1545+
# Unlike ignoreExtraEvents, extra spans can finish interleaved
1546+
# anywhere rather than only at the end, so match by name in
1547+
# order instead of truncating the tail.
15681548
filtered = []
15691549
expected_iter = iter(expected_list)
15701550
current_expected = next(expected_iter, None)

test/unified_format.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,8 @@ def __init__(self, test_class):
241241
self._entities: dict[str, Any] = {}
242242
self._listeners: dict[str, EventListenerUtil] = {}
243243
self._session_lsids: dict[str, Mapping[str, Any]] = {}
244-
# The id of the (at most one, today) client entity created with
245-
# observeTracingMessages. Spans carry no attribute identifying which
246-
# client emitted them, so multi-client tracing correlation isn't
247-
# supported; _create_entity fails loudly if a second one appears.
244+
# The one client entity created with observeTracingMessages. Spans carry
245+
# no attribute identifying their client, so a second one is rejected.
248246
self._tracing_client_id: Optional[str] = None
249247
self.test: UnifiedSpecTestMixinV1 = test_class
250248

@@ -340,9 +338,7 @@ def _create_entity(self, entity_spec, uri=None):
340338
enable_payload = observe_tracing.get("enableCommandPayload", False)
341339
kwargs["tracing"] = {
342340
"enabled": True,
343-
# Tests asserting db.query.text match the full, untruncated
344-
# command, so an effectively-unlimited length avoids
345-
# truncating and failing that assertion.
341+
# Tests match the full command, so never truncate.
346342
"query_text_max_length": 1_000_000 if enable_payload else None,
347343
}
348344

@@ -563,10 +559,8 @@ def insert_initial_data(self, initial_data):
563559

564560
@classmethod
565561
def setUpClass(cls) -> None:
566-
# Only register a span exporter (and the shared SDK TracerProvider it
567-
# depends on) for test files that actually use observeTracingMessages,
568-
# to avoid needlessly accumulating span processors on the process-wide
569-
# provider for the (vast majority of) unified-format suites that don't.
562+
# Only for test files that use observeTracingMessages: span processors
563+
# accumulate on the process-wide provider and can never be removed.
570564
cls._tracing_exporter = None
571565
uses_tracing = any(
572566
"observeTracingMessages" in entity.get("client", {})
@@ -592,12 +586,8 @@ def setUpClass(cls) -> None:
592586
@classmethod
593587
def tearDownClass(cls) -> None:
594588
cls.knobs.disable()
595-
# The exporter's span processor can never be removed from the shared process-wide
596-
# TracerProvider (see _shared_test_provider), so without this, every span emitted by any
597-
# client anywhere in the process for the rest of the test run keeps getting appended to this
598-
# (otherwise dead) class's exporter: an unbounded memory leak across a full test run, and
599-
# needless per-span export overhead for every other tracing-enabled test class that runs
600-
# afterwards. shutdown() makes further export() calls into this exporter no-ops.
589+
# The span processor can never be removed from the shared process-wide
590+
# TracerProvider, so without this the exporter accumulates every span.
601591
if cls._tracing_exporter is not None:
602592
cls._tracing_exporter.shutdown()
603593

@@ -638,9 +628,6 @@ def maybe_skip_test(self, spec):
638628
self.skipTest("PyMongo does not support the symbol type")
639629
if "timeoutms applied to entire download" in description:
640630
self.skipTest("PyMongo's open_download_stream does not cap the stream's lifetime")
641-
# Removed API: PyMongo no longer exposes map_reduce/inline_map_reduce at
642-
# all (mapReduce is deprecated server-side), so there's no code path left
643-
# that could send this command; this operation can never be exercised.
644631
if class_name == "testoperationmapreduce" and description == "mapreduce":
645632
self.skipTest(
646633
"PyMongo removed the map_reduce/inline_map_reduce Collection methods "
@@ -1522,9 +1509,8 @@ def format_logs(log_list):
15221509
self.match_evaluator.match_result(expected_msg, actual_msg)
15231510

15241511
def check_tracing_messages(self, operations, spec):
1525-
# Like expectLogMessages/expectEvents, expectTracingMessages is a list of
1526-
# per-client blocks (even though only one client with
1527-
# observeTracingMessages is currently supported, see entity.py above).
1512+
# A list of per-client blocks, like expectLogMessages, though only one
1513+
# client with observeTracingMessages is supported.
15281514
exporter = self._tracing_exporter
15291515
if exporter is None:
15301516
self.fail(
@@ -1535,23 +1521,17 @@ def check_tracing_messages(self, operations, spec):
15351521
self.run_operations(operations)
15361522
finished_spans = exporter.get_finished_spans()
15371523

1538-
# Reconstruct the parent/child span tree from the flat, finish-ordered
1539-
# list the in-memory exporter records, keyed by each span's parent id.
1524+
# Rebuild the parent/child tree from the exporter's flat, finish-ordered list.
15401525
children_by_parent_id = defaultdict(list)
15411526
for span in finished_spans:
15421527
parent_id = span.parent.span_id if span.parent is not None else None
15431528
children_by_parent_id[parent_id].append(span)
15441529

15451530
def check_span_list(expected_list, actual_list, ignore_extra_spans):
15461531
if ignore_extra_spans:
1547-
# Per the unified-test-format spec, "additional unexpected spans
1548-
# are allowed". Unlike ignoreExtraEvents (which only tolerates
1549-
# a trailing tail), spans from concurrent/out-of-band activity
1550-
# (e.g. a testRunner-issued configureFailPoint command) can
1551-
# finish interleaved anywhere among the expected ones, not just
1552-
# at the end. Filter down to just the spans that line up (by
1553-
# name, in order) with the expected list, dropping anything
1554-
# else, instead of naively truncating the tail.
1532+
# Unlike ignoreExtraEvents, extra spans can finish interleaved
1533+
# anywhere rather than only at the end, so match by name in
1534+
# order instead of truncating the tail.
15551535
filtered = []
15561536
expected_iter = iter(expected_list)
15571537
current_expected = next(expected_iter, None)

test/unified_format_shared.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -588,22 +588,12 @@ def match_result(self, expectation, actual, in_recursive_call=False, test=True):
588588

589589
@staticmethod
590590
def _normalize_span_attribute(key: str, value: Any) -> Any:
591-
"""Adapt one OTel span attribute value to what the generic match
592-
evaluator expects, since span attributes are plain Python primitives
593-
rather than the BSON-decoded documents/events it normally matches
594-
against.
595-
596-
- Widen plain Python ints (excluding bools) to ``bson.Int64``: span
597-
attributes carry no int32/int64 distinction, but the $$type matcher's
598-
"long" alias maps to ``Int64`` specifically (see
599-
BSON_TYPE_ALIAS_MAP), so a bare ``int`` (e.g. ``server.port``) would
600-
otherwise fail a ``$$type: ["long", "string"]`` check. ``Int64`` is a
601-
subclass of ``int``, so this is safe for "int" checks too.
602-
- Reconstruct ``db.mongodb.lsid`` (formatted by pymongo/_otel.py as a
603-
plain UUID string, per the OTel spec's attribute table) back into the
604-
``{"id": Binary(...)}`` document shape :meth:`_operation_sessionLsid`
605-
compares against, that operator being designed for
606-
command-monitoring-style raw command documents.
591+
"""Adapt one span attribute value to what the generic match evaluator expects.
592+
593+
Span attributes are plain Python primitives, not the BSON-decoded documents
594+
the evaluator matches against. Ints widen to ``Int64`` for the ``$$type``
595+
"long" alias, and ``db.mongodb.lsid`` is rebuilt from its UUID string into
596+
the document shape :meth:`_operation_sessionLsid` expects.
607597
"""
608598
if key == "db.mongodb.lsid" and isinstance(value, str):
609599
try:

0 commit comments

Comments
 (0)