Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved configuration precedence and command-span correctness issues remain.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (4)
What changed in this PR
Adds optional OpenTelemetry command-span tracing for synchronous and asynchronous PyMongo clients.
Changes:
- Adds tracing configuration, span attributes, and lifecycle integration.
- Adds OpenTelemetry dependency metadata and documentation.
- Adds sync/async tests and Evergreen coverage.
| File | Description |
|---|---|
uv.lock |
Locks OpenTelemetry dependencies |
test/test_otel.py |
Synchronous tracing tests |
test/asynchronous/test_otel.py |
Asynchronous tracing tests |
requirements/opentelemetry.txt |
OpenTelemetry API dependency |
pyproject.toml |
Optional dependency and pytest marker |
pymongo/synchronous/mongo_client.py |
Sync tracing documentation |
pymongo/synchronous/command_runner.py |
Sync tracing integration |
pymongo/pool_shared.py |
Connection address typing |
pymongo/common.py |
Tracing option validation |
pymongo/client_options.py |
Stores tracing configuration |
pymongo/asynchronous/mongo_client.py |
Async tracing documentation |
pymongo/asynchronous/command_runner.py |
Async tracing integration |
pymongo/_telemetry.py |
Span lifecycle integration |
pymongo/_otel.py |
OpenTelemetry span implementation |
justfile |
Typing dependency setup |
doc/changelog.rst |
Feature changelog entry |
.evergreen/scripts/utils.py |
OTel test mapping |
.evergreen/scripts/setup_tests.py |
OTel test and coverage setup |
.evergreen/scripts/generate_config.py |
OTel variant generation |
.evergreen/generated_configs/variants.yml |
Generated OTel variant |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
c68e175 to
55a6bd7
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Security redaction, monitoring spans, option coercion, payload selection, and cancellation cleanup have unresolved correctness issues.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (6)
Normalize command names before sensitive-command checks · New Disable tracing for internal calls without client options · New Finish command spans when async tasks are cancelled · New Use the published command document for query text · New Preserve validated integer values for query text length · New Document client tracing options overriding environment settings · New
|
@NoahStapp the first commit was already merged in the last PR. I'm going to squash down all the copilot back and forth here into a second commit. |
55a6bd7 to
c8788d7
Compare
…butes Fix tracing.enabled so an explicit client value overrides the OTEL_PYTHON_INSTRUMENTATION_MONGODB_ENABLED environment variable, fix db.query.text truncation so budgets smaller than the "..." marker still honor the bound, and fix collection-name extraction so user and role management commands do not expose usernames as db.collection.name.
e91db53 to
61da468
Compare
| pool_opts=pool_opts, | ||
| ) | ||
| except Exception as exc: | ||
| except BaseException as exc: |
There was a problem hiding this comment.
If CancelledError is the only BaseException type we want to catch here, can we narrow this catch back down to (Exception, CancelledError)?
| | **OpenTelemetry options:** | ||
| | (Requires the ``opentelemetry-api`` package; install with the ``pymongo[opentelemetry]`` extra.) | ||
|
|
||
| - `tracing`: (dict) Configuration for OpenTelemetry command spans, with keys: |
There was a problem hiding this comment.
Do we allow tracing to be passed as a connection string option? The spec doesn't say explicitly.
|
|
||
| .. seealso:: The MongoDB documentation on `connections <https://dochub.mongodb.org/core/connections>`_. | ||
|
|
||
| .. versionchanged:: 4.18 |
There was a problem hiding this comment.
This should be 4.XX until we're ready for release.
|
|
||
| .. seealso:: The MongoDB documentation on `connections <https://dochub.mongodb.org/core/connections>`_. | ||
|
|
||
| .. versionchanged:: 4.18 |
There was a problem hiding this comment.
This should be 4.XX until we're ready for release.
| def tracing(self) -> _otel.TracingOptions: | ||
| """The configured ``tracing`` option for OpenTelemetry command spans. | ||
|
|
||
| .. versionadded:: 4.18 |
There was a problem hiding this comment.
This should be 4.XX until we're ready for release.
| if ( | ||
| (topology_id is not None and _is_debug_enabled(_COMMAND_LOGGER)) | ||
| or (listeners is not None and listeners.enabled_for_commands) | ||
| or _otel._is_tracing_enabled(tracing_options) |
There was a problem hiding this comment.
I recall that we don't support enabling/disabling OTel after client construction, so we can determine if tracing is enabled or not one single time at creation instead of needing to make this call on every operation. There's a few other places we call _otel._is_tracing_enabled() every time instead of once at startup that could be removed as well.
| Returns None when tracing is disabled/unavailable or the command is | ||
| sensitive (mirroring the redaction applied to logs). | ||
| """ | ||
| if not _is_tracing_enabled(tracing_options): |
There was a problem hiding this comment.
Can we add a check to ensure the span is recording before doing all the work below?
| def _build_query_text(cmd: Mapping[str, Any], max_length: int) -> str: | ||
| """Serialize ``cmd`` to extended JSON, redacted and truncated to ``max_length``. | ||
|
|
||
| Mirrors the truncation approach used for log messages: truncate field |
There was a problem hiding this comment.
If this is the same approach we use for logging, can we use a shared helper instead of duplicating it here?
|
|
||
|
|
||
| def _is_sensitive_command(command_name: str, speculative_hello: bool) -> bool: | ||
| """Mirror the redaction rules in ``pymongo.logger.LogMessage._is_sensitive``.""" |
There was a problem hiding this comment.
Same here, if this is the same as the logger's version can we use a shared helper instead of duplicating?
| # expose the username or role name as a collection. | ||
| _NOT_COLLECTION_COMMANDS = frozenset( | ||
| { | ||
| "createUser", |
There was a problem hiding this comment.
We redact createUser for command logging, so this won't ever get used. Same goes for updateUser.



PYTHON-5945
Carries the content of #2946, which merged into the temporary
otelfeature branch, ontomain. This is the bottom of the OpenTelemetry stack retargeted to trackmaindirectly.PYTHON-5947-operationserror.typecommand span attributeChanges in this PR
Adds optional, opt-in OpenTelemetry tracing for server commands, conforming to the DRIVERS-719 client-side OpenTelemetry spec. Spec-driven unified test format compliance is deferred to PYTHON-5947 (every operation/transaction YAML test asserts an operation-level span, which is out of scope here); the spec's two command/config-scoped prose tests are included directly.
Test Plan
New tests in
test/test_otel.py(and async mirror) using an in-memory span exporter, including the spec's two prose tests (env-var enable/disable, env-var-drivendb.query.text), run under their ownotelpytest marker/Evergreen test type (like encryption/kms) so opentelemetry stays an optional dependency. Verified no regression in existing command logging/monitoring test suites. Manually verified span output against a live server with the OTel console exporter.Checklist
Checklist for Author
Checklist for Reviewer
Stack created with GitHub Stacks CLI • Give Feedback 💬