Use Tracing Channels for observability

XMLWordPrintableJSON

    • Type: New Feature
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: Logging
    • None
    • None
    • None
    • None
    • None
    • None

      I'd like to propose adding first-class TracingChannel support to the MongoDB Node.js driver, following the pattern established by [undici|https://github.com/nodejs/undici] in Node.js core.

      The MongoDB driver already has an excellent observability foundation via command monitoring.

      However, APM instrumentation libraries (OpenTelemetry, Datadog, Sentry) {}do not use these events{} for span-based tracing today. Instead, they resort to monkey-patching internal methods like `Connection.prototype.command` and `ConnectionPool.prototype.checkOut` via IITM/RITM. Here's why:

      1. {}No async context propagation.{} Command Monitoring events are emitted via `EventEmitter`. When `commandStarted` fires, the listener runs in the emitter's execution context — not the caller's `AsyncLocalStorage` context. APM tools need to create child spans of the caller's span, which requires capturing the async context at the call site. EventEmitter listeners lose this context.

      2. {}Opt-in gating.{} Command Monitoring only fires when the user passes `monitorCommands: true` to `MongoClient`. APM tools can't control how users instantiate their clients, so they can't rely on this flag being set. Monkey-patching works regardless of user configuration.

      3. {}Split lifecycle.{} `commandStarted` and `commandSucceeded`/`commandFailed` are separate EventEmitter events. To build a span, APM tools must correlate them via `requestId` and manage span storage manually. Tracing channels provide a contextualized lifecycle for the operation, so correlation is built-in.

      Beyond these APM-specific gaps, the current monkey-patching approach has broader ecosystem concerns:

      • Runtime lock-in: RITM and IITM rely on Node.js-specific module loader internals (`Module._resolveFilename`, `module.register()`). They don't work on Bun or Deno, which implement the Node.js API surface but not the module loader internals.
      • ESM fragility: IITM is built on Node.js's module customization hooks, which are still evolving and have been a persistent source of breakage in the OTEL JS ecosystem.
      • Initialization ordering: Both require instrumentation to be set up before `mongodb` is first `require()`'d / `import`'d. Get the order wrong and instrumentation silently does nothing — very hard to debug in production.
      • Bundling: Users must ensure instrumented modules are externalized, which is increasingly difficult as frameworks bundle server-side code into single executables or deployment files.

      `TracingChannel` solves all of these. It provides structured lifecycle events (`start`, `end`, `asyncStart`, `asyncEnd`, `error`) with built-in async context propagation, zero-cost when no subscribers are attached, and a standardized subscription model that requires no monkey-patching.

      The driver's existing Command Monitoring and CMAP events remain valuable for operational monitoring and debugging. `TracingChannel` is not a replacement, it's a complement that fills the specific gaps APM tools need for span-based distributed tracing.

      I'm happy to collaborate on this with your team if you think it's a worthwhile improvement.

            Assignee:
            Unassigned
            Reporter:
            Abdelrahman Awad
            None
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: