Skip to content

PYTHON-5947 Add OpenTelemetry operation spans - #2991

Draft
blink1073 wants to merge 4 commits into
otelfrom
PYTHON-5947-otel-1-operations
Draft

PYTHON-5947 Add OpenTelemetry operation spans#2991
blink1073 wants to merge 4 commits into
otelfrom
PYTHON-5947-otel-1-operations

Conversation

@blink1073

@blink1073 blink1073 commented Aug 17, 2026

Copy link
Copy Markdown
Member

PYTHON-5947

First of four PRs splitting #2964. Base is otel; review in order.

Branch Contents
1 PYTHON-5947-otel-1-operations operation spans (this PR)
2 PYTHON-5947-otel-2-transactions transaction spans
3 PYTHON-5947-otel-3-unified unified runner and vendored fixtures
4 PYTHON-5947-otel-4-getmore getMore spans

Changes in this PR

Adds one span per public API call, containing one command span per command sent to the server, per the OpenTelemetry driver specification. Without it a retried operation's command spans share no parent, so a reader cannot tell which attempts belong to the same call.

  • One operation span covers every retry attempt of a call, so retries show up as sibling command spans instead of collapsing into one.
  • killCursors, endSessions, and unacknowledged client bulk writes get operation spans too.
  • An operation that fails before anything reaches the wire still produces a conformant span, so a server selection timeout is reported rather than lost.
  • Cursor-creating calls (find, aggregate, listCollections, listIndexes) are covered, but only for the command that creates the cursor. Caller-driven getMores arrive in PR 4.
  • Fixed truncated output dropping falsy values (0, False, ""). This affected structured command logging as well as spans.
  • Background tasks no longer inherit a caller's span.
  • The otel Evergreen variant now covers all three topologies, held at 22 tasks.

Opt-in: no behavior change unless the tracing client option or OTEL_PYTHON_INSTRUMENTATION_MONGODB_ENABLED is set. With tracing off there is no added allocation per command.

Around 1,000 of the added lines are just synchro output and another ~745 are tests.

Test Plan

  • 49 new tests each side: span attributes and naming, retry and failure paths, sensitive-command redaction, and config handling, plus a regression test that enabling tracing through the environment variable does not trace background heartbeats.
  • Regression tests for the truncation bug and for collection names containing dots.
  • Locally against a replica set: 98 otel tests pass, along with the cursor, collection, common, json_util, and operation-id suites. just lint clean.

Checklist

Checklist for Author

  • Did you update the changelog (if necessary)?
  • Is there test coverage?
  • Is any followup work tracked in a JIRA ticket? If so, add link(s).

Checklist for Reviewer

  • Does the title of the PR reference a JIRA Ticket?
  • Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
  • Is all relevant documentation (README or docstring) updated?

@blink1073
blink1073 force-pushed the PYTHON-5947-otel-1-operations branch 3 times, most recently from 4a8db0c to ba21bb8 Compare August 17, 2026 23:09
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

@blink1073
blink1073 force-pushed the PYTHON-5947-otel-1-operations branch 11 times, most recently from c841c9f to 4e0c468 Compare August 18, 2026 12:02
Give every public API call an operation span containing one command span
per command sent to the server, per the OpenTelemetry driver specification.

The span covers all retry attempts of one _retry_internal call, so retries
appear as sibling command spans rather than being collapsed into one.
killCursors and endSessions bypass the retry layer and start their spans at
the call site instead, as does an unacknowledged client bulk write, which
never reaches the command-span code that would fill in its namespace.

Cursor-creating operations (find, aggregate, listCollections, listIndexes)
are covered here, but only for the command that creates the cursor. Spans
for caller-driven getMores come in a later change, as do transaction spans.

_otel.py also takes over the specification's naming and attribute rules, so
_telemetry.py deals only with span lifecycles and a specification change
need not touch it. Namespace parsing moves to helpers_shared._split_namespace.
@blink1073
blink1073 force-pushed the PYTHON-5947-otel-1-operations branch from 4e0c468 to 6638ae1 Compare August 18, 2026 12:55
Lead with the condition rather than the bare adjective.
The vendored unified spec fixtures it pointed at arrive in a later change, so
the note described tests absent from this one.
…d test

Evergreen only runs on PRs whose base is a configured branch, so the upper PRs
in this stack get no Evergreen coverage, and the otel tests only run in
Evergreen's otel variant. Add a temporary GitHub Actions job that runs them on
every branch in the stack, against a replica set so the transaction span tests
are included. Remove the job before merging.

Also drop test_operation_name_normalizes_enum_operation. All 22 vendored
fixtures assert db.operation.name with literal values, so the _Op formatting
regression it guards fails them loudly, and adding a test here only to delete
it once the fixtures land is churn.
enable-cache: true
python-version: "3.11"
- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
@semgrep-code-mongodb

Copy link
Copy Markdown

Semgrep found 2 github-actions-mutable-action-tag findings:

GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

🛟 Help? Slack #semgrep-help or go/semgrep-help.

Resolution Options:

  • Fix the code
  • Reply /fp $reason (if security gap doesn’t exist)
  • Reply /ar $reason (if gap is valid but intentional; add mitigations/monitoring)
  • Reply /other $reason (e.g., test-only)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants