MongoDB
Monitor MongoDB database performance, slow queries, and memory usage with OpenTelemetry and Last9
Use OpenTelemetry to instrument your self-hosted MongoDB database and send telemetry data to Last9. This integration collects metrics, parses structured JSON logs, and extracts slow query details into structured attributes for analysis.
Prerequisites
Before setting up MongoDB monitoring, ensure you have:
- MongoDB 4.x or 5.x+ installed and running
- Administrative access to create MongoDB users and roles
- OpenTelemetry Collector binary or container runtime
- Last9 account with integration credentials
Database Setup
The setup process varies slightly between MongoDB versions. Choose the appropriate section for your MongoDB version:
-
Create Monitoring Role and User
Log into your MongoDB instance and create a custom role for index access metrics and a least-privilege monitoring user:
use admin// Custom role for index access metrics (mongodb.index.access.count)db.createRole({role: "indexStatsRole",privileges: [{resource: { db: "admin", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "config", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "local", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "", collection: "system.profile" },actions: [ "indexStats", "find" ]}],roles: []})// Create monitoring user with least-privilege roles (NO root access)db.createUser({user: "otel",pwd: "YOUR_SECURE_PASSWORD",roles: [{ role: "clusterMonitor", db: "admin" }, // Required: serverStatus, dbStats, top{ role: "read", db: "local" }, // Required: replica set oplog monitoring{ role: "indexStatsRole", db: "admin" } // Required: index access metrics],mechanisms: [ "SCRAM-SHA-1" ]}) -
Configure MongoDB Settings
Edit
/etc/mongod.confto enable monitoring features:storage:dbPath: /var/lib/mongodbjournal:enabled: truesystemLog:destination: filelogAppend: truepath: /var/log/mongodb/mongod.lognet:port: 27017bindIp: 0.0.0.0processManagement:timeZoneInfo: /usr/share/zoneinfosecurity:authorization: enabledoperationProfiling:mode: allslowOpThresholdMs: 100setParameter:diagnosticDataCollectionEnabled: true -
Restart MongoDB Service
sudo systemctl restart mongod
-
Create Monitoring Role and User
Log into your MongoDB instance and create a custom role for index access metrics and a least-privilege monitoring user:
use admin// Custom role for index access metrics (mongodb.index.access.count)db.createRole({role: "indexStatsRole",privileges: [{resource: { db: "admin", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "config", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "local", collection: "system.profile" },actions: [ "indexStats", "find" ]},{resource: { db: "", collection: "system.profile" },actions: [ "indexStats", "find" ]}],roles: []})// Create monitoring user with least-privilege roles (NO root access)db.createUser({user: "otel",pwd: "YOUR_SECURE_PASSWORD",roles: [{ role: "clusterMonitor", db: "admin" }, // Required: serverStatus, dbStats, top{ role: "read", db: "local" }, // Required: replica set oplog monitoring{ role: "indexStatsRole", db: "admin" } // Required: index access metrics],mechanisms: [ "SCRAM-SHA-1", "SCRAM-SHA-256" ]}) -
Configure MongoDB Settings
Add the following to
/etc/mongod.conf:operationProfiling:mode: allslowOpThresholdMs: 100setParameter:diagnosticDataCollectionEnabled: true -
Restart MongoDB Service
sudo systemctl restart mongod
Install OpenTelemetry Collector
Choose the appropriate binary for your system architecture:
sudo apt-get updatesudo apt-get -y install wget systemctlwget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_amd64.debsudo dpkg -i otelcol-contrib_0.144.0_linux_amd64.debsudo apt-get updatesudo apt-get -y install wget systemctlwget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_arm64.debsudo dpkg -i otelcol-contrib_0.144.0_linux_arm64.debConfigure OpenTelemetry Collector
-
Create Collector Configuration
Create the collector configuration file at
/etc/otelcol-contrib/config.yaml.Note: The MongoDB connection string format varies based on version:
- For MongoDB 4.0-4.3:
"127.0.0.1:27017/?authSource=admin&tls=false&directConnection=true" - For MongoDB ≥ 4.4 and 5.x+:
"127.0.0.1:27017/?authSource=admin&directConnection=true"
Replace
MONGODB_USERNAMEandMONGODB_PASSWORDwith your actual MongoDB credentials.receivers:filelog:include: [/var/log/mongodb/*.log]include_file_path: truestart_at: endretry_on_failure:enabled: trueoperators:- type: json_parserif: body matches "^\\{"timestamp:parse_from: attributes.t.$$datelayout_type: gotimelayout: "2006-01-02T15:04:05.999-07:00"severity:parse_from: attributes.smapping:fatal: Ferror: Ewarn: Winfo: Idebug: D1hostmetrics:collection_interval: 60sscrapers:cpu:metrics:system.cpu.logical.count:enabled: truememory:metrics:system.memory.utilization:enabled: truesystem.memory.limit:enabled: trueload:disk:filesystem:metrics:system.filesystem.utilization:enabled: truenetwork:paging:mongodb:hosts:- endpoint: "127.0.0.1:27017/?authSource=admin&directConnection=true"username: "MONGODB_USERNAME"password: "MONGODB_PASSWORD"collection_interval: 60sinitial_delay: 1stimeout: 30stls:insecure: truemetrics:mongodb.operation.latency.time:enabled: truemongodb.page_faults:enabled: truemongodb.active.reads:enabled: truemongodb.active.writes:enabled: truemongodb.health:enabled: truemongodb.uptime:enabled: truemongodb.lock.acquire.count:enabled: truemongodb.lock.acquire.time:enabled: trueprocessors:batch:timeout: 5ssend_batch_size: 10000send_batch_max_size: 10000resourcedetection/system:detectors: ["system", "ec2"]system:hostname_sources: ["os"]transform/add_timestamp:flatten_data: truelog_statements:- context: logstatements:- set(observed_time, Now())- set(time_unix_nano, observed_time_unix_nano) where time_unix_nano == 0transform/add_service:flatten_data: truelog_statements:- context: logstatements:- set(resource.attributes["service.name"], "mongodb")transform/slow_queries:log_statements:- context: logconditions:- IsMatch(body, "Slow query")statements:- set(attributes["db.namespace"], attributes["attr"]["ns"]) where attributes["attr"]["ns"] != nil- set(attributes["db.operation.duration_ms"], attributes["attr"]["durationMillis"]) where attributes["attr"]["durationMillis"] != nil- set(attributes["db.plan_summary"], attributes["attr"]["planSummary"]) where attributes["attr"]["planSummary"] != nil- set(attributes["db.keys_examined"], attributes["attr"]["keysExamined"]) where attributes["attr"]["keysExamined"] != nil- set(attributes["db.docs_examined"], attributes["attr"]["docsExamined"]) where attributes["attr"]["docsExamined"] != nil- set(attributes["db.rows_affected"], attributes["attr"]["nreturned"]) where attributes["attr"]["nreturned"] != nil- set(attributes["db.query_hash"], attributes["attr"]["queryHash"]) where attributes["attr"]["queryHash"] != nil- set(attributes["db.system"], "mongodb")- set(attributes["slow_query"], true)- set(severity_text, "WARN") where attributes["attr"]["durationMillis"] != nil and attributes["attr"]["durationMillis"] > 100transform/hostmetrics:metric_statements:- context: datapointstatements:- set(attributes["host.name"], resource.attributes["host.name"])- set(attributes["database"], resource.attributes["database"])- set(attributes["server.address"], resource.attributes["server.address"])- set(attributes["cloud.account.id"], resource.attributes["cloud.account.id"])- set(attributes["cloud.availability_zone"], resource.attributes["cloud.availability_zone"])- set(attributes["cloud.platform"], resource.attributes["cloud.platform"])- set(attributes["cloud.provider"], resource.attributes["cloud.provider"])- set(attributes["cloud.region"], resource.attributes["cloud.region"])- set(attributes["host.type"], resource.attributes["host.type"])- set(attributes["host.image.id"], resource.attributes["host.image.id"])exporters:otlp/last9:endpoint: "{{ .Logs.WriteURL }}"headers:"Authorization": "{{ .Logs.AuthValue }}"debug:verbosity: detailedservice:pipelines:logs:receivers: [filelog]processors:[batch,resourcedetection/system,transform/add_timestamp,transform/add_service,transform/slow_queries,]exporters: [otlp/last9]metrics:receivers: [mongodb, hostmetrics]processors: [batch, resourcedetection/system, transform/hostmetrics]exporters: [otlp/last9] - For MongoDB 4.0-4.3:
-
Start the Collector
otelcol-contrib --config /etc/otelcol-contrib/config.yaml --feature-gates transform.flatten.logs
Memory Metrics
The MongoDB receiver collects mongodb.memory.usage by default with resident and virtual breakdowns. Combined with hostmetrics system memory, you can calculate MongoDB memory percentage:
| Metric | Description | Unit |
|---|---|---|
mongodb.memory.usage | MongoDB process memory (resident, virtual) | By |
mongodb.page_faults | Page faults indicating memory pressure | {faults} |
system.memory.utilization | System memory utilization ratio | 1 |
system.memory.limit | Total system memory | By |
Calculating memory usage percentage:
- MongoDB memory % =
mongodb.memory.usage{memory_type="resident"}/system.memory.limit* 100
Slow Query Monitoring
MongoDB 4.4+ outputs structured JSON logs. The filelog receiver parses these and the transform/slow_queries processor extracts slow query fields:
| Attribute | Source Field | Description |
|---|---|---|
db.namespace | attr.ns | Database and collection (e.g., mydb.users) |
db.operation.duration_ms | attr.durationMillis | Total execution time in milliseconds |
db.plan_summary | attr.planSummary | Execution plan (COLLSCAN, IXSCAN, etc.) |
db.keys_examined | attr.keysExamined | Number of index keys scanned |
db.docs_examined | attr.docsExamined | Number of documents scanned |
db.rows_affected | attr.nreturned | Number of documents returned |
db.query_hash | attr.queryHash | Hash identifying the query shape |
db.system | — | Always set to mongodb |
slow_query | — | Always set to true for slow query logs |
Slow queries (> 100ms) are automatically elevated to WARN severity. The threshold is controlled by slowOpThresholdMs in mongod.conf.
Verification
-
Check Collector Status
sudo systemctl status otelcol-contrib -
View Collector Logs
sudo journalctl -u otelcol-contrib -f -
Verify Metrics in Last9
Log into your Last9 account and check that MongoDB metrics are being received. Look for the
mongodbservice name.
Best Practices
- Security: Use strong passwords for the monitoring user. The configuration above uses least-privilege roles — avoid granting
rootaccess. - Performance: Adjust
slowOpThresholdMsbased on your application’s performance requirements. - Storage: Monitor log file sizes and implement log rotation to prevent disk space issues.
- Monitoring: Set up alerts for critical MongoDB metrics like connection count and replication lag.
Need Help?
If you encounter any issues or have questions:
- Join our Discord community for real-time support
- Contact our support team at support@last9.io