Skip to content

feat(mongodb): add OpenTelemetry tracing and metrics - #15

Merged
ashishl9 merged 5 commits into
mainfrom
feat/mongodb-tracing
Feb 23, 2026
Merged

feat(mongodb): add OpenTelemetry tracing and metrics#15
ashishl9 merged 5 commits into
mainfrom
feat/mongodb-tracing

Conversation

@prathamesh-sonpatki

Copy link
Copy Markdown
Member

Summary

  • Adds MongoDB instrumentation using event.CommandMonitor from mongo-driver v1, replacing the deprecated otelmongo contrib package
  • Provides NewClient(Config) and Instrument(*options.ClientOptions) APIs consistent with existing Redis/Kafka integration patterns
  • Includes OTel semantic convention attributes, operation metrics (count, errors, duration histogram), command filtering, and monitor chaining

Details

Tracing: Spans are created per MongoDB command with names following OTel DB semconv ("insert users", "find orders"). Housekeeping commands (hello, isMaster, ping, saslStart, etc.) are filtered out. Spans carry db.system, db.name, db.operation, db.mongodb.collection, server.address, and server.port attributes.

Metrics: Three instruments — db.mongodb.operations (counter), db.mongodb.errors (counter), db.mongodb.operation.duration (histogram in ms).

Context propagation: Spans correctly parent under application spans via the driver's context forwarding.

Monitor chaining: If the caller has already set a CommandMonitor on their options, both monitors are called.

Test plan

  • TestMongoDB_InsertFind — verifies insert/find spans with correct attributes
  • TestMongoDB_UpdateDelete — verifies update/delete span attributes
  • TestMongoDB_ContextPropagation — verifies child spans share parent trace ID
  • TestMongoDB_Aggregate — verifies aggregation pipeline spans
  • TestMongoDB_SkippedCommands — verifies housekeeping commands produce no spans
  • TestMongoDB_DuplicateKeyStillTraced — verifies both insert spans exist even when one returns a duplicate key error
  • TestMongoDB_InstrumentAPI — verifies Instrument() API path produces traced spans

All 7 integration tests pass against a mongo:7 testcontainer.

Resolves: FDE-48

🤖 Generated with Claude Code

prathamesh-sonpatki and others added 2 commits February 23, 2026 12:57
Implement MongoDB instrumentation using the mongo-driver v1
event.CommandMonitor API, replacing the deprecated otelmongo contrib
package.

Provides two APIs:
- NewClient(Config) for new connections
- Instrument(*options.ClientOptions) for existing option chains

Includes OTel semantic convention attributes (db.system, db.name,
db.operation, db.mongodb.collection, server.address, server.port),
operation metrics (count, errors, duration histogram), command
filtering for housekeeping commands, and monitor chaining to preserve
user-set CommandMonitors.

Resolves: FDE-48

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix duration precision: use float64(nanoseconds)/1e6 instead of
  float64(Milliseconds()) to preserve sub-millisecond accuracy in
  the duration histogram
- Add nil-guard in connectWithMonitor: skip instrumentation gracefully
  if monitor creation fails, preventing potential nil-pointer dereference
- Make NewClient error handling consistent with Instrument: warn and
  continue (instead of hard-failing) when the agent fails to start,
  matching the Redis integration pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@prathamesh-sonpatki

Copy link
Copy Markdown
Member Author

Code review

Found 1 issue:

  1. connectWithMonitor silently swallows instrumentation errors — the newMonitor error is logged but never returned to the caller. A caller of NewClient or Instrument receives a connected client with nil error even when metric instrument creation failed, giving no programmatic indication that instrumentation is degraded. The Redis integration (integrations/redis/redis.go) returns both the client and the instrumentation error, letting callers decide how to handle it. The MongoDB integration should follow the same pattern.

func connectWithMonitor(opts *options.ClientOptions, baseAttrs []attribute.KeyValue) (*mongo.Client, error) {
m, err := newMonitor(baseAttrs)
if err != nil {
log.Printf("[Last9 Agent] Warning: partial MongoDB monitor setup: %v", err)
}
// If monitor creation failed entirely, connect without instrumentation.
if m != nil {
cmdMonitor := m.commandMonitor()
// Chain with any existing monitor the caller may have set.
if opts.Monitor != nil {
cmdMonitor = chainMonitors(opts.Monitor, cmdMonitor)
}
opts.SetMonitor(cmdMonitor)
}
client, err := mongo.Connect(context.Background(), opts)
if err != nil {
return nil, fmt.Errorf("mongodb: failed to connect: %w", err)
}
return client, nil
}

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

prathamesh-sonpatki and others added 2 commits February 23, 2026 13:17
Add MongoDB integration documentation covering both NewClient and
Instrument APIs, traced operations, skipped commands, span attributes,
and automatic metrics. Update table of contents, supported frameworks
table, and metrics sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Return the newMonitor error from connectWithMonitor instead of
swallowing it. The client is still returned and usable (matching the
Redis integration pattern), but callers now get programmatic notice
when instrumentation setup partially failed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@ashishl9 ashishl9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Excellent MongoDB instrumentation implementation:

  • Replaces deprecated otelmongo with native CommandMonitor approach
  • Complete observability: spans, metrics (operations, errors, duration), proper OTel semconv
  • Smart housekeeping command filtering reduces noise
  • Proper context propagation with correct span nesting
  • Flexible APIs: NewClient() and Instrument() patterns
  • Monitor chaining respects existing configurations
  • 7 comprehensive integration tests covering CRUD, aggregation, errors

Well-executed following established Redis/Kafka integration patterns.

@ashishl9

Copy link
Copy Markdown
Contributor

@prathamesh-sonpatki PR #16 has been merged. This PR needs to be updated with the latest main branch. Please update the branch and I'll merge it.

@ashishl9
ashishl9 merged commit e96ca53 into main Feb 23, 2026
10 checks passed
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