summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/mongodb
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:18 +0000
commit5da14042f70711ea5cf66e034699730335462f66 (patch)
tree0f6354ccac934ed87a2d555f45be4c831cf92f4a /src/go/collectors/go.d.plugin/modules/mongodb
parentReleasing debian version 1.44.3-2. (diff)
downloadnetdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz
netdata-5da14042f70711ea5cf66e034699730335462f66.zip
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
l---------src/go/collectors/go.d.plugin/modules/mongodb/README.md1
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/charts.go1036
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/client.go299
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect.go43
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect_dbstats.go100
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go113
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect_serverstatus.go129
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect_sharding.go102
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/config_schema.json105
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/documents.go276
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/init.go29
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/integrations/mongodb.md356
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/metadata.yaml580
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/mongodb.go126
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/mongodb_test.go816
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.json12
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.yaml7
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/dbStats.json9
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongod-serverStatus.json497
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongos-serverStatus.json129
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/replSetGetStatus.json27
21 files changed, 4792 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/README.md b/src/go/collectors/go.d.plugin/modules/mongodb/README.md
new file mode 120000
index 000000000..a28253054
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/README.md
@@ -0,0 +1 @@
+integrations/mongodb.md \ No newline at end of file
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/charts.go b/src/go/collectors/go.d.plugin/modules/mongodb/charts.go
new file mode 100644
index 000000000..f1b9c1a07
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/charts.go
@@ -0,0 +1,1036 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+const (
+ prioOperationsRate = module.Priority + iota
+ prioOperationsLatencyTime
+ prioOperationsByTypeRate
+ prioDocumentOperationsRate
+ prioScannedIndexesRate
+ prioScannedDocumentsRate
+
+ prioActiveClientsCount
+ prioQueuedOperationsCount
+
+ prioGlobalLockAcquisitionsRate
+ prioDatabaseLockAcquisitionsRate
+ prioCollectionLockAcquisitionsRate
+ prioMutexLockAcquisitionsRate
+ prioMetadataLockAcquisitionsRate
+ prioOpLogLockAcquisitionsRate
+
+ prioCursorsOpenCount
+ prioCursorsOpenNoTimeoutCount
+ prioCursorsOpenedRate
+ prioTimedOutCursorsRate
+ prioCursorsByLifespanCount
+
+ prioTransactionsCount
+ prioTransactionsRate
+ prioTransactionsNoShardsCommitsRate
+ prioTransactionsNoShardsCommitsDurationTime
+ prioTransactionsSingleShardCommitsRate
+ prioTransactionsSingleShardCommitsDurationTime
+ prioTransactionsSingleWriteShardCommitsRate
+ prioTransactionsSingleWriteShardCommitsDurationTime
+ prioTransactionsReadOnlyCommitsRate
+ prioTransactionsReadOnlyCommitsDurationTime
+ prioTransactionsTwoPhaseCommitCommitsRate
+ prioTransactionsTwoPhaseCommitCommitsDurationTime
+ prioTransactionsRecoverWithTokenCommitsRate
+ prioTransactionsRecoverWithTokenCommitsDurationTime
+
+ prioConnectionsUsage
+ prioConnectionsByStateCount
+ prioConnectionsRate
+
+ prioAssertsRate
+
+ prioNetworkTrafficRate
+ prioNetworkRequestsRate
+ prioNetworkSlowDNSResolutionsRate
+ prioNetworkSlowSSLHandshakesRate
+
+ prioMemoryResidentSize
+ prioMemoryVirtualSize
+ prioMemoryPageFaultsRate
+ prioMemoryTCMallocStats
+
+ prioWiredTigerConcurrentReadTransactionsUsage
+ prioWiredTigerConcurrentWriteTransactionsUsage
+ prioWiredTigerCacheUsage
+ prioWiredTigerCacheDirtySpaceSize
+ prioWiredTigerCacheIORate
+ prioWiredTigerCacheEvictionsRate
+
+ prioDatabaseCollectionsCount
+ prioDatabaseIndexesCount
+ prioDatabaseViewsCount
+ prioDatabaseDocumentsCount
+ prioDatabaseDataSize
+ prioDatabaseStorageSize
+ prioDatabaseIndexSize
+
+ prioReplSetMemberState
+ prioReplSetMemberHealthStatus
+ prioReplSetMemberReplicationLagTime
+ prioReplSetMemberHeartbeatLatencyTime
+ prioReplSetMemberPingRTTTime
+ prioReplSetMemberUptime
+
+ prioShardingNodesCount
+ prioShardingShardedDatabasesCount
+ prioShardingShardedCollectionsCount
+ prioShardChunks
+)
+
+const (
+ chartPxDatabase = "database_"
+ chartPxReplSetMember = "replica_set_member_"
+ chartPxShard = "sharding_shard_"
+)
+
+// these charts are expected to be available in many versions
+var chartsServerStatus = module.Charts{
+ chartOperationsByTypeRate.Copy(),
+ chartDocumentOperationsRate.Copy(),
+ chartScannedIndexesRate.Copy(),
+ chartScannedDocumentsRate.Copy(),
+
+ chartConnectionsUsage.Copy(),
+ chartConnectionsByStateCount.Copy(),
+ chartConnectionsRate.Copy(),
+
+ chartNetworkTrafficRate.Copy(),
+ chartNetworkRequestsRate.Copy(),
+
+ chartMemoryResidentSize.Copy(),
+ chartMemoryVirtualSize.Copy(),
+ chartMemoryPageFaultsRate.Copy(),
+
+ chartAssertsRate.Copy(),
+}
+
+var chartsTmplDatabase = module.Charts{
+ chartTmplDatabaseCollectionsCount.Copy(),
+ chartTmplDatabaseIndexesCount.Copy(),
+ chartTmplDatabaseViewsCount.Copy(),
+ chartTmplDatabaseDocumentsCount.Copy(),
+ chartTmplDatabaseDataSize.Copy(),
+ chartTmplDatabaseStorageSize.Copy(),
+ chartTmplDatabaseIndexSize.Copy(),
+}
+
+var chartsTmplReplSetMember = module.Charts{
+ chartTmplReplSetMemberState.Copy(),
+ chartTmplReplSetMemberHealthStatus.Copy(),
+ chartTmplReplSetMemberReplicationLagTime.Copy(),
+ chartTmplReplSetMemberHeartbeatLatencyTime.Copy(),
+ chartTmplReplSetMemberPingRTTTime.Copy(),
+ chartTmplReplSetMemberUptime.Copy(),
+}
+
+var chartsSharding = module.Charts{
+ chartShardingNodesCount.Copy(),
+ chartShardingShardedDatabases.Copy(),
+ chartShardingShardedCollectionsCount.Copy(),
+}
+
+var chartsTmplShardingShard = module.Charts{
+ chartTmplShardChunks.Copy(),
+}
+
+var (
+ chartOperationsRate = module.Chart{
+ ID: "operations_rate",
+ Title: "Operations rate",
+ Units: "operations/s",
+ Fam: "operations",
+ Ctx: "mongodb.operations_rate",
+ Priority: prioOperationsRate,
+ Dims: module.Dims{
+ {ID: "operations_latencies_reads_ops", Name: "reads", Algo: module.Incremental},
+ {ID: "operations_latencies_writes_ops", Name: "writes", Algo: module.Incremental},
+ {ID: "operations_latencies_commands_ops", Name: "commands", Algo: module.Incremental},
+ },
+ }
+ chartOperationsLatencyTime = module.Chart{
+ ID: "operations_latency_time",
+ Title: "Operations Latency",
+ Units: "milliseconds",
+ Fam: "operations",
+ Ctx: "mongodb.operations_latency_time",
+ Priority: prioOperationsLatencyTime,
+ Dims: module.Dims{
+ {ID: "operations_latencies_reads_latency", Name: "reads", Algo: module.Incremental, Div: 1000},
+ {ID: "operations_latencies_writes_latency", Name: "writes", Algo: module.Incremental, Div: 1000},
+ {ID: "operations_latencies_commands_latency", Name: "commands", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartOperationsByTypeRate = module.Chart{
+ ID: "operations_by_type_rate",
+ Title: "Operations by type",
+ Units: "operations/s",
+ Fam: "operations",
+ Ctx: "mongodb.operations_by_type_rate",
+ Priority: prioOperationsByTypeRate,
+ Dims: module.Dims{
+ {ID: "operations_insert", Name: "insert", Algo: module.Incremental},
+ {ID: "operations_query", Name: "query", Algo: module.Incremental},
+ {ID: "operations_update", Name: "update", Algo: module.Incremental},
+ {ID: "operations_delete", Name: "delete", Algo: module.Incremental},
+ {ID: "operations_getmore", Name: "getmore", Algo: module.Incremental},
+ {ID: "operations_command", Name: "command", Algo: module.Incremental},
+ },
+ }
+ chartDocumentOperationsRate = module.Chart{
+ ID: "document_operations_rate",
+ Title: "Document operations",
+ Units: "operations/s",
+ Fam: "operations",
+ Ctx: "mongodb.document_operations_rate",
+ Type: module.Stacked,
+ Priority: prioDocumentOperationsRate,
+ Dims: module.Dims{
+ {ID: "metrics_document_inserted", Name: "inserted", Algo: module.Incremental},
+ {ID: "metrics_document_deleted", Name: "deleted", Algo: module.Incremental},
+ {ID: "metrics_document_returned", Name: "returned", Algo: module.Incremental},
+ {ID: "metrics_document_updated", Name: "updated", Algo: module.Incremental},
+ },
+ }
+ chartScannedIndexesRate = module.Chart{
+ ID: "scanned_indexes_rate",
+ Title: "Scanned indexes",
+ Units: "indexes/s",
+ Fam: "operations",
+ Ctx: "mongodb.scanned_indexes_rate",
+ Priority: prioScannedIndexesRate,
+ Dims: module.Dims{
+ {ID: "metrics_query_executor_scanned", Name: "scanned", Algo: module.Incremental},
+ },
+ }
+ chartScannedDocumentsRate = module.Chart{
+ ID: "scanned_documents_rate",
+ Title: "Scanned documents",
+ Units: "documents/s",
+ Fam: "operations",
+ Ctx: "mongodb.scanned_documents_rate",
+ Priority: prioScannedDocumentsRate,
+ Dims: module.Dims{
+ {ID: "metrics_query_executor_scanned_objects", Name: "scanned", Algo: module.Incremental},
+ },
+ }
+
+ chartGlobalLockActiveClientsCount = module.Chart{
+ ID: "active_clients_count",
+ Title: "Connected clients",
+ Units: "clients",
+ Fam: "clients",
+ Ctx: "mongodb.active_clients_count",
+ Priority: prioActiveClientsCount,
+ Dims: module.Dims{
+ {ID: "global_lock_active_clients_readers", Name: "readers"},
+ {ID: "global_lock_active_clients_writers", Name: "writers"},
+ },
+ }
+ chartGlobalLockCurrentQueueCount = module.Chart{
+ ID: "queued_operations",
+ Title: "Queued operations because of a lock",
+ Units: "operations",
+ Fam: "clients",
+ Ctx: "mongodb.queued_operations_count",
+ Priority: prioQueuedOperationsCount,
+ Dims: module.Dims{
+ {ID: "global_lock_current_queue_readers", Name: "readers"},
+ {ID: "global_lock_current_queue_writers", Name: "writers"},
+ },
+ }
+
+ chartConnectionsUsage = module.Chart{
+ ID: "connections_usage",
+ Title: "Connections usage",
+ Units: "connections",
+ Fam: "connections",
+ Ctx: "mongodb.connections_usage",
+ Type: module.Stacked,
+ Priority: prioConnectionsUsage,
+ Dims: module.Dims{
+ {ID: "connections_available", Name: "available"},
+ {ID: "connections_current", Name: "used"},
+ },
+ }
+ chartConnectionsByStateCount = module.Chart{
+ ID: "connections_by_state_count",
+ Title: "Connections By State",
+ Units: "connections",
+ Fam: "connections",
+ Ctx: "mongodb.connections_by_state_count",
+ Priority: prioConnectionsByStateCount,
+ Dims: module.Dims{
+ {ID: "connections_active", Name: "active"},
+ {ID: "connections_threaded", Name: "threaded"},
+ {ID: "connections_exhaust_is_master", Name: "exhaust_is_master"},
+ {ID: "connections_exhaust_hello", Name: "exhaust_hello"},
+ {ID: "connections_awaiting_topology_changes", Name: "awaiting_topology_changes"},
+ },
+ }
+ chartConnectionsRate = module.Chart{
+ ID: "connections_rate",
+ Title: "Connections Rate",
+ Units: "connections/s",
+ Fam: "connections",
+ Ctx: "mongodb.connections_rate",
+ Priority: prioConnectionsRate,
+ Dims: module.Dims{
+ {ID: "connections_total_created", Name: "created", Algo: module.Incremental},
+ },
+ }
+
+ chartNetworkTrafficRate = module.Chart{
+ ID: "network_traffic",
+ Title: "Network traffic",
+ Units: "bytes/s",
+ Fam: "network",
+ Ctx: "mongodb.network_traffic_rate",
+ Priority: prioNetworkTrafficRate,
+ Type: module.Area,
+ Dims: module.Dims{
+ {ID: "network_bytes_in", Name: "in", Algo: module.Incremental},
+ {ID: "network_bytes_out", Name: "out", Algo: module.Incremental},
+ },
+ }
+ chartNetworkRequestsRate = module.Chart{
+ ID: "network_requests_rate",
+ Title: "Network Requests",
+ Units: "requests/s",
+ Fam: "network",
+ Ctx: "mongodb.network_requests_rate",
+ Priority: prioNetworkRequestsRate,
+ Dims: module.Dims{
+ {ID: "network_requests", Name: "requests", Algo: module.Incremental},
+ },
+ }
+ chartNetworkSlowDNSResolutionsRate = module.Chart{
+ ID: "network_slow_dns_resolutions_rate",
+ Title: "Slow DNS resolution operations",
+ Units: "resolutions/s",
+ Fam: "network",
+ Ctx: "mongodb.network_slow_dns_resolutions_rate",
+ Priority: prioNetworkSlowDNSResolutionsRate,
+ Dims: module.Dims{
+ {ID: "network_slow_dns_operations", Name: "slow_dns", Algo: module.Incremental},
+ },
+ }
+ chartNetworkSlowSSLHandshakesRate = module.Chart{
+ ID: "network_slow_ssl_handshakes_rate",
+ Title: "Slow SSL handshake operations",
+ Units: "handshakes/s",
+ Fam: "network",
+ Ctx: "mongodb.network_slow_ssl_handshakes_rate",
+ Priority: prioNetworkSlowSSLHandshakesRate,
+ Dims: module.Dims{
+ {ID: "network_slow_ssl_operations", Name: "slow_ssl", Algo: module.Incremental},
+ },
+ }
+
+ chartMemoryResidentSize = module.Chart{
+ ID: "memory_resident_size",
+ Title: "Used resident memory",
+ Units: "bytes",
+ Fam: "memory",
+ Ctx: "mongodb.memory_resident_size",
+ Priority: prioMemoryResidentSize,
+ Dims: module.Dims{
+ {ID: "memory_resident", Name: "used"},
+ },
+ }
+ chartMemoryVirtualSize = module.Chart{
+ ID: "memory_virtual_size",
+ Title: "Used virtual memory",
+ Units: "bytes",
+ Fam: "memory",
+ Ctx: "mongodb.memory_virtual_size",
+ Priority: prioMemoryVirtualSize,
+ Dims: module.Dims{
+ {ID: "memory_virtual", Name: "used"},
+ },
+ }
+ chartMemoryPageFaultsRate = module.Chart{
+ ID: "memory_page_faults",
+ Title: "Memory page faults",
+ Units: "pgfaults/s",
+ Fam: "memory",
+ Ctx: "mongodb.memory_page_faults_rate",
+ Priority: prioMemoryPageFaultsRate,
+ Dims: module.Dims{
+ {ID: "extra_info_page_faults", Name: "pgfaults", Algo: module.Incremental},
+ },
+ }
+ chartMemoryTCMallocStatsChart = module.Chart{
+ ID: "memory_tcmalloc_stats",
+ Title: "TCMalloc statistics",
+ Units: "bytes",
+ Fam: "memory",
+ Ctx: "mongodb.memory_tcmalloc_stats",
+ Priority: prioMemoryTCMallocStats,
+ Dims: module.Dims{
+ {ID: "tcmalloc_generic_current_allocated_bytes", Name: "allocated"},
+ {ID: "tcmalloc_central_cache_free_bytes", Name: "central_cache_freelist"},
+ {ID: "tcmalloc_transfer_cache_free_bytes", Name: "transfer_cache_freelist"},
+ {ID: "tcmalloc_thread_cache_free_bytes", Name: "thread_cache_freelists"},
+ {ID: "tcmalloc_pageheap_free_bytes", Name: "pageheap_freelist"},
+ {ID: "tcmalloc_pageheap_unmapped_bytes", Name: "pageheap_unmapped"},
+ },
+ }
+
+ chartAssertsRate = module.Chart{
+ ID: "asserts_rate",
+ Title: "Raised assertions",
+ Units: "asserts/s",
+ Fam: "asserts",
+ Ctx: "mongodb.asserts_rate",
+ Type: module.Stacked,
+ Priority: prioAssertsRate,
+ Dims: module.Dims{
+ {ID: "asserts_regular", Name: "regular", Algo: module.Incremental},
+ {ID: "asserts_warning", Name: "warning", Algo: module.Incremental},
+ {ID: "asserts_msg", Name: "msg", Algo: module.Incremental},
+ {ID: "asserts_user", Name: "user", Algo: module.Incremental},
+ {ID: "asserts_tripwire", Name: "tripwire", Algo: module.Incremental},
+ {ID: "asserts_rollovers", Name: "rollovers", Algo: module.Incremental},
+ },
+ }
+
+ chartTransactionsCount = module.Chart{
+ ID: "transactions_count",
+ Title: "Current transactions",
+ Units: "transactions",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_count",
+ Priority: prioTransactionsCount,
+ Dims: module.Dims{
+ {ID: "txn_active", Name: "active"},
+ {ID: "txn_inactive", Name: "inactive"},
+ {ID: "txn_open", Name: "open"},
+ {ID: "txn_prepared", Name: "prepared"},
+ },
+ }
+ chartTransactionsRate = module.Chart{
+ ID: "transactions_rate",
+ Title: "Transactions rate",
+ Units: "transactions/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_rate",
+ Priority: prioTransactionsRate,
+ Dims: module.Dims{
+ {ID: "txn_total_started", Name: "started", Algo: module.Incremental},
+ {ID: "txn_total_aborted", Name: "aborted", Algo: module.Incremental},
+ {ID: "txn_total_committed", Name: "committed", Algo: module.Incremental},
+ {ID: "txn_total_prepared", Name: "prepared", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsNoShardsCommitsRate = module.Chart{
+ ID: "transactions_no_shards_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsNoShardsCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "noShards"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_no_shards_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_no_shards_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsNoShardsCommitsDurationTime = module.Chart{
+ ID: "transactions_no_shards_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsNoShardsCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "noShards"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_no_shards_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartTransactionsSingleShardCommitsRate = module.Chart{
+ ID: "transactions_single_shard_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsSingleShardCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "singleShard"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_single_shard_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_single_shard_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsSingleShardCommitsDurationTime = module.Chart{
+ ID: "transactions_single_shard_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsSingleShardCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "singleShard"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_single_shard_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartTransactionsSingleWriteShardCommitsRate = module.Chart{
+ ID: "transactions_single_write_shard_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsSingleWriteShardCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "singleWriteShard"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_single_write_shard_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_single_write_shard_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsSingleWriteShardCommitsDurationTime = module.Chart{
+ ID: "transactions_single_write_shard_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsSingleWriteShardCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "singleWriteShard"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_single_write_shard_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartTransactionsReadOnlyCommitsRate = module.Chart{
+ ID: "transactions_read_only_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsReadOnlyCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "readOnly"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_read_only_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_read_only_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsReadOnlyCommitsDurationTime = module.Chart{
+ ID: "transactions_read_only_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsReadOnlyCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "readOnly"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_read_only_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartTransactionsTwoPhaseCommitCommitsRate = module.Chart{
+ ID: "transactions_two_phase_commit_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsTwoPhaseCommitCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "twoPhaseCommit"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_two_phase_commit_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_two_phase_commit_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsTwoPhaseCommitCommitsDurationTime = module.Chart{
+ ID: "transactions_two_phase_commit_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsTwoPhaseCommitCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "twoPhaseCommit"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_two_phase_commit_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+ chartTransactionsRecoverWithTokenCommitsRate = module.Chart{
+ ID: "transactions_recover_with_token_commits_rate",
+ Title: "Transactions commits",
+ Units: "commits/s",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_rate",
+ Priority: prioTransactionsRecoverWithTokenCommitsRate,
+ Type: module.Stacked,
+ Labels: []module.Label{{Key: "commit_type", Value: "recoverWithToken"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_recover_with_token_successful", Name: "success", Algo: module.Incremental},
+ {ID: "txn_commit_types_recover_with_token_unsuccessful", Name: "fail", Algo: module.Incremental},
+ },
+ }
+ chartTransactionsRecoverWithTokenCommitsDurationTime = module.Chart{
+ ID: "transactions_recover_with_token_commits_duration_time",
+ Title: "Transactions successful commits duration",
+ Units: "milliseconds",
+ Fam: "transactions",
+ Ctx: "mongodb.transactions_commits_duration_time",
+ Priority: prioTransactionsRecoverWithTokenCommitsDurationTime,
+ Labels: []module.Label{{Key: "commit_type", Value: "recoverWithToken"}},
+ Dims: module.Dims{
+ {ID: "txn_commit_types_recover_with_token_successful_duration_micros", Name: "commits", Algo: module.Incremental, Div: 1000},
+ },
+ }
+
+ chartGlobalLockAcquisitionsRate = module.Chart{
+ ID: "global_lock_acquisitions_rate",
+ Title: "Global lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioGlobalLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "global"}},
+ Dims: module.Dims{
+ {ID: "locks_global_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_global_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_global_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_global_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+ chartDatabaseLockAcquisitionsRate = module.Chart{
+ ID: "database_lock_acquisitions_rate",
+ Title: "Database lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioDatabaseLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "database"}},
+ Dims: module.Dims{
+ {ID: "locks_database_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_database_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_database_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_database_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+ chartCollectionLockAcquisitionsRate = module.Chart{
+ ID: "collection_lock_acquisitions_rate",
+ Title: "Collection lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioCollectionLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "collection"}},
+ Dims: module.Dims{
+ {ID: "locks_collection_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_collection_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_collection_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_collection_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+ chartMutexLockAcquisitionsRate = module.Chart{
+ ID: "mutex_lock_acquisitions_rate",
+ Title: "Mutex lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioMutexLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "mutex"}},
+ Dims: module.Dims{
+ {ID: "locks_mutex_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_mutex_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_mutex_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_mutex_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+ chartMetadataLockAcquisitionsRate = module.Chart{
+ ID: "metadata_lock_acquisitions_rate",
+ Title: "Metadata lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioMetadataLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "metadata"}},
+ Dims: module.Dims{
+ {ID: "locks_metadata_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_metadata_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_metadata_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_metadata_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+ chartOpLogLockAcquisitionsRate = module.Chart{
+ ID: "oplog_lock_acquisitions_rate",
+ Title: "Operations log lock acquisitions",
+ Units: "acquisitions/s",
+ Fam: "locks",
+ Ctx: "mongodb.lock_acquisitions_rate",
+ Priority: prioOpLogLockAcquisitionsRate,
+ Labels: []module.Label{{Key: "lock_type", Value: "oplog"}},
+ Dims: module.Dims{
+ {ID: "locks_oplog_acquire_shared", Name: "shared", Algo: module.Incremental},
+ {ID: "locks_oplog_acquire_exclusive", Name: "exclusive", Algo: module.Incremental},
+ {ID: "locks_oplog_acquire_intent_shared", Name: "intent_shared", Algo: module.Incremental},
+ {ID: "locks_oplog_acquire_intent_exclusive", Name: "intent_exclusive", Algo: module.Incremental},
+ },
+ }
+
+ chartCursorsOpenCount = module.Chart{
+ ID: "cursors_open_count",
+ Title: "Open cursors",
+ Units: "cursors",
+ Fam: "cursors",
+ Ctx: "mongodb.cursors_open_count",
+ Priority: prioCursorsOpenCount,
+ Dims: module.Dims{
+ {ID: "metrics_cursor_open_total", Name: "open"},
+ },
+ }
+ chartCursorsOpenNoTimeoutCount = module.Chart{
+ ID: "cursors_open_no_timeout_count",
+ Title: "Open cursors with disabled timeout",
+ Units: "cursors",
+ Fam: "cursors",
+ Ctx: "mongodb.cursors_open_no_timeout_count",
+ Priority: prioCursorsOpenNoTimeoutCount,
+ Dims: module.Dims{
+ {ID: "metrics_cursor_open_no_timeout", Name: "open_no_timeout"},
+ },
+ }
+ chartCursorsOpenedRate = module.Chart{
+ ID: "cursors_opened_rate",
+ Title: "Opened cursors rate",
+ Units: "cursors/s",
+ Fam: "cursors",
+ Ctx: "mongodb.cursors_opened_rate",
+ Priority: prioCursorsOpenedRate,
+ Dims: module.Dims{
+ {ID: "metrics_cursor_total_opened", Name: "opened"},
+ },
+ }
+ chartCursorsTimedOutRate = module.Chart{
+ ID: "cursors_timed_out_rate",
+ Title: "Timed-out cursors",
+ Units: "cursors/s",
+ Fam: "cursors",
+ Ctx: "mongodb.cursors_timed_out_rate",
+ Priority: prioTimedOutCursorsRate,
+ Dims: module.Dims{
+ {ID: "metrics_cursor_timed_out", Name: "timed_out"},
+ },
+ }
+ chartCursorsByLifespanCount = module.Chart{
+ ID: "cursors_by_lifespan_count",
+ Title: "Cursors lifespan",
+ Units: "cursors",
+ Fam: "cursors",
+ Ctx: "mongodb.cursors_by_lifespan_count",
+ Priority: prioCursorsByLifespanCount,
+ Type: module.Stacked,
+ Dims: module.Dims{
+ {ID: "metrics_cursor_lifespan_less_than_1_second", Name: "le_1s"},
+ {ID: "metrics_cursor_lifespan_less_than_5_seconds", Name: "1s_5s"},
+ {ID: "metrics_cursor_lifespan_less_than_15_seconds", Name: "5s_15s"},
+ {ID: "metrics_cursor_lifespan_less_than_30_seconds", Name: "15s_30s"},
+ {ID: "metrics_cursor_lifespan_less_than_1_minute", Name: "30s_1m"},
+ {ID: "metrics_cursor_lifespan_less_than_10_minutes", Name: "1m_10m"},
+ {ID: "metrics_cursor_lifespan_greater_than_or_equal_10_minutes", Name: "ge_10m"},
+ },
+ }
+
+ chartWiredTigerConcurrentReadTransactionsUsage = module.Chart{
+ ID: "wiredtiger_concurrent_read_transactions_usage",
+ Title: "Wired Tiger concurrent read transactions usage",
+ Units: "transactions",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_concurrent_read_transactions_usage",
+ Priority: prioWiredTigerConcurrentReadTransactionsUsage,
+ Type: module.Stacked,
+ Dims: module.Dims{
+ {ID: "wiredtiger_concurrent_txn_read_available", Name: "available"},
+ {ID: "wiredtiger_concurrent_txn_read_out", Name: "used"},
+ },
+ }
+ chartWiredTigerConcurrentWriteTransactionsUsage = module.Chart{
+ ID: "wiredtiger_concurrent_write_transactions_usage",
+ Title: "Wired Tiger concurrent write transactions usage",
+ Units: "transactions",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_concurrent_write_transactions_usage",
+ Priority: prioWiredTigerConcurrentWriteTransactionsUsage,
+ Type: module.Stacked,
+ Dims: module.Dims{
+ {ID: "wiredtiger_concurrent_txn_write_available", Name: "available"},
+ {ID: "wiredtiger_concurrent_txn_write_out", Name: "used"},
+ },
+ }
+ chartWiredTigerCacheUsage = module.Chart{
+ ID: "wiredtiger_cache_usage",
+ Title: "Wired Tiger cache usage",
+ Units: "bytes",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_cache_usage",
+ Priority: prioWiredTigerCacheUsage,
+ Type: module.Stacked,
+ Dims: module.Dims{
+ {ID: "wiredtiger_cache_currently_in_cache_bytes", Name: "used"},
+ },
+ }
+ chartWiredTigerCacheDirtySpaceSize = module.Chart{
+ ID: "wiredtiger_cache_dirty_space_size",
+ Title: "Wired Tiger cache dirty space size",
+ Units: "bytes",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_cache_dirty_space_size",
+ Priority: prioWiredTigerCacheDirtySpaceSize,
+ Dims: module.Dims{
+ {ID: "wiredtiger_cache_tracked_dirty_in_the_cache_bytes", Name: "dirty"},
+ },
+ }
+ chartWiredTigerCacheIORate = module.Chart{
+ ID: "wiredtiger_cache_io_rate",
+ Title: "Wired Tiger IO activity",
+ Units: "pages/s",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_cache_io_rate",
+ Priority: prioWiredTigerCacheIORate,
+ Dims: module.Dims{
+ {ID: "wiredtiger_cache_read_into_cache_pages", Name: "read", Algo: module.Incremental},
+ {ID: "wiredtiger_cache_written_from_cache_pages", Name: "written", Algo: module.Incremental},
+ },
+ }
+ chartWiredTigerCacheEvictionsRate = module.Chart{
+ ID: "wiredtiger_cache_eviction_rate",
+ Title: "Wired Tiger cache evictions",
+ Units: "pages/s",
+ Fam: "wiredtiger",
+ Ctx: "mongodb.wiredtiger_cache_evictions_rate",
+ Type: module.Stacked,
+ Priority: prioWiredTigerCacheEvictionsRate,
+ Dims: module.Dims{
+ {ID: "wiredtiger_cache_unmodified_evicted_pages", Name: "unmodified", Algo: module.Incremental},
+ {ID: "wiredtiger_cache_modified_evicted_pages", Name: "modified", Algo: module.Incremental},
+ },
+ }
+)
+
+var (
+ chartTmplDatabaseCollectionsCount = &module.Chart{
+ ID: chartPxDatabase + "%s_collections_count",
+ Title: "Database collections",
+ Units: "collections",
+ Fam: "databases",
+ Ctx: "mongodb.database_collections_count",
+ Priority: prioDatabaseCollectionsCount,
+ Dims: module.Dims{
+ {ID: "database_%s_collections", Name: "collections"},
+ },
+ }
+ chartTmplDatabaseIndexesCount = &module.Chart{
+ ID: chartPxDatabase + "%s_indexes_count",
+ Title: "Database indexes",
+ Units: "indexes",
+ Fam: "databases",
+ Ctx: "mongodb.database_indexes_count",
+ Priority: prioDatabaseIndexesCount,
+ Dims: module.Dims{
+ {ID: "database_%s_indexes", Name: "indexes"},
+ },
+ }
+ chartTmplDatabaseViewsCount = &module.Chart{
+ ID: chartPxDatabase + "%s_views_count",
+ Title: "Database views",
+ Units: "views",
+ Fam: "databases",
+ Ctx: "mongodb.database_views_count",
+ Priority: prioDatabaseViewsCount,
+ Dims: module.Dims{
+ {ID: "database_%s_views", Name: "views"},
+ },
+ }
+ chartTmplDatabaseDocumentsCount = &module.Chart{
+ ID: chartPxDatabase + "%s_documents_count",
+ Title: "Database documents",
+ Units: "documents",
+ Fam: "databases",
+ Ctx: "mongodb.database_documents_count",
+ Priority: prioDatabaseDocumentsCount,
+ Dims: module.Dims{
+ {ID: "database_%s_documents", Name: "documents"},
+ },
+ }
+ chartTmplDatabaseDataSize = &module.Chart{
+ ID: chartPxDatabase + "%s_data_size",
+ Title: "Database data size",
+ Units: "bytes",
+ Fam: "databases",
+ Ctx: "mongodb.database_data_size",
+ Priority: prioDatabaseDataSize,
+ Dims: module.Dims{
+ {ID: "database_%s_data_size", Name: "data_size"},
+ },
+ }
+ chartTmplDatabaseStorageSize = &module.Chart{
+ ID: chartPxDatabase + "%s_storage_size",
+ Title: "Database storage size",
+ Units: "bytes",
+ Fam: "databases",
+ Ctx: "mongodb.database_storage_size",
+ Priority: prioDatabaseStorageSize,
+ Dims: module.Dims{
+ {ID: "database_%s_storage_size", Name: "storage_size"},
+ },
+ }
+ chartTmplDatabaseIndexSize = &module.Chart{
+ ID: chartPxDatabase + "%s_index_size",
+ Title: "Database index size",
+ Units: "bytes",
+ Fam: "databases",
+ Ctx: "mongodb.database_index_size",
+ Priority: prioDatabaseIndexSize,
+ Dims: module.Dims{
+ {ID: "database_%s_index_size", Name: "index_size"},
+ },
+ }
+)
+
+var (
+ chartTmplReplSetMemberState = &module.Chart{
+ ID: chartPxReplSetMember + "%s_state",
+ Title: "Replica Set member state",
+ Units: "state",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_state",
+ Priority: prioReplSetMemberState,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_state_primary", Name: "primary"},
+ {ID: "repl_set_member_%s_state_startup", Name: "startup"},
+ {ID: "repl_set_member_%s_state_secondary", Name: "secondary"},
+ {ID: "repl_set_member_%s_state_recovering", Name: "recovering"},
+ {ID: "repl_set_member_%s_state_startup2", Name: "startup2"},
+ {ID: "repl_set_member_%s_state_unknown", Name: "unknown"},
+ {ID: "repl_set_member_%s_state_arbiter", Name: "arbiter"},
+ {ID: "repl_set_member_%s_state_down", Name: "down"},
+ {ID: "repl_set_member_%s_state_rollback", Name: "rollback"},
+ {ID: "repl_set_member_%s_state_removed", Name: "removed"},
+ },
+ }
+ chartTmplReplSetMemberHealthStatus = &module.Chart{
+ ID: chartPxReplSetMember + "%s_health_status",
+ Title: "Replica Set member health status",
+ Units: "status",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_health_status",
+ Priority: prioReplSetMemberHealthStatus,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_health_status_up", Name: "up"},
+ {ID: "repl_set_member_%s_health_status_down", Name: "down"},
+ },
+ }
+ chartTmplReplSetMemberReplicationLagTime = &module.Chart{
+ ID: chartPxReplSetMember + "%s_replication_lag_time",
+ Title: "Replica Set member replication lag",
+ Units: "milliseconds",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_replication_lag_time",
+ Priority: prioReplSetMemberReplicationLagTime,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_replication_lag", Name: "replication_lag"},
+ },
+ }
+ chartTmplReplSetMemberHeartbeatLatencyTime = &module.Chart{
+ ID: chartPxReplSetMember + "%s_heartbeat_latency_time",
+ Title: "Replica Set member heartbeat latency",
+ Units: "milliseconds",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_heartbeat_latency_time",
+ Priority: prioReplSetMemberHeartbeatLatencyTime,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_heartbeat_latency", Name: "heartbeat_latency"},
+ },
+ }
+ chartTmplReplSetMemberPingRTTTime = &module.Chart{
+ ID: chartPxReplSetMember + "%s_ping_rtt_time",
+ Title: "Replica Set member ping RTT",
+ Units: "milliseconds",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_ping_rtt_time",
+ Priority: prioReplSetMemberPingRTTTime,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_ping_rtt", Name: "ping_rtt"},
+ },
+ }
+ chartTmplReplSetMemberUptime = &module.Chart{
+ ID: chartPxReplSetMember + "%s_uptime",
+ Title: "Replica Set member uptime",
+ Units: "seconds",
+ Fam: "replica sets",
+ Ctx: "mongodb.repl_set_member_uptime",
+ Priority: prioReplSetMemberUptime,
+ Dims: module.Dims{
+ {ID: "repl_set_member_%s_uptime", Name: "uptime"},
+ },
+ }
+)
+
+var (
+ chartShardingNodesCount = &module.Chart{
+ ID: "sharding_nodes_count",
+ Title: "Sharding Nodes",
+ Units: "nodes",
+ Fam: "sharding",
+ Ctx: "mongodb.sharding_nodes_count",
+ Type: module.Stacked,
+ Priority: prioShardingNodesCount,
+ Dims: module.Dims{
+ {ID: "shard_nodes_aware", Name: "shard_aware"},
+ {ID: "shard_nodes_unaware", Name: "shard_unaware"},
+ },
+ }
+ chartShardingShardedDatabases = &module.Chart{
+ ID: "sharding_sharded_databases_count",
+ Title: "Sharded databases",
+ Units: "databases",
+ Fam: "sharding",
+ Ctx: "mongodb.sharding_sharded_databases_count",
+ Type: module.Stacked,
+ Priority: prioShardingShardedDatabasesCount,
+ Dims: module.Dims{
+ {ID: "shard_databases_partitioned", Name: "partitioned"},
+ {ID: "shard_databases_unpartitioned", Name: "unpartitioned"},
+ },
+ }
+
+ chartShardingShardedCollectionsCount = &module.Chart{
+ ID: "sharding_sharded_collections_count",
+ Title: "Sharded collections",
+ Units: "collections",
+ Fam: "sharding",
+ Ctx: "mongodb.sharding_sharded_collections_count",
+ Type: module.Stacked,
+ Priority: prioShardingShardedCollectionsCount,
+ Dims: module.Dims{
+ {ID: "shard_collections_partitioned", Name: "partitioned"},
+ {ID: "shard_collections_unpartitioned", Name: "unpartitioned"},
+ },
+ }
+
+ chartTmplShardChunks = &module.Chart{
+ ID: chartPxShard + "%s_chunks",
+ Title: "Shard chunks",
+ Units: "chunks",
+ Fam: "sharding",
+ Ctx: "mongodb.sharding_shard_chunks_count",
+ Priority: prioShardChunks,
+ Dims: module.Dims{
+ {ID: "shard_id_%s_chunks", Name: "chunks"},
+ },
+ }
+)
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/client.go b/src/go/collectors/go.d.plugin/modules/mongodb/client.go
new file mode 100644
index 000000000..eb36fa8ac
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/client.go
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+)
+
+const (
+ mongos = "mongos"
+)
+
+type mongoConn interface {
+ serverStatus() (*documentServerStatus, error)
+ listDatabaseNames() ([]string, error)
+ dbStats(name string) (*documentDBStats, error)
+ isReplicaSet() bool
+ isMongos() bool
+ replSetGetStatus() (*documentReplSetStatus, error)
+ shardNodes() (*documentShardNodesResult, error)
+ shardDatabasesPartitioning() (*documentPartitionedResult, error)
+ shardCollectionsPartitioning() (*documentPartitionedResult, error)
+ shardChunks() (map[string]int64, error)
+ initClient(uri string, timeout time.Duration) error
+ close() error
+}
+
+type mongoClient struct {
+ client *mongo.Client
+ timeout time.Duration
+ replicaSetFlag *bool
+ mongosFlag *bool
+}
+
+func (c *mongoClient) serverStatus() (*documentServerStatus, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ cmd := bson.D{
+ {Key: "serverStatus", Value: 1},
+ {Key: "repl", Value: 1},
+ {Key: "metrics",
+ Value: bson.D{
+ {Key: "document", Value: true},
+ {Key: "cursor", Value: true},
+ {Key: "queryExecutor", Value: true},
+ {Key: "apiVersions", Value: false},
+ {Key: "aggStageCounters", Value: false},
+ {Key: "commands", Value: false},
+ {Key: "dotsAndDollarsFields", Value: false},
+ {Key: "getLastError", Value: false},
+ {Key: "mongos", Value: false},
+ {Key: "operation", Value: false},
+ {Key: "operatorCounters", Value: false},
+ {Key: "query", Value: false},
+ {Key: "record", Value: false},
+ {Key: "repl", Value: false},
+ {Key: "storage", Value: false},
+ {Key: "ttl", Value: false},
+ },
+ },
+ }
+ var status *documentServerStatus
+
+ err := c.client.Database("admin").RunCommand(ctx, cmd).Decode(&status)
+ if err != nil {
+ return nil, err
+ }
+
+ isReplSet := status.Repl != nil
+ c.replicaSetFlag = &isReplSet
+
+ isMongos := status.Process == mongos
+ c.mongosFlag = &isMongos
+
+ return status, err
+}
+
+func (c *mongoClient) listDatabaseNames() ([]string, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ return c.client.ListDatabaseNames(ctx, bson.M{})
+}
+
+func (c *mongoClient) dbStats(name string) (*documentDBStats, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ cmd := bson.M{"dbStats": 1}
+ var stats documentDBStats
+
+ if err := c.client.Database(name).RunCommand(ctx, cmd).Decode(&stats); err != nil {
+ return nil, err
+ }
+
+ return &stats, nil
+}
+
+func (c *mongoClient) isReplicaSet() bool {
+ if c.replicaSetFlag != nil {
+ return *c.replicaSetFlag
+ }
+
+ status, err := c.serverStatus()
+ if err != nil {
+ return false
+ }
+
+ return status.Repl != nil
+}
+
+func (c *mongoClient) isMongos() bool {
+ if c.mongosFlag != nil {
+ return *c.mongosFlag
+ }
+
+ status, err := c.serverStatus()
+ if err != nil {
+ return false
+ }
+
+ return status.Process == mongos
+}
+
+func (c *mongoClient) replSetGetStatus() (*documentReplSetStatus, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ var status *documentReplSetStatus
+ cmd := bson.M{"replSetGetStatus": 1}
+
+ err := c.client.Database("admin").RunCommand(ctx, cmd).Decode(&status)
+ if err != nil {
+ return nil, err
+ }
+
+ return status, err
+}
+
+func (c *mongoClient) shardNodes() (*documentShardNodesResult, error) {
+ collection := "shards"
+ groupStage := bson.D{{Key: "$sortByCount", Value: "$state"}}
+
+ nodesByState, err := c.shardCollectAggregation(collection, []bson.D{groupStage})
+ if err != nil {
+ return nil, err
+ }
+
+ return &documentShardNodesResult{nodesByState.True, nodesByState.False}, nil
+}
+
+func (c *mongoClient) shardDatabasesPartitioning() (*documentPartitionedResult, error) {
+ collection := "databases"
+ groupStage := bson.D{{Key: "$sortByCount", Value: "$partitioned"}}
+
+ partitioning, err := c.shardCollectAggregation(collection, []bson.D{groupStage})
+ if err != nil {
+ return nil, err
+ }
+
+ return &documentPartitionedResult{partitioning.True, partitioning.False}, nil
+}
+
+func (c *mongoClient) shardCollectionsPartitioning() (*documentPartitionedResult, error) {
+ collection := "collections"
+ matchStage := bson.D{{Key: "$match", Value: bson.D{{Key: "dropped", Value: false}}}}
+ countStage := bson.D{{Key: "$sortByCount", Value: bson.D{{Key: "$eq", Value: bson.A{"$distributionMode", "sharded"}}}}}
+
+ partitioning, err := c.shardCollectAggregation(collection, []bson.D{matchStage, countStage})
+ if err != nil {
+ return nil, err
+ }
+
+ return &documentPartitionedResult{partitioning.True, partitioning.False}, nil
+}
+
+func (c *mongoClient) shardCollectAggregation(collection string, aggr []bson.D) (*documentAggrResult, error) {
+ rows, err := c.dbAggregate(collection, aggr)
+ if err != nil {
+ return nil, err
+ }
+
+ result := &documentAggrResult{}
+
+ for _, row := range rows {
+ if row.Bool {
+ result.True = row.Count
+ } else {
+ result.False = row.Count
+ }
+ }
+
+ return result, err
+}
+
+func (c *mongoClient) shardChunks() (map[string]int64, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ col := c.client.Database("config").Collection("chunks")
+
+ cursor, err := col.Aggregate(ctx, mongo.Pipeline{bson.D{{Key: "$sortByCount", Value: "$shard"}}})
+ if err != nil {
+ return nil, err
+ }
+
+ var shards []bson.M
+ if err = cursor.All(ctx, &shards); err != nil {
+ return nil, err
+ }
+
+ defer func() { _ = cursor.Close(ctx) }()
+
+ result := map[string]int64{}
+
+ for _, row := range shards {
+ k, ok := row["_id"].(string)
+ if !ok {
+ return nil, fmt.Errorf("shard name is not a string: %v", row["_id"])
+ }
+ v, ok := row["count"].(int32)
+ if !ok {
+ return nil, fmt.Errorf("shard chunk count is not a int32: %v", row["count"])
+ }
+ result[k] = int64(v)
+ }
+
+ return result, err
+}
+
+func (c *mongoClient) initClient(uri string, timeout time.Duration) error {
+ if c.client != nil {
+ return nil
+ }
+
+ c.timeout = timeout
+
+ ctxConn, cancelConn := context.WithTimeout(context.Background(), c.timeout)
+ defer cancelConn()
+
+ client, err := mongo.Connect(ctxConn, options.Client().ApplyURI(uri))
+ if err != nil {
+ return err
+ }
+
+ ctxPing, cancelPing := context.WithTimeout(context.Background(), c.timeout)
+ defer cancelPing()
+
+ if err := client.Ping(ctxPing, nil); err != nil {
+ return err
+ }
+
+ c.client = client
+
+ return nil
+}
+
+func (c *mongoClient) close() error {
+ if c.client == nil {
+ return nil
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ if err := c.client.Disconnect(ctx); err != nil {
+ return err
+ }
+
+ c.client = nil
+
+ return nil
+}
+
+func (c *mongoClient) dbAggregate(collection string, aggr []bson.D) ([]documentAggrResults, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
+ defer cancel()
+
+ cursor, err := c.client.Database("config").Collection(collection).Aggregate(ctx, aggr)
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() { _ = cursor.Close(ctx) }()
+
+ var rows []documentAggrResults
+ if err := cursor.All(ctx, &rows); err != nil {
+ return nil, err
+ }
+
+ return rows, nil
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/collect.go b/src/go/collectors/go.d.plugin/modules/mongodb/collect.go
new file mode 100644
index 000000000..232145de3
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/collect.go
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import "fmt"
+
+func (m *Mongo) collect() (map[string]int64, error) {
+ if err := m.conn.initClient(m.URI, m.Timeout.Duration()); err != nil {
+ return nil, fmt.Errorf("init mongo conn: %v", err)
+ }
+
+ mx := make(map[string]int64)
+
+ if err := m.collectServerStatus(mx); err != nil {
+ return nil, fmt.Errorf("couldn't collect server status metrics: %v", err)
+ }
+
+ if err := m.collectDbStats(mx); err != nil {
+ return mx, fmt.Errorf("couldn't collect dbstats metrics: %v", err)
+ }
+
+ if m.conn.isReplicaSet() {
+ if err := m.collectReplSetStatus(mx); err != nil {
+ return mx, fmt.Errorf("couldn't collect documentReplSetStatus metrics: %v", err)
+ }
+ }
+
+ if m.conn.isMongos() {
+ m.addShardingChartsOnce.Do(m.addShardingCharts)
+ if err := m.collectSharding(mx); err != nil {
+ return mx, fmt.Errorf("couldn't collect sharding metrics: %v", err)
+ }
+ }
+
+ return mx, nil
+}
+
+func boolToInt(v bool) int64 {
+ if v {
+ return 1
+ }
+ return 0
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/collect_dbstats.go b/src/go/collectors/go.d.plugin/modules/mongodb/collect_dbstats.go
new file mode 100644
index 000000000..edd7077e1
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/collect_dbstats.go
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+func (m *Mongo) collectDbStats(mx map[string]int64) error {
+ if m.dbSelector == nil {
+ m.Debug("'database' selector not set, skip collecting database statistics")
+ return nil
+ }
+
+ allDBs, err := m.conn.listDatabaseNames()
+ if err != nil {
+ return fmt.Errorf("cannot get database names: %v", err)
+ }
+
+ m.Debugf("all databases on the server: '%v'", allDBs)
+
+ var dbs []string
+ for _, db := range allDBs {
+ if m.dbSelector.MatchString(db) {
+ dbs = append(dbs, db)
+ }
+ }
+
+ if len(allDBs) != len(dbs) {
+ m.Debugf("databases remaining after filtering: %v", dbs)
+ }
+
+ seen := make(map[string]bool)
+ for _, db := range dbs {
+ s, err := m.conn.dbStats(db)
+ if err != nil {
+ return fmt.Errorf("dbStats command failed: %v", err)
+ }
+
+ seen[db] = true
+
+ mx["database_"+db+"_collections"] = s.Collections
+ mx["database_"+db+"_views"] = s.Views
+ mx["database_"+db+"_indexes"] = s.Indexes
+ mx["database_"+db+"_documents"] = s.Objects
+ mx["database_"+db+"_data_size"] = s.DataSize
+ mx["database_"+db+"_index_size"] = s.IndexSize
+ mx["database_"+db+"_storage_size"] = s.StorageSize
+ }
+
+ for db := range seen {
+ if !m.databases[db] {
+ m.databases[db] = true
+ m.Debugf("new database '%s': creating charts", db)
+ m.addDatabaseCharts(db)
+ }
+ }
+
+ for db := range m.databases {
+ if !seen[db] {
+ delete(m.databases, db)
+ m.Debugf("stale database '%s': removing charts", db)
+ m.removeDatabaseCharts(db)
+ }
+ }
+
+ return nil
+}
+
+func (m *Mongo) addDatabaseCharts(name string) {
+ charts := chartsTmplDatabase.Copy()
+
+ for _, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, name)
+ chart.Labels = []module.Label{
+ {Key: "database", Value: name},
+ }
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, name)
+ }
+ }
+
+ if err := m.Charts().Add(*charts...); err != nil {
+ m.Warning(err)
+ }
+}
+
+func (m *Mongo) removeDatabaseCharts(name string) {
+ px := fmt.Sprintf("%s%s_", chartPxDatabase, name)
+
+ for _, chart := range *m.Charts() {
+ if strings.HasPrefix(chart.ID, px) {
+ chart.MarkRemove()
+ chart.MarkNotCreated()
+ }
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go b/src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go
new file mode 100644
index 000000000..235e8900e
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+// https://www.mongodb.com/docs/manual/reference/replica-states/#replica-set-member-states
+var replicaSetMemberStates = map[string]int{
+ "startup": 0,
+ "primary": 1,
+ "secondary": 2,
+ "recovering": 3,
+ "startup2": 5,
+ "unknown": 6,
+ "arbiter": 7,
+ "down": 8,
+ "rollback": 9,
+ "removed": 10,
+}
+
+// TODO: deal with duplicates if we collect metrics from all cluster nodes
+// should we only collect ReplSetStatus (at least by default) from primary nodes? (db.runCommand( { isMaster: 1 } ))
+func (m *Mongo) collectReplSetStatus(mx map[string]int64) error {
+ s, err := m.conn.replSetGetStatus()
+ if err != nil {
+ return fmt.Errorf("error get status of the replica set from mongo: %s", err)
+ }
+
+ seen := make(map[string]documentReplSetMember)
+
+ for _, member := range s.Members {
+ seen[member.Name] = member
+
+ px := fmt.Sprintf("repl_set_member_%s_", member.Name)
+
+ mx[px+"replication_lag"] = s.Date.Sub(member.OptimeDate).Milliseconds()
+
+ for k, v := range replicaSetMemberStates {
+ mx[px+"state_"+k] = boolToInt(member.State == v)
+ }
+
+ mx[px+"health_status_up"] = boolToInt(member.Health == 1)
+ mx[px+"health_status_down"] = boolToInt(member.Health == 0)
+
+ if member.Self == nil {
+ mx[px+"uptime"] = member.Uptime
+ if v := member.LastHeartbeatRecv; v != nil && !v.IsZero() {
+ mx[px+"heartbeat_latency"] = s.Date.Sub(*v).Milliseconds()
+ }
+ if v := member.PingMs; v != nil {
+ mx[px+"ping_rtt"] = *v
+ }
+ }
+ }
+
+ for name, member := range seen {
+ if !m.replSetMembers[name] {
+ m.replSetMembers[name] = true
+ m.Debugf("new replica set member '%s': adding charts", name)
+ m.addReplSetMemberCharts(member)
+ }
+ }
+
+ for name := range m.replSetMembers {
+ if _, ok := seen[name]; !ok {
+ delete(m.replSetMembers, name)
+ m.Debugf("stale replica set member '%s': removing charts", name)
+ m.removeReplSetMemberCharts(name)
+ }
+ }
+
+ return nil
+}
+
+func (m *Mongo) addReplSetMemberCharts(v documentReplSetMember) {
+ charts := chartsTmplReplSetMember.Copy()
+
+ if v.Self != nil {
+ _ = charts.Remove(chartTmplReplSetMemberHeartbeatLatencyTime.ID)
+ _ = charts.Remove(chartTmplReplSetMemberPingRTTTime.ID)
+ _ = charts.Remove(chartTmplReplSetMemberUptime.ID)
+ }
+
+ for _, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, v.Name)
+ chart.Labels = []module.Label{
+ {Key: "repl_set_member", Value: v.Name},
+ }
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, v.Name)
+ }
+ }
+
+ if err := m.Charts().Add(*charts...); err != nil {
+ m.Warning(err)
+ }
+}
+
+func (m *Mongo) removeReplSetMemberCharts(name string) {
+ px := fmt.Sprintf("%s%s_", chartPxReplSetMember, name)
+
+ for _, chart := range *m.Charts() {
+ if strings.HasPrefix(chart.ID, px) {
+ chart.MarkRemove()
+ chart.MarkNotCreated()
+ }
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/collect_serverstatus.go b/src/go/collectors/go.d.plugin/modules/mongodb/collect_serverstatus.go
new file mode 100644
index 000000000..33fd86b76
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/collect_serverstatus.go
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/stm"
+)
+
+// collectServerStatus creates the map[string]int64 for the available dims.
+// nil values will be ignored and not added to the map and thus metrics should not appear on the dashboard.
+// Because mongo reports a metric only after it first appears,some dims might take a while to appear.
+// For example, in order to report number of create commands, a document must be created first.
+func (m *Mongo) collectServerStatus(mx map[string]int64) error {
+ s, err := m.conn.serverStatus()
+ if err != nil {
+ return fmt.Errorf("serverStatus command failed: %s", err)
+ }
+
+ m.addOptionalCharts(s)
+
+ for k, v := range stm.ToMap(s) {
+ mx[k] = v
+ }
+
+ if s.Transactions != nil && s.Transactions.CommitTypes != nil {
+ px := "txn_commit_types_"
+ v := s.Transactions.CommitTypes
+ mx[px+"no_shards_unsuccessful"] = v.NoShards.Initiated - v.NoShards.Successful
+ mx[px+"single_shard_unsuccessful"] = v.SingleShard.Initiated - v.SingleShard.Successful
+ mx[px+"single_write_shard_unsuccessful"] = v.SingleWriteShard.Initiated - v.SingleWriteShard.Successful
+ mx[px+"read_only_unsuccessful"] = v.ReadOnly.Initiated - v.ReadOnly.Successful
+ mx[px+"two_phase_commit_unsuccessful"] = v.TwoPhaseCommit.Initiated - v.TwoPhaseCommit.Successful
+ mx[px+"recover_with_token_unsuccessful"] = v.RecoverWithToken.Initiated - v.RecoverWithToken.Successful
+ }
+
+ return nil
+}
+
+func (m *Mongo) addOptionalCharts(s *documentServerStatus) {
+ m.addOptionalChart(s.OpLatencies,
+ &chartOperationsRate,
+ &chartOperationsLatencyTime,
+ )
+ m.addOptionalChart(s.WiredTiger,
+ &chartWiredTigerConcurrentReadTransactionsUsage,
+ &chartWiredTigerConcurrentWriteTransactionsUsage,
+ &chartWiredTigerCacheUsage,
+ &chartWiredTigerCacheDirtySpaceSize,
+ &chartWiredTigerCacheIORate,
+ &chartWiredTigerCacheEvictionsRate,
+ )
+ m.addOptionalChart(s.Tcmalloc,
+ &chartMemoryTCMallocStatsChart,
+ )
+ m.addOptionalChart(s.GlobalLock,
+ &chartGlobalLockActiveClientsCount,
+ &chartGlobalLockCurrentQueueCount,
+ )
+ m.addOptionalChart(s.Network.NumSlowDNSOperations,
+ &chartNetworkSlowDNSResolutionsRate,
+ )
+ m.addOptionalChart(s.Network.NumSlowSSLOperations,
+ &chartNetworkSlowSSLHandshakesRate,
+ )
+ m.addOptionalChart(s.Metrics.Cursor.TotalOpened,
+ &chartCursorsOpenedRate,
+ )
+ m.addOptionalChart(s.Metrics.Cursor.TimedOut,
+ &chartCursorsTimedOutRate,
+ )
+ m.addOptionalChart(s.Metrics.Cursor.Open.Total,
+ &chartCursorsOpenCount,
+ )
+ m.addOptionalChart(s.Metrics.Cursor.Open.NoTimeout,
+ &chartCursorsOpenNoTimeoutCount,
+ )
+ m.addOptionalChart(s.Metrics.Cursor.Lifespan,
+ &chartCursorsByLifespanCount,
+ )
+
+ if s.Transactions != nil {
+ m.addOptionalChart(s.Transactions,
+ &chartTransactionsCount,
+ &chartTransactionsRate,
+ )
+ m.addOptionalChart(s.Transactions.CommitTypes,
+ &chartTransactionsNoShardsCommitsRate,
+ &chartTransactionsNoShardsCommitsDurationTime,
+ &chartTransactionsSingleShardCommitsRate,
+ &chartTransactionsSingleShardCommitsDurationTime,
+ &chartTransactionsSingleWriteShardCommitsRate,
+ &chartTransactionsSingleWriteShardCommitsDurationTime,
+ &chartTransactionsReadOnlyCommitsRate,
+ &chartTransactionsReadOnlyCommitsDurationTime,
+ &chartTransactionsTwoPhaseCommitCommitsRate,
+ &chartTransactionsTwoPhaseCommitCommitsDurationTime,
+ &chartTransactionsRecoverWithTokenCommitsRate,
+ &chartTransactionsRecoverWithTokenCommitsDurationTime,
+ )
+ }
+ if s.Locks != nil {
+ m.addOptionalChart(s.Locks.Global, &chartGlobalLockAcquisitionsRate)
+ m.addOptionalChart(s.Locks.Database, &chartDatabaseLockAcquisitionsRate)
+ m.addOptionalChart(s.Locks.Collection, &chartCollectionLockAcquisitionsRate)
+ m.addOptionalChart(s.Locks.Mutex, &chartMutexLockAcquisitionsRate)
+ m.addOptionalChart(s.Locks.Metadata, &chartMetadataLockAcquisitionsRate)
+ m.addOptionalChart(s.Locks.Oplog, &chartOpLogLockAcquisitionsRate)
+ }
+}
+
+func (m *Mongo) addOptionalChart(iface any, charts ...*module.Chart) {
+ if reflect.ValueOf(iface).IsNil() {
+ return
+ }
+ for _, chart := range charts {
+ if m.optionalCharts[chart.ID] {
+ continue
+ }
+ m.optionalCharts[chart.ID] = true
+
+ if err := m.charts.Add(chart.Copy()); err != nil {
+ m.Warning(err)
+ }
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/collect_sharding.go b/src/go/collectors/go.d.plugin/modules/mongodb/collect_sharding.go
new file mode 100644
index 000000000..175004d34
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/collect_sharding.go
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+func (m *Mongo) collectSharding(mx map[string]int64) error {
+ nodes, err := m.conn.shardNodes()
+ if err != nil {
+ return err
+ }
+
+ mx["shard_nodes_aware"] = nodes.ShardAware
+ mx["shard_nodes_unaware"] = nodes.ShardUnaware
+
+ dbPart, err := m.conn.shardDatabasesPartitioning()
+ if err != nil {
+ return err
+ }
+
+ mx["shard_databases_partitioned"] = dbPart.Partitioned
+ mx["shard_databases_unpartitioned"] = dbPart.UnPartitioned
+
+ collPart, err := m.conn.shardCollectionsPartitioning()
+ if err != nil {
+ return err
+ }
+
+ mx["shard_collections_partitioned"] = collPart.Partitioned
+ mx["shard_collections_unpartitioned"] = collPart.UnPartitioned
+
+ chunksPerShard, err := m.conn.shardChunks()
+ if err != nil {
+ return err
+ }
+
+ seen := make(map[string]bool)
+
+ for shard, count := range chunksPerShard {
+ seen[shard] = true
+ mx["shard_id_"+shard+"_chunks"] = count
+ }
+
+ for id := range seen {
+ if !m.shards[id] {
+ m.shards[id] = true
+ m.addShardCharts(id)
+ }
+ }
+
+ for id := range m.shards {
+ if !seen[id] {
+ delete(m.shards, id)
+ m.removeShardCharts(id)
+ }
+ }
+
+ return nil
+}
+
+func (m *Mongo) addShardCharts(id string) {
+ charts := chartsTmplShardingShard.Copy()
+
+ for _, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, id)
+ chart.Labels = []module.Label{
+ {Key: "shard_id", Value: id},
+ }
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, id)
+ }
+ }
+
+ if err := m.Charts().Add(*charts...); err != nil {
+ m.Warning(err)
+ }
+
+}
+
+func (m *Mongo) removeShardCharts(id string) {
+ px := fmt.Sprintf("%s%s_", chartPxShard, id)
+
+ for _, chart := range *m.Charts() {
+ if strings.HasPrefix(chart.ID, px) {
+ chart.MarkRemove()
+ chart.MarkNotCreated()
+ }
+ }
+}
+
+func (m *Mongo) addShardingCharts() {
+ charts := chartsSharding.Copy()
+
+ if err := m.Charts().Add(*charts...); err != nil {
+ m.Warning(err)
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/config_schema.json b/src/go/collectors/go.d.plugin/modules/mongodb/config_schema.json
new file mode 100644
index 000000000..406468189
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/config_schema.json
@@ -0,0 +1,105 @@
+{
+ "jsonSchema": {
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "MongoDB collector configuration.",
+ "type": "object",
+ "properties": {
+ "update_every": {
+ "title": "Update every",
+ "description": "Data collection interval, measured in seconds.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 1
+ },
+ "uri": {
+ "title": "URI",
+ "description": "The MongoDB connection string in the [standard connection string format](https://www.mongodb.com/docs/manual/reference/connection-string/#std-label-connections-standard-connection-string-format).",
+ "type": "string",
+ "default": "mongodb://localhost:27017"
+ },
+ "timeout": {
+ "title": "Timeout",
+ "description": "Timeout for queries, in seconds.",
+ "type": "number",
+ "minimum": 0.5,
+ "default": 1
+ },
+ "databases": {
+ "title": "Database selector",
+ "description": "Configuration for monitoring specific databases. If left empty, no [database stats](https://docs.mongodb.com/manual/reference/command/dbStats/) will be collected.",
+ "type": [
+ "object",
+ "null"
+ ],
+ "properties": {
+ "includes": {
+ "title": "Include",
+ "description": "Include databases that match any of the specified include [patterns](https://github.com/netdata/netdata/tree/master/src/go/collectors/go.d.plugin/pkg/matcher#readme).",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "title": "Pattern",
+ "type": "string"
+ },
+ "uniqueItems": true
+ },
+ "excludes": {
+ "title": "Exclude",
+ "description": "Exclude databases that match any of the specified exclude [patterns](https://github.com/netdata/netdata/tree/master/src/go/collectors/go.d.plugin/pkg/matcher#readme).",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "title": "Pattern",
+ "type": "string"
+ },
+ "uniqueItems": true
+ }
+ }
+ }
+ },
+ "required": [
+ "uri"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^name$": {}
+ }
+ },
+ "uiSchema": {
+ "uiOptions": {
+ "fullPage": true
+ },
+ "uri": {
+ "ui:placeholder": "mongodb://username:password@host:port"
+ },
+ "timeout": {
+ "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
+ },
+ "databases": {
+ "ui:help": "The logic for inclusion and exclusion is as follows: `(include1 OR include2) AND !(exclude1 OR exclude2)`."
+ },
+ "ui:flavour": "tabs",
+ "ui:options": {
+ "tabs": [
+ {
+ "title": "Base",
+ "fields": [
+ "update_every",
+ "uri",
+ "timeout"
+ ]
+ },
+ {
+ "title": "Database stats",
+ "fields": [
+ "databases"
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/documents.go b/src/go/collectors/go.d.plugin/modules/mongodb/documents.go
new file mode 100644
index 000000000..5c95e952e
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/documents.go
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import "time"
+
+// https://www.mongodb.com/docs/manual/reference/command/serverStatus
+type documentServerStatus struct {
+ Process string `bson:"process"` // mongod|mongos
+ OpCounters documentOpCounters `bson:"opcounters" stm:"operations"`
+ OpLatencies *documentOpLatencies `bson:"opLatencies" stm:"operations_latencies"` // mongod only
+ Connections documentConnections `bson:"connections" stm:"connections"`
+ Network documentNetwork `bson:"network" stm:"network"`
+ Memory documentMemory `bson:"mem" stm:"memory"`
+ Metrics documentMetrics `bson:"metrics" stm:"metrics"`
+ ExtraInfo documentExtraInfo `bson:"extra_info" stm:"extra_info"`
+ Asserts documentAsserts `bson:"asserts" stm:"asserts"`
+ Transactions *documentTransactions `bson:"transactions" stm:"txn"` // mongod in 3.6.3+ and on mongos in 4.2+
+ GlobalLock *documentGlobalLock `bson:"globalLock" stm:"global_lock"`
+ Tcmalloc *documentTCMallocStatus `bson:"tcmalloc" stm:"tcmalloc"`
+ Locks *documentLocks `bson:"locks" stm:"locks"`
+ WiredTiger *documentWiredTiger `bson:"wiredTiger" stm:"wiredtiger"`
+ Repl interface{} `bson:"repl"`
+}
+
+type (
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#opcounters
+ documentOpCounters struct {
+ Insert int64 `bson:"insert" stm:"insert"`
+ Query int64 `bson:"query" stm:"query"`
+ Update int64 `bson:"update" stm:"update"`
+ Delete int64 `bson:"delete" stm:"delete"`
+ GetMore int64 `bson:"getmore" stm:"getmore"`
+ Command int64 `bson:"command" stm:"command"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#oplatencies
+ documentOpLatencies struct {
+ Reads documentLatencyStats `bson:"reads" stm:"reads"`
+ Writes documentLatencyStats `bson:"writes" stm:"writes"`
+ Commands documentLatencyStats `bson:"commands" stm:"commands"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/operator/aggregation/collStats/#latencystats-document
+ documentLatencyStats struct {
+ Latency int64 `bson:"latency" stm:"latency"`
+ Ops int64 `bson:"ops" stm:"ops"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#connections
+ documentConnections struct {
+ Current int64 `bson:"current" stm:"current"`
+ Available int64 `bson:"available" stm:"available"`
+ TotalCreated int64 `bson:"totalCreated" stm:"total_created"`
+ Active *int64 `bson:"active" stm:"active"`
+ Threaded *int64 `bson:"threaded" stm:"threaded"`
+ ExhaustIsMaster *int64 `bson:"exhaustIsMaster" stm:"exhaust_is_master"`
+ ExhaustHello *int64 `bson:"exhaustHello" stm:"exhaust_hello"`
+ AwaitingTopologyChanges *int64 `bson:"awaitingTopologyChanges" stm:"awaiting_topology_changes"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#network
+ documentNetwork struct {
+ BytesIn int64 `bson:"bytesIn" stm:"bytes_in"`
+ BytesOut int64 `bson:"bytesOut" stm:"bytes_out"`
+ NumRequests int64 `bson:"numRequests" stm:"requests"`
+ NumSlowDNSOperations *int64 `bson:"numSlowDNSOperations" stm:"slow_dns_operations"` // 4.4+
+ NumSlowSSLOperations *int64 `bson:"numSlowSSLOperations" stm:"slow_ssl_operations"` // 4.4+
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#mem
+ documentMemory struct {
+ Resident int64 `bson:"resident" stm:"resident,1048576,1"`
+ Virtual int64 `bson:"virtual" stm:"virtual,1048576,1"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#extra_info
+ documentExtraInfo struct {
+ PageFaults int64 `bson:"page_faults" stm:"page_faults"`
+ }
+ // Values:
+ // - mongodb: https://github.com/mongodb/mongo/blob/54e1be7d98aa154e1676d6d652b4d2d1a1073b07/src/mongo/util/tcmalloc_server_status_section.cpp#L88
+ // - tcmalloc: https://github.com/google/tcmalloc/blob/927c1433141daa1f0bcf920e6d71bf64795cc2c2/tcmalloc/global_stats.cc#L582
+ // formattedString:
+ // - https://github.com/google/tcmalloc/blob/master/docs/stats.md
+ // - https://github.com/google/tcmalloc/blob/927c1433141daa1f0bcf920e6d71bf64795cc2c2/tcmalloc/global_stats.cc#L208
+ documentTCMallocStatus struct {
+ Generic *struct {
+ CurrentAllocatedBytes int64 `bson:"current_allocated_bytes" stm:"current_allocated_bytes"`
+ HeapSize int64 `bson:"heap_size" stm:"heap_size"`
+ } `bson:"generic" stm:"generic"`
+ Tcmalloc *struct {
+ PageheapFreeBytes int64 `bson:"pageheap_free_bytes" stm:"pageheap_free_bytes"`
+ PageheapUnmappedBytes int64 `bson:"pageheap_unmapped_bytes" stm:"pageheap_unmapped_bytes"`
+ MaxTotalThreadCacheBytes int64 `bson:"max_total_thread_cache_bytes" stm:"max_total_thread_cache_bytes"`
+ CurrentTotalThreadCacheBytes int64 `bson:"current_total_thread_cache_bytes" stm:"current_total_thread_cache_bytes"`
+ TotalFreeBytes int64 `bson:"total_free_bytes" stm:"total_free_bytes"`
+ CentralCacheFreeBytes int64 `bson:"central_cache_free_bytes" stm:"central_cache_free_bytes"`
+ TransferCacheFreeBytes int64 `bson:"transfer_cache_free_bytes" stm:"transfer_cache_free_bytes"`
+ ThreadCacheFreeBytes int64 `bson:"thread_cache_free_bytes" stm:"thread_cache_free_bytes"`
+ AggressiveMemoryDecommit int64 `bson:"aggressive_memory_decommit" stm:"aggressive_memory_decommit"`
+ PageheapCommittedBytes int64 `bson:"pageheap_committed_bytes" stm:"pageheap_committed_bytes"`
+ PageheapScavengeBytes int64 `bson:"pageheap_scavenge_bytes" stm:"pageheap_scavenge_bytes"`
+ PageheapCommitCount int64 `bson:"pageheap_commit_count" stm:"pageheap_commit_count"`
+ PageheapTotalCommitBytes int64 `bson:"pageheap_total_commit_bytes" stm:"pageheap_total_commit_bytes"`
+ PageheapDecommitCount int64 `bson:"pageheap_decommit_count" stm:"pageheap_decommit_count"`
+ PageheapTotalDecommitBytes int64 `bson:"pageheap_total_decommit_bytes" stm:"pageheap_total_decommit_bytes"`
+ PageheapReserveCount int64 `bson:"pageheap_reserve_count" stm:"pageheap_reserve_count"`
+ PageheapTotalReserveBytes int64 `bson:"pageheap_total_reserve_bytes" stm:"pageheap_total_reserve_bytes"`
+ SpinlockTotalDelayNs int64 `bson:"spinlock_total_delay_ns" stm:"spinlock_total_delay_ns"`
+ } `bson:"tcmalloc" stm:""`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#metrics
+ documentMetrics struct {
+ Cursor struct {
+ TotalOpened *int64 `bson:"totalOpened" stm:"total_opened"`
+ TimedOut *int64 `bson:"timedOut" stm:"timed_out"`
+ Open struct {
+ NoTimeout *int64 `bson:"noTimeout" stm:"no_timeout"`
+ Total *int64 `bson:"total" stm:"total"`
+ } `bson:"open" stm:"open"`
+ Lifespan *struct {
+ GreaterThanOrEqual10Minutes int64 `bson:"greaterThanOrEqual10Minutes" stm:"greater_than_or_equal_10_minutes"`
+ LessThan10Minutes int64 `bson:"lessThan10Minutes" stm:"less_than_10_minutes"`
+ LessThan15Seconds int64 `bson:"lessThan15Seconds" stm:"less_than_15_seconds"`
+ LessThan1Minute int64 `bson:"lessThan1Minute" stm:"less_than_1_minute"`
+ LessThan1Second int64 `bson:"lessThan1Second" stm:"less_than_1_second"`
+ LessThan30Seconds int64 `bson:"lessThan30Seconds" stm:"less_than_30_seconds"`
+ LessThan5Seconds int64 `bson:"lessThan5Seconds" stm:"less_than_5_seconds"`
+ } `bson:"lifespan" stm:"lifespan"`
+ } `bson:"cursor" stm:"cursor"`
+ Document struct {
+ Deleted int64 `bson:"deleted" stm:"deleted"`
+ Inserted int64 `bson:"inserted" stm:"inserted"`
+ Returned int64 `bson:"returned" stm:"returned"`
+ Updated int64 `bson:"updated" stm:"updated"`
+ } `bson:"document" stm:"document"`
+ QueryExecutor struct {
+ Scanned int64 `bson:"scanned" stm:"scanned"`
+ ScannedObjects int64 `bson:"scannedObjects" stm:"scanned_objects"`
+ } `bson:"queryExecutor" stm:"query_executor"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#asserts
+ documentAsserts struct {
+ Regular int64 `bson:"regular" stm:"regular"`
+ Warning int64 `bson:"warning" stm:"warning"`
+ Msg int64 `bson:"msg" stm:"msg"`
+ User int64 `bson:"user" stm:"user"`
+ Tripwire int64 `bson:"tripwire" stm:"tripwire"`
+ Rollovers int64 `bson:"rollovers" stm:"rollovers"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#transactions
+ documentTransactions struct {
+ CurrentActive *int64 `bson:"currentActive" stm:"active"` // mongod in 4.0.2+ and mongos in 4.2.1+
+ CurrentInactive *int64 `bson:"currentInactive" stm:"inactive"` // mongod in 4.0.2+ and mongos in 4.2.1+
+ CurrentOpen *int64 `bson:"currentOpen" stm:"open"` // mongod in 4.0.2+ and mongos in 4.2.1+
+ CurrentPrepared *int64 `bson:"currentPrepared" stm:"prepared"` // 4.2+ mongod only
+ TotalAborted *int64 `bson:"totalAborted" stm:"total_aborted"` // mongod in 4.0.2+ and mongos in 4.2+
+ TotalCommitted *int64 `bson:"totalCommitted" stm:"total_committed"` // mongod in 4.0.2+ and mongos in 4.2+
+ TotalStarted *int64 `bson:"totalStarted" stm:"total_started"` // mongod in 4.0.2+ and mongos in 4.2+
+ TotalPrepared *int64 `bson:"totalPrepared" stm:"total_prepared"` // mongod in 4.0.2+ and mongos in 4.2+
+ CommitTypes *documentTransactionsCommitTypes `bson:"commitTypes" stm:"commit_types"` // mongos only
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#mongodb-serverstatus-serverstatus.transactions.commitTypes
+ documentTransactionsCommitTypes struct {
+ NoShards documentTransactionsCommitType `bson:"noShards" stm:"no_shards"`
+ SingleShard documentTransactionsCommitType `bson:"singleShard" stm:"single_shard"`
+ SingleWriteShard documentTransactionsCommitType `bson:"singleWriteShard" stm:"single_write_shard"`
+ ReadOnly documentTransactionsCommitType `bson:"readOnly" stm:"read_only"`
+ TwoPhaseCommit documentTransactionsCommitType `bson:"twoPhaseCommit" stm:"two_phase_commit"`
+ RecoverWithToken documentTransactionsCommitType `bson:"recoverWithToken" stm:"recover_with_token"`
+ }
+ documentTransactionsCommitType struct {
+ Initiated int64 `json:"initiated" stm:"initiated"`
+ Successful int64 `json:"successful" stm:"successful"`
+ SuccessfulDurationMicros int64 `json:"successfulDurationMicros" stm:"successful_duration_micros"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#globallock
+ documentGlobalLock struct {
+ CurrentQueue *struct {
+ Readers int64 `bson:"readers" stm:"readers"`
+ Writers int64 `bson:"writers" stm:"writers"`
+ } `bson:"currentQueue" stm:"current_queue"`
+ ActiveClients *struct {
+ Readers int64 `bson:"readers" stm:"readers"`
+ Writers int64 `bson:"writers" stm:"writers"`
+ } `bson:"activeClients" stm:"active_clients"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#mongodb-serverstatus-serverstatus.locks
+ documentLocks struct {
+ Global *documentLockType `bson:"Global" stm:"global"`
+ Database *documentLockType `bson:"Database" stm:"database"`
+ Collection *documentLockType `bson:"Collection" stm:"collection"`
+ Mutex *documentLockType `bson:"Mutex" stm:"mutex"`
+ Metadata *documentLockType `bson:"Metadata" stm:"metadata"`
+ Oplog *documentLockType `bson:"oplog" stm:"oplog"`
+ }
+ documentLockType struct {
+ AcquireCount documentLockModes `bson:"acquireCount" stm:"acquire"`
+ }
+ documentLockModes struct {
+ Shared int64 `bson:"R" stm:"shared"`
+ Exclusive int64 `bson:"W" stm:"exclusive"`
+ IntentShared int64 `bson:"r" stm:"intent_shared"`
+ IntentExclusive int64 `bson:"w" stm:"intent_exclusive"`
+ }
+ // https://www.mongodb.com/docs/manual/reference/command/serverStatus/#wiredtiger
+ documentWiredTiger struct {
+ ConcurrentTransaction struct {
+ Write struct {
+ Out int `bson:"out" stm:"out"`
+ Available int `bson:"available" stm:"available"`
+ } `bson:"write" stm:"write"`
+ Read struct {
+ Out int `bson:"out" stm:"out"`
+ Available int `bson:"available" stm:"available"`
+ } `bson:"read" stm:"read"`
+ } `bson:"concurrentTransactions" stm:"concurrent_txn"`
+ Cache struct {
+ BytesCurrentlyInCache int `bson:"bytes currently in the cache" stm:"currently_in_cache_bytes"`
+ MaximumBytesConfigured int `bson:"maximum bytes configured" stm:"maximum_configured_bytes"`
+ TrackedDirtyBytesInCache int `bson:"tracked dirty bytes in the cache" stm:"tracked_dirty_in_the_cache_bytes"`
+ UnmodifiedPagesEvicted int `bson:"unmodified pages evicted" stm:"unmodified_evicted_pages"`
+ ModifiedPagesEvicted int `bson:"modified pages evicted" stm:"modified_evicted_pages"`
+ PagesReadIntoCache int `bson:"pages read into cache" stm:"read_into_cache_pages"`
+ PagesWrittenFromCache int `bson:"pages written from cache" stm:"written_from_cache_pages"`
+ } `bson:"cache" stm:"cache"`
+ }
+)
+
+// https://www.mongodb.com/docs/manual/reference/command/dbStats/
+type documentDBStats struct {
+ Collections int64 `bson:"collections"`
+ Views int64 `bson:"views"`
+ Indexes int64 `bson:"indexes"`
+ Objects int64 `bson:"objects"`
+ DataSize int64 `bson:"dataSize"`
+ IndexSize int64 `bson:"indexSize"`
+ StorageSize int64 `bson:"storageSize"`
+}
+
+// https://www.mongodb.com/docs/manual/reference/command/replSetGetStatus/
+type documentReplSetStatus struct {
+ Date time.Time `bson:"date"`
+ Members []documentReplSetMember `bson:"members"`
+}
+
+type (
+ documentReplSetMember struct {
+ Name string `bson:"name"`
+ Self *bool `bson:"self"`
+ State int `bson:"state"`
+ Health int `bson:"health"`
+ OptimeDate time.Time `bson:"optimeDate"`
+ LastHeartbeat *time.Time `bson:"lastHeartbeat"`
+ LastHeartbeatRecv *time.Time `bson:"lastHeartbeatRecv"`
+ PingMs *int64 `bson:"pingMs"`
+ Uptime int64 `bson:"uptime"`
+ }
+)
+
+type documentAggrResults struct {
+ Bool bool `bson:"_id"`
+ Count int64 `bson:"count"`
+}
+
+type (
+ documentAggrResult struct {
+ True int64
+ False int64
+ }
+)
+
+type documentPartitionedResult struct {
+ Partitioned int64
+ UnPartitioned int64
+}
+
+type documentShardNodesResult struct {
+ ShardAware int64
+ ShardUnaware int64
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/init.go b/src/go/collectors/go.d.plugin/modules/mongodb/init.go
new file mode 100644
index 000000000..b881e8711
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/init.go
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "errors"
+)
+
+func (m *Mongo) verifyConfig() error {
+ if m.URI == "" {
+ return errors.New("connection URI is empty")
+ }
+
+ return nil
+}
+
+func (m *Mongo) initDatabaseSelector() error {
+ if m.Databases.Empty() {
+ return nil
+ }
+
+ sr, err := m.Databases.Parse()
+ if err != nil {
+ return err
+ }
+ m.dbSelector = sr
+
+ return nil
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/integrations/mongodb.md b/src/go/collectors/go.d.plugin/modules/mongodb/integrations/mongodb.md
new file mode 100644
index 000000000..c43af5211
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/integrations/mongodb.md
@@ -0,0 +1,356 @@
+<!--startmeta
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/mongodb/README.md"
+meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/mongodb/metadata.yaml"
+sidebar_label: "MongoDB"
+learn_status: "Published"
+learn_rel_path: "Collecting Metrics/Databases"
+most_popular: False
+message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE"
+endmeta-->
+
+# MongoDB
+
+
+<img src="https://netdata.cloud/img/mongodb.svg" width="150"/>
+
+
+Plugin: go.d.plugin
+Module: mongodb
+
+<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
+
+## Overview
+
+This collector monitors MongoDB servers.
+
+Executed queries:
+
+- [serverStatus](https://docs.mongodb.com/manual/reference/command/serverStatus/)
+- [dbStats](https://docs.mongodb.com/manual/reference/command/dbStats/)
+- [replSetGetStatus](https://www.mongodb.com/docs/manual/reference/command/replSetGetStatus/)
+
+
+
+
+This collector is supported on all platforms.
+
+This collector supports collecting metrics from multiple instances of this integration, including remote instances.
+
+
+### Default Behavior
+
+#### Auto-Detection
+
+This integration doesn't support auto-detection.
+
+#### Limits
+
+The default configuration for this integration does not impose any limits on data collection.
+
+#### Performance Impact
+
+The default configuration for this integration is not expected to impose a significant performance impact on the system.
+
+
+## Metrics
+
+Metrics grouped by *scope*.
+
+The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.
+
+- WireTiger metrics are available only if [WiredTiger](https://docs.mongodb.com/v6.0/core/wiredtiger/) is used as the
+ storage engine.
+- Sharding metrics are available on shards only
+ for [mongos](https://www.mongodb.com/docs/manual/reference/program/mongos/).
+
+
+### Per MongoDB instance
+
+These metrics refer to the entire monitored application.
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.operations_rate | reads, writes, commands | operations/s |
+| mongodb.operations_latency_time | reads, writes, commands | milliseconds |
+| mongodb.operations_by_type_rate | insert, query, update, delete, getmore, command | operations/s |
+| mongodb.document_operations_rate | inserted, deleted, returned, updated | operations/s |
+| mongodb.scanned_indexes_rate | scanned | indexes/s |
+| mongodb.scanned_documents_rate | scanned | documents/s |
+| mongodb.active_clients_count | readers, writers | clients |
+| mongodb.queued_operations_count | reads, writes | operations |
+| mongodb.cursors_open_count | open | cursors |
+| mongodb.cursors_open_no_timeout_count | open_no_timeout | cursors |
+| mongodb.cursors_opened_rate | opened | cursors/s |
+| mongodb.cursors_timed_out_rate | timed_out | cursors/s |
+| mongodb.cursors_by_lifespan_count | le_1s, 1s_5s, 5s_15s, 15s_30s, 30s_1m, 1m_10m, ge_10m | cursors |
+| mongodb.transactions_count | active, inactive, open, prepared | transactions |
+| mongodb.transactions_rate | started, aborted, committed, prepared | transactions/s |
+| mongodb.connections_usage | available, used | connections |
+| mongodb.connections_by_state_count | active, threaded, exhaust_is_master, exhaust_hello, awaiting_topology_changes | connections |
+| mongodb.connections_rate | created | connections/s |
+| mongodb.asserts_rate | regular, warning, msg, user, tripwire, rollovers | asserts/s |
+| mongodb.network_traffic_rate | in, out | bytes/s |
+| mongodb.network_requests_rate | requests | requests/s |
+| mongodb.network_slow_dns_resolutions_rate | slow_dns | resolutions/s |
+| mongodb.network_slow_ssl_handshakes_rate | slow_ssl | handshakes/s |
+| mongodb.memory_resident_size | used | bytes |
+| mongodb.memory_virtual_size | used | bytes |
+| mongodb.memory_page_faults_rate | pgfaults | pgfaults/s |
+| mongodb.memory_tcmalloc_stats | allocated, central_cache_freelist, transfer_cache_freelist, thread_cache_freelists, pageheap_freelist, pageheap_unmapped | bytes |
+| mongodb.wiredtiger_concurrent_read_transactions_usage | available, used | transactions |
+| mongodb.wiredtiger_concurrent_write_transactions_usage | available, used | transactions |
+| mongodb.wiredtiger_cache_usage | used | bytes |
+| mongodb.wiredtiger_cache_dirty_space_size | dirty | bytes |
+| mongodb.wiredtiger_cache_io_rate | read, written | pages/s |
+| mongodb.wiredtiger_cache_evictions_rate | unmodified, modified | pages/s |
+| mongodb.sharding_nodes_count | shard_aware, shard_unaware | nodes |
+| mongodb.sharding_sharded_databases_count | partitioned, unpartitioned | databases |
+| mongodb.sharding_sharded_collections_count | partitioned, unpartitioned | collections |
+
+### Per lock type
+
+These metrics refer to the lock type.
+
+Labels:
+
+| Label | Description |
+|:-----------|:----------------|
+| lock_type | lock type (e.g. global, database, collection, mutex) |
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.lock_acquisitions_rate | shared, exclusive, intent_shared, intent_exclusive | acquisitions/s |
+
+### Per commit type
+
+These metrics refer to the commit type.
+
+Labels:
+
+| Label | Description |
+|:-----------|:----------------|
+| commit_type | commit type (e.g. noShards, singleShard, singleWriteShard) |
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.transactions_commits_rate | success, fail | commits/s |
+| mongodb.transactions_commits_duration_time | commits | milliseconds |
+
+### Per database
+
+These metrics refer to the database.
+
+Labels:
+
+| Label | Description |
+|:-----------|:----------------|
+| database | database name |
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.database_collection_count | collections | collections |
+| mongodb.database_indexes_count | indexes | indexes |
+| mongodb.database_views_count | views | views |
+| mongodb.database_documents_count | documents | documents |
+| mongodb.database_data_size | data_size | bytes |
+| mongodb.database_storage_size | storage_size | bytes |
+| mongodb.database_index_size | index_size | bytes |
+
+### Per replica set member
+
+These metrics refer to the replica set member.
+
+Labels:
+
+| Label | Description |
+|:-----------|:----------------|
+| repl_set_member | replica set member name |
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.repl_set_member_state | primary, startup, secondary, recovering, startup2, unknown, arbiter, down, rollback, removed | state |
+| mongodb.repl_set_member_health_status | up, down | status |
+| mongodb.repl_set_member_replication_lag_time | replication_lag | milliseconds |
+| mongodb.repl_set_member_heartbeat_latency_time | heartbeat_latency | milliseconds |
+| mongodb.repl_set_member_ping_rtt_time | ping_rtt | milliseconds |
+| mongodb.repl_set_member_uptime | uptime | seconds |
+
+### Per shard
+
+These metrics refer to the shard.
+
+Labels:
+
+| Label | Description |
+|:-----------|:----------------|
+| shard_id | shard id |
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| mongodb.sharding_shard_chunks_count | chunks | chunks |
+
+
+
+## Alerts
+
+There are no alerts configured by default for this integration.
+
+
+## Setup
+
+### Prerequisites
+
+#### Create a read-only user
+
+Create a read-only user for Netdata in the admin database.
+
+- Authenticate as the admin user:
+
+ ```bash
+ use admin
+ db.auth("admin", "<MONGODB_ADMIN_PASSWORD>")
+ ```
+
+- Create a user:
+
+ ```bash
+ db.createUser({
+ "user":"netdata",
+ "pwd": "<UNIQUE_PASSWORD>",
+ "roles" : [
+ {role: 'read', db: 'admin' },
+ {role: 'clusterMonitor', db: 'admin'},
+ {role: 'read', db: 'local' }
+ ]
+ })
+ ```
+
+
+
+### Configuration
+
+#### File
+
+The configuration file name for this integration is `go.d/mongodb.conf`.
+
+
+You can edit the configuration file using the `edit-config` script from the
+Netdata [config directory](https://github.com/netdata/netdata/blob/master/docs/netdata-agent/configuration.md#the-netdata-config-directory).
+
+```bash
+cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
+sudo ./edit-config go.d/mongodb.conf
+```
+#### Options
+
+The following options can be defined globally: update_every, autodetection_retry.
+
+
+<details><summary>Config options</summary>
+
+| Name | Description | Default | Required |
+|:----|:-----------|:-------|:--------:|
+| update_every | Data collection frequency. | 5 | no |
+| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no |
+| uri | MongoDB connection string. See [URI syntax](https://www.mongodb.com/docs/manual/reference/connection-string/). | mongodb://localhost:27017 | yes |
+| timeout | Query timeout in seconds. | 1 | no |
+| databases | Databases selector. Determines which database metrics will be collected. | | no |
+
+</details>
+
+#### Examples
+
+##### TCP socket
+
+An example configuration.
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+
+```
+</details>
+
+##### With databases metrics
+
+An example configuration.
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+ databases:
+ includes:
+ - "* *"
+
+```
+</details>
+
+##### Multi-instance
+
+> **Note**: When you define multiple jobs, their names must be unique.
+
+Local and remote instances.
+
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+
+ - name: remote
+ uri: mongodb://netdata:password@203.0.113.0:27017
+
+```
+</details>
+
+
+
+## Troubleshooting
+
+### Debug Mode
+
+To troubleshoot issues with the `mongodb` collector, run the `go.d.plugin` with the debug option enabled. The output
+should give you clues as to why the collector isn't working.
+
+- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on
+ your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`.
+
+ ```bash
+ cd /usr/libexec/netdata/plugins.d/
+ ```
+
+- Switch to the `netdata` user.
+
+ ```bash
+ sudo -u netdata -s
+ ```
+
+- Run the `go.d.plugin` to debug the collector:
+
+ ```bash
+ ./go.d.plugin -d -m mongodb
+ ```
+
+
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/metadata.yaml b/src/go/collectors/go.d.plugin/modules/mongodb/metadata.yaml
new file mode 100644
index 000000000..bad65393d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/metadata.yaml
@@ -0,0 +1,580 @@
+plugin_name: go.d.plugin
+modules:
+ - meta:
+ id: collector-go.d.plugin-mongodb
+ plugin_name: go.d.plugin
+ module_name: mongodb
+ monitored_instance:
+ name: MongoDB
+ link: https://www.mongodb.com/
+ icon_filename: mongodb.svg
+ categories:
+ - data-collection.database-servers
+ keywords:
+ - mongodb
+ - databases
+ related_resources:
+ integrations:
+ list: []
+ info_provided_to_referring_integrations:
+ description: ""
+ most_popular: false
+ overview:
+ data_collection:
+ metrics_description: |
+ This collector monitors MongoDB servers.
+
+ Executed queries:
+
+ - [serverStatus](https://docs.mongodb.com/manual/reference/command/serverStatus/)
+ - [dbStats](https://docs.mongodb.com/manual/reference/command/dbStats/)
+ - [replSetGetStatus](https://www.mongodb.com/docs/manual/reference/command/replSetGetStatus/)
+ method_description: ""
+ supported_platforms:
+ include: []
+ exclude: []
+ multi_instance: true
+ additional_permissions:
+ description: ""
+ default_behavior:
+ auto_detection:
+ description: ""
+ limits:
+ description: ""
+ performance_impact:
+ description: ""
+ setup:
+ prerequisites:
+ list:
+ - title: Create a read-only user
+ description: |
+ Create a read-only user for Netdata in the admin database.
+
+ - Authenticate as the admin user:
+
+ ```bash
+ use admin
+ db.auth("admin", "<MONGODB_ADMIN_PASSWORD>")
+ ```
+
+ - Create a user:
+
+ ```bash
+ db.createUser({
+ "user":"netdata",
+ "pwd": "<UNIQUE_PASSWORD>",
+ "roles" : [
+ {role: 'read', db: 'admin' },
+ {role: 'clusterMonitor', db: 'admin'},
+ {role: 'read', db: 'local' }
+ ]
+ })
+ ```
+ configuration:
+ file:
+ name: go.d/mongodb.conf
+ options:
+ description: |
+ The following options can be defined globally: update_every, autodetection_retry.
+ folding:
+ title: Config options
+ enabled: true
+ list:
+ - name: update_every
+ description: Data collection frequency.
+ default_value: 5
+ required: false
+ - name: autodetection_retry
+ description: Recheck interval in seconds. Zero means no recheck will be scheduled.
+ default_value: 0
+ required: false
+ - name: uri
+ description: MongoDB connection string. See [URI syntax](https://www.mongodb.com/docs/manual/reference/connection-string/).
+ default_value: mongodb://localhost:27017
+ required: true
+ - name: timeout
+ description: Query timeout in seconds.
+ default_value: 1
+ required: false
+ - name: databases
+ description: Databases selector. Determines which database metrics will be collected.
+ default_value: ""
+ required: false
+ details: |
+ Metrics of databases matching the selector will be collected.
+
+ - Logic: (pattern1 OR pattern2) AND !(pattern3 or pattern4)
+ - Pattern syntax: [matcher](https://github.com/netdata/netdata/tree/master/src/go/collectors/go.d.plugin/pkg/matcher#supported-format).
+ - Syntax:
+
+ ```yaml
+ per_user_stats:
+ includes:
+ - pattern1
+ - pattern2
+ excludes:
+ - pattern3
+ - pattern4
+ ```
+ examples:
+ folding:
+ title: Config
+ enabled: true
+ list:
+ - name: TCP socket
+ description: An example configuration.
+ config: |
+ jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+ - name: With databases metrics
+ description: An example configuration.
+ config: |
+ jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+ databases:
+ includes:
+ - "* *"
+ - name: Multi-instance
+ description: |
+ > **Note**: When you define multiple jobs, their names must be unique.
+
+ Local and remote instances.
+ config: |
+ jobs:
+ - name: local
+ uri: mongodb://netdata:password@localhost:27017
+
+ - name: remote
+ uri: mongodb://netdata:password@203.0.113.0:27017
+ troubleshooting:
+ problems:
+ list: []
+ alerts: []
+ metrics:
+ folding:
+ title: Metrics
+ enabled: false
+ availability: []
+ description: |
+ - WireTiger metrics are available only if [WiredTiger](https://docs.mongodb.com/v6.0/core/wiredtiger/) is used as the
+ storage engine.
+ - Sharding metrics are available on shards only
+ for [mongos](https://www.mongodb.com/docs/manual/reference/program/mongos/).
+ scopes:
+ - name: global
+ description: These metrics refer to the entire monitored application.
+ labels: []
+ metrics:
+ - name: mongodb.operations_rate
+ description: Operations rate
+ unit: operations/s
+ chart_type: line
+ dimensions:
+ - name: reads
+ - name: writes
+ - name: commands
+ - name: mongodb.operations_latency_time
+ description: Operations Latency
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: reads
+ - name: writes
+ - name: commands
+ - name: mongodb.operations_by_type_rate
+ description: Operations by type
+ unit: operations/s
+ chart_type: line
+ dimensions:
+ - name: insert
+ - name: query
+ - name: update
+ - name: delete
+ - name: getmore
+ - name: command
+ - name: mongodb.document_operations_rate
+ description: Document operations
+ unit: operations/s
+ chart_type: stacked
+ dimensions:
+ - name: inserted
+ - name: deleted
+ - name: returned
+ - name: updated
+ - name: mongodb.scanned_indexes_rate
+ description: Scanned indexes
+ unit: indexes/s
+ chart_type: line
+ dimensions:
+ - name: scanned
+ - name: mongodb.scanned_documents_rate
+ description: Scanned documents
+ unit: documents/s
+ chart_type: line
+ dimensions:
+ - name: scanned
+ - name: mongodb.active_clients_count
+ description: Connected clients
+ unit: clients
+ chart_type: line
+ dimensions:
+ - name: readers
+ - name: writers
+ - name: mongodb.queued_operations_count
+ description: Queued operations because of a lock
+ unit: operations
+ chart_type: line
+ dimensions:
+ - name: reads
+ - name: writes
+ - name: mongodb.cursors_open_count
+ description: Open cursors
+ unit: cursors
+ chart_type: line
+ dimensions:
+ - name: open
+ - name: mongodb.cursors_open_no_timeout_count
+ description: Open cursors with disabled timeout
+ unit: cursors
+ chart_type: line
+ dimensions:
+ - name: open_no_timeout
+ - name: mongodb.cursors_opened_rate
+ description: Opened cursors rate
+ unit: cursors/s
+ chart_type: line
+ dimensions:
+ - name: opened
+ - name: mongodb.cursors_timed_out_rate
+ description: Timed-out cursors
+ unit: cursors/s
+ chart_type: line
+ dimensions:
+ - name: timed_out
+ - name: mongodb.cursors_by_lifespan_count
+ description: Cursors lifespan
+ unit: cursors
+ chart_type: stacked
+ dimensions:
+ - name: le_1s
+ - name: 1s_5s
+ - name: 5s_15s
+ - name: 15s_30s
+ - name: 30s_1m
+ - name: 1m_10m
+ - name: ge_10m
+ - name: mongodb.transactions_count
+ description: Current transactions
+ unit: transactions
+ chart_type: line
+ dimensions:
+ - name: active
+ - name: inactive
+ - name: open
+ - name: prepared
+ - name: mongodb.transactions_rate
+ description: Transactions rate
+ unit: transactions/s
+ chart_type: line
+ dimensions:
+ - name: started
+ - name: aborted
+ - name: committed
+ - name: prepared
+ - name: mongodb.connections_usage
+ description: Connections usage
+ unit: connections
+ chart_type: stacked
+ dimensions:
+ - name: available
+ - name: used
+ - name: mongodb.connections_by_state_count
+ description: Connections By State
+ unit: connections
+ chart_type: line
+ dimensions:
+ - name: active
+ - name: threaded
+ - name: exhaust_is_master
+ - name: exhaust_hello
+ - name: awaiting_topology_changes
+ - name: mongodb.connections_rate
+ description: Connections Rate
+ unit: connections/s
+ chart_type: line
+ dimensions:
+ - name: created
+ - name: mongodb.asserts_rate
+ description: Raised assertions
+ unit: asserts/s
+ chart_type: stacked
+ dimensions:
+ - name: regular
+ - name: warning
+ - name: msg
+ - name: user
+ - name: tripwire
+ - name: rollovers
+ - name: mongodb.network_traffic_rate
+ description: Network traffic
+ unit: bytes/s
+ chart_type: stacked
+ dimensions:
+ - name: in
+ - name: out
+ - name: mongodb.network_requests_rate
+ description: Network Requests
+ unit: requests/s
+ chart_type: line
+ dimensions:
+ - name: requests
+ - name: mongodb.network_slow_dns_resolutions_rate
+ description: Slow DNS resolution operations
+ unit: resolutions/s
+ chart_type: line
+ dimensions:
+ - name: slow_dns
+ - name: mongodb.network_slow_ssl_handshakes_rate
+ description: Slow SSL handshake operations
+ unit: handshakes/s
+ chart_type: line
+ dimensions:
+ - name: slow_ssl
+ - name: mongodb.memory_resident_size
+ description: Used resident memory
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: used
+ - name: mongodb.memory_virtual_size
+ description: Used virtual memory
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: used
+ - name: mongodb.memory_page_faults_rate
+ description: Memory page faults
+ unit: pgfaults/s
+ chart_type: line
+ dimensions:
+ - name: pgfaults
+ - name: mongodb.memory_tcmalloc_stats
+ description: TCMalloc statistics
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: allocated
+ - name: central_cache_freelist
+ - name: transfer_cache_freelist
+ - name: thread_cache_freelists
+ - name: pageheap_freelist
+ - name: pageheap_unmapped
+ - name: mongodb.wiredtiger_concurrent_read_transactions_usage
+ description: Wired Tiger concurrent read transactions usage
+ unit: transactions
+ chart_type: stacked
+ dimensions:
+ - name: available
+ - name: used
+ - name: mongodb.wiredtiger_concurrent_write_transactions_usage
+ description: Wired Tiger concurrent write transactions usage
+ unit: transactions
+ chart_type: stacked
+ dimensions:
+ - name: available
+ - name: used
+ - name: mongodb.wiredtiger_cache_usage
+ description: Wired Tiger cache usage
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: used
+ - name: mongodb.wiredtiger_cache_dirty_space_size
+ description: Wired Tiger cache dirty space size
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: dirty
+ - name: mongodb.wiredtiger_cache_io_rate
+ description: Wired Tiger IO activity
+ unit: pages/s
+ chart_type: line
+ dimensions:
+ - name: read
+ - name: written
+ - name: mongodb.wiredtiger_cache_evictions_rate
+ description: Wired Tiger cache evictions
+ unit: pages/s
+ chart_type: stacked
+ dimensions:
+ - name: unmodified
+ - name: modified
+ - name: mongodb.sharding_nodes_count
+ description: Sharding Nodes
+ unit: nodes
+ chart_type: stacked
+ dimensions:
+ - name: shard_aware
+ - name: shard_unaware
+ - name: mongodb.sharding_sharded_databases_count
+ description: Sharded databases
+ unit: databases
+ chart_type: stacked
+ dimensions:
+ - name: partitioned
+ - name: unpartitioned
+ - name: mongodb.sharding_sharded_collections_count
+ description: Sharded collections
+ unit: collections
+ chart_type: stacked
+ dimensions:
+ - name: partitioned
+ - name: unpartitioned
+ - name: lock type
+ description: These metrics refer to the lock type.
+ labels:
+ - name: lock_type
+ description: lock type (e.g. global, database, collection, mutex)
+ metrics:
+ - name: mongodb.lock_acquisitions_rate
+ description: Lock acquisitions
+ unit: acquisitions/s
+ chart_type: line
+ dimensions:
+ - name: shared
+ - name: exclusive
+ - name: intent_shared
+ - name: intent_exclusive
+ - name: commit type
+ description: These metrics refer to the commit type.
+ labels:
+ - name: commit_type
+ description: commit type (e.g. noShards, singleShard, singleWriteShard)
+ metrics:
+ - name: mongodb.transactions_commits_rate
+ description: Transactions commits
+ unit: commits/s
+ chart_type: line
+ dimensions:
+ - name: success
+ - name: fail
+ - name: mongodb.transactions_commits_duration_time
+ description: Transactions successful commits duration
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: commits
+ - name: database
+ description: These metrics refer to the database.
+ labels:
+ - name: database
+ description: database name
+ metrics:
+ - name: mongodb.database_collection_count
+ description: Database collections
+ unit: collections
+ chart_type: line
+ dimensions:
+ - name: collections
+ - name: mongodb.database_indexes_count
+ description: Database indexes
+ unit: indexes
+ chart_type: line
+ dimensions:
+ - name: indexes
+ - name: mongodb.database_views_count
+ description: Database views
+ unit: views
+ chart_type: line
+ dimensions:
+ - name: views
+ - name: mongodb.database_documents_count
+ description: Database documents
+ unit: documents
+ chart_type: line
+ dimensions:
+ - name: documents
+ - name: mongodb.database_data_size
+ description: Database data size
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: data_size
+ - name: mongodb.database_storage_size
+ description: Database storage size
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: storage_size
+ - name: mongodb.database_index_size
+ description: Database index size
+ unit: bytes
+ chart_type: line
+ dimensions:
+ - name: index_size
+ - name: replica set member
+ description: These metrics refer to the replica set member.
+ labels:
+ - name: repl_set_member
+ description: replica set member name
+ metrics:
+ - name: mongodb.repl_set_member_state
+ description: Replica Set member state
+ unit: state
+ chart_type: line
+ dimensions:
+ - name: primary
+ - name: startup
+ - name: secondary
+ - name: recovering
+ - name: startup2
+ - name: unknown
+ - name: arbiter
+ - name: down
+ - name: rollback
+ - name: removed
+ - name: mongodb.repl_set_member_health_status
+ description: Replica Set member health status
+ unit: status
+ chart_type: line
+ dimensions:
+ - name: up
+ - name: down
+ - name: mongodb.repl_set_member_replication_lag_time
+ description: Replica Set member replication lag
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: replication_lag
+ - name: mongodb.repl_set_member_heartbeat_latency_time
+ description: Replica Set member heartbeat latency
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: heartbeat_latency
+ - name: mongodb.repl_set_member_ping_rtt_time
+ description: Replica Set member ping RTT
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: ping_rtt
+ - name: mongodb.repl_set_member_uptime
+ description: Replica Set member uptime
+ unit: seconds
+ chart_type: line
+ dimensions:
+ - name: uptime
+ - name: shard
+ description: These metrics refer to the shard.
+ labels:
+ - name: shard_id
+ description: shard id
+ metrics:
+ - name: mongodb.sharding_shard_chunks_count
+ description: Shard chunks
+ unit: chunks
+ chart_type: line
+ dimensions:
+ - name: chunks
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/mongodb.go b/src/go/collectors/go.d.plugin/modules/mongodb/mongodb.go
new file mode 100644
index 000000000..68c8b8b8a
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/mongodb.go
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ _ "embed"
+ "errors"
+ "sync"
+ "time"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/matcher"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/web"
+)
+
+//go:embed "config_schema.json"
+var configSchema string
+
+func init() {
+ module.Register("mongodb", module.Creator{
+ JobConfigSchema: configSchema,
+ Create: func() module.Module { return New() },
+ })
+}
+
+func New() *Mongo {
+ return &Mongo{
+ Config: Config{
+ URI: "mongodb://localhost:27017",
+ Timeout: web.Duration(time.Second),
+ Databases: matcher.SimpleExpr{
+ Includes: []string{},
+ Excludes: []string{},
+ },
+ },
+
+ conn: &mongoClient{},
+
+ charts: chartsServerStatus.Copy(),
+ addShardingChartsOnce: &sync.Once{},
+
+ optionalCharts: make(map[string]bool),
+ replSetMembers: make(map[string]bool),
+ databases: make(map[string]bool),
+ shards: make(map[string]bool),
+ }
+}
+
+type Config struct {
+ URI string `yaml:"uri" json:"uri"`
+ Timeout web.Duration `yaml:"timeout" json:"timeout"`
+ Databases matcher.SimpleExpr `yaml:"databases" json:"databases"`
+}
+
+type Mongo struct {
+ module.Base
+ Config `yaml:",inline" json:""`
+
+ charts *module.Charts
+ addShardingChartsOnce *sync.Once
+
+ conn mongoConn
+
+ dbSelector matcher.Matcher
+ optionalCharts map[string]bool
+ databases map[string]bool
+ replSetMembers map[string]bool
+ shards map[string]bool
+}
+
+func (m *Mongo) Configuration() any {
+ return m.Config
+}
+
+func (m *Mongo) Init() error {
+ if err := m.verifyConfig(); err != nil {
+ m.Errorf("config validation: %v", err)
+ return err
+ }
+
+ if err := m.initDatabaseSelector(); err != nil {
+ m.Errorf("init database selector: %v", err)
+ return err
+ }
+
+ return nil
+}
+
+func (m *Mongo) Check() error {
+ mx, err := m.collect()
+ if err != nil {
+ m.Error(err)
+ return err
+ }
+ if len(mx) == 0 {
+ return errors.New("no metrics collected")
+ }
+ return nil
+}
+
+func (m *Mongo) Charts() *module.Charts {
+ return m.charts
+}
+
+func (m *Mongo) Collect() map[string]int64 {
+ mx, err := m.collect()
+ if err != nil {
+ m.Error(err)
+ }
+
+ if len(mx) == 0 {
+ m.Warning("no values collected")
+ return nil
+ }
+
+ return mx
+}
+
+func (m *Mongo) Cleanup() {
+ if m.conn == nil {
+ return
+ }
+ if err := m.conn.close(); err != nil {
+ m.Warningf("cleanup: error on closing mongo conn: %v", err)
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/mongodb_test.go b/src/go/collectors/go.d.plugin/modules/mongodb/mongodb_test.go
new file mode 100644
index 000000000..c7cf0f42b
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/mongodb_test.go
@@ -0,0 +1,816 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package mongo
+
+import (
+ "encoding/json"
+ "errors"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/matcher"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ dataConfigJSON, _ = os.ReadFile("testdata/config.json")
+ dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
+
+ dataVer6MongodServerStatus, _ = os.ReadFile("testdata/v6.0.3/mongod-serverStatus.json")
+ dataVer6MongosServerStatus, _ = os.ReadFile("testdata/v6.0.3/mongos-serverStatus.json")
+ dataVer6DbStats, _ = os.ReadFile("testdata/v6.0.3/dbStats.json")
+ dataVer6ReplSetGetStatus, _ = os.ReadFile("testdata/v6.0.3/replSetGetStatus.json")
+)
+
+func Test_testDataIsValid(t *testing.T) {
+ for name, data := range map[string][]byte{
+ "dataConfigJSON": dataConfigJSON,
+ "dataConfigYAML": dataConfigYAML,
+ "dataVer6MongodServerStatus": dataVer6MongodServerStatus,
+ "dataVer6MongosServerStatus": dataVer6MongosServerStatus,
+ "dataVer6DbStats": dataVer6DbStats,
+ "dataVer6ReplSetGetStatus": dataVer6ReplSetGetStatus,
+ } {
+ require.NotNil(t, data, name)
+ }
+}
+
+func TestMongo_ConfigurationSerialize(t *testing.T) {
+ module.TestConfigurationSerialize(t, &Mongo{}, dataConfigJSON, dataConfigYAML)
+}
+
+func TestMongo_Init(t *testing.T) {
+ tests := map[string]struct {
+ config Config
+ wantFail bool
+ }{
+ "success on default config": {
+ wantFail: false,
+ config: New().Config,
+ },
+ "fails on unset 'address'": {
+ wantFail: true,
+ config: Config{
+ URI: "",
+ },
+ },
+ "fails on invalid database selector": {
+ wantFail: true,
+ config: Config{
+ URI: "mongodb://localhost:27017",
+ Databases: matcher.SimpleExpr{
+ Includes: []string{"!@#"},
+ },
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ mongo := New()
+ mongo.Config = test.config
+
+ if test.wantFail {
+ assert.Error(t, mongo.Init())
+ } else {
+ assert.NoError(t, mongo.Init())
+ }
+ })
+ }
+}
+
+func TestMongo_Charts(t *testing.T) {
+ assert.NotNil(t, New().Charts())
+}
+
+func TestMongo_Cleanup(t *testing.T) {
+ tests := map[string]struct {
+ prepare func(t *testing.T) *Mongo
+ wantClose bool
+ }{
+ "client not initialized": {
+ wantClose: false,
+ prepare: func(t *testing.T) *Mongo {
+ return New()
+ },
+ },
+ "client initialized": {
+ wantClose: true,
+ prepare: func(t *testing.T) *Mongo {
+ mongo := New()
+ mongo.conn = caseMongod()
+ _ = mongo.conn.initClient("", 0)
+
+ return mongo
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ mongo := test.prepare(t)
+
+ require.NotPanics(t, mongo.Cleanup)
+ if test.wantClose {
+ mock, ok := mongo.conn.(*mockMongoClient)
+ require.True(t, ok)
+ assert.True(t, mock.closeCalled)
+ }
+ })
+ }
+}
+
+func TestMongo_Check(t *testing.T) {
+ tests := map[string]struct {
+ prepare func() *mockMongoClient
+ wantFail bool
+ }{
+ "success on Mongod (v6)": {
+ wantFail: false,
+ prepare: caseMongod,
+ },
+ "success on Mongod Replicas Set(v6)": {
+ wantFail: false,
+ prepare: caseMongodReplicaSet,
+ },
+ "success on Mongos (v6)": {
+ wantFail: false,
+ prepare: caseMongos,
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ mongo := prepareMongo()
+ defer mongo.Cleanup()
+ mongo.conn = test.prepare()
+
+ require.NoError(t, mongo.Init())
+
+ if test.wantFail {
+ assert.Error(t, mongo.Check())
+ } else {
+ assert.NoError(t, mongo.Check())
+ }
+ })
+ }
+}
+
+func TestMongo_Collect(t *testing.T) {
+ tests := map[string]struct {
+ prepare func() *mockMongoClient
+ wantCollected map[string]int64
+ }{
+ "success on Mongod (v6)": {
+ prepare: caseMongod,
+ wantCollected: map[string]int64{
+ "asserts_msg": 0,
+ "asserts_regular": 0,
+ "asserts_rollovers": 0,
+ "asserts_tripwire": 0,
+ "asserts_user": 246,
+ "asserts_warning": 0,
+ "connections_active": 7,
+ "connections_available": 838841,
+ "connections_awaiting_topology_changes": 5,
+ "connections_current": 19,
+ "connections_exhaust_hello": 2,
+ "connections_exhaust_is_master": 1,
+ "connections_threaded": 19,
+ "connections_total_created": 77,
+ "database_admin_collections": 3,
+ "database_admin_data_size": 796,
+ "database_admin_documents": 5,
+ "database_admin_index_size": 81920,
+ "database_admin_indexes": 4,
+ "database_admin_storage_size": 61440,
+ "database_admin_views": 0,
+ "database_config_collections": 3,
+ "database_config_data_size": 796,
+ "database_config_documents": 5,
+ "database_config_index_size": 81920,
+ "database_config_indexes": 4,
+ "database_config_storage_size": 61440,
+ "database_config_views": 0,
+ "database_local_collections": 3,
+ "database_local_data_size": 796,
+ "database_local_documents": 5,
+ "database_local_index_size": 81920,
+ "database_local_indexes": 4,
+ "database_local_storage_size": 61440,
+ "database_local_views": 0,
+ "extra_info_page_faults": 0,
+ "global_lock_active_clients_readers": 0,
+ "global_lock_active_clients_writers": 0,
+ "global_lock_current_queue_readers": 0,
+ "global_lock_current_queue_writers": 0,
+ "locks_collection_acquire_exclusive": 6,
+ "locks_collection_acquire_intent_exclusive": 172523,
+ "locks_collection_acquire_intent_shared": 336370,
+ "locks_collection_acquire_shared": 0,
+ "locks_database_acquire_exclusive": 3,
+ "locks_database_acquire_intent_exclusive": 172539,
+ "locks_database_acquire_intent_shared": 50971,
+ "locks_database_acquire_shared": 0,
+ "locks_global_acquire_exclusive": 6,
+ "locks_global_acquire_intent_exclusive": 174228,
+ "locks_global_acquire_intent_shared": 437905,
+ "locks_global_acquire_shared": 0,
+ "locks_mutex_acquire_exclusive": 0,
+ "locks_mutex_acquire_intent_exclusive": 0,
+ "locks_mutex_acquire_intent_shared": 245077,
+ "locks_mutex_acquire_shared": 0,
+ "locks_oplog_acquire_exclusive": 0,
+ "locks_oplog_acquire_intent_exclusive": 1,
+ "locks_oplog_acquire_intent_shared": 16788,
+ "locks_oplog_acquire_shared": 0,
+ "memory_resident": 193986560,
+ "memory_virtual": 3023044608,
+ "metrics_cursor_lifespan_greater_than_or_equal_10_minutes": 0,
+ "metrics_cursor_lifespan_less_than_10_minutes": 0,
+ "metrics_cursor_lifespan_less_than_15_seconds": 0,
+ "metrics_cursor_lifespan_less_than_1_minute": 0,
+ "metrics_cursor_lifespan_less_than_1_second": 0,
+ "metrics_cursor_lifespan_less_than_30_seconds": 0,
+ "metrics_cursor_lifespan_less_than_5_seconds": 0,
+ "metrics_cursor_open_no_timeout": 0,
+ "metrics_cursor_open_total": 1,
+ "metrics_cursor_timed_out": 0,
+ "metrics_cursor_total_opened": 1,
+ "metrics_document_deleted": 7,
+ "metrics_document_inserted": 0,
+ "metrics_document_returned": 1699,
+ "metrics_document_updated": 52,
+ "metrics_query_executor_scanned": 61,
+ "metrics_query_executor_scanned_objects": 1760,
+ "network_bytes_in": 38851356,
+ "network_bytes_out": 706335836,
+ "network_requests": 130530,
+ "network_slow_dns_operations": 0,
+ "network_slow_ssl_operations": 0,
+ "operations_command": 125531,
+ "operations_delete": 7,
+ "operations_getmore": 5110,
+ "operations_insert": 0,
+ "operations_latencies_commands_latency": 46432082,
+ "operations_latencies_commands_ops": 125412,
+ "operations_latencies_reads_latency": 1009868,
+ "operations_latencies_reads_ops": 5111,
+ "operations_latencies_writes_latency": 0,
+ "operations_latencies_writes_ops": 0,
+ "operations_query": 76,
+ "operations_update": 59,
+ "tcmalloc_aggressive_memory_decommit": 0,
+ "tcmalloc_central_cache_free_bytes": 406680,
+ "tcmalloc_current_total_thread_cache_bytes": 2490832,
+ "tcmalloc_generic_current_allocated_bytes": 109050648,
+ "tcmalloc_generic_heap_size": 127213568,
+ "tcmalloc_max_total_thread_cache_bytes": 1073741824,
+ "tcmalloc_pageheap_commit_count": 376,
+ "tcmalloc_pageheap_committed_bytes": 127086592,
+ "tcmalloc_pageheap_decommit_count": 122,
+ "tcmalloc_pageheap_free_bytes": 13959168,
+ "tcmalloc_pageheap_reserve_count": 60,
+ "tcmalloc_pageheap_scavenge_bytes": 0,
+ "tcmalloc_pageheap_total_commit_bytes": 229060608,
+ "tcmalloc_pageheap_total_decommit_bytes": 101974016,
+ "tcmalloc_pageheap_total_reserve_bytes": 127213568,
+ "tcmalloc_pageheap_unmapped_bytes": 126976,
+ "tcmalloc_spinlock_total_delay_ns": 33426251,
+ "tcmalloc_thread_cache_free_bytes": 2490832,
+ "tcmalloc_total_free_bytes": 4076776,
+ "tcmalloc_transfer_cache_free_bytes": 1179264,
+ "txn_active": 0,
+ "txn_inactive": 0,
+ "txn_open": 0,
+ "txn_prepared": 0,
+ "txn_total_aborted": 0,
+ "txn_total_committed": 0,
+ "txn_total_prepared": 0,
+ "txn_total_started": 0,
+ "wiredtiger_cache_currently_in_cache_bytes": 814375,
+ "wiredtiger_cache_maximum_configured_bytes": 7854882816,
+ "wiredtiger_cache_modified_evicted_pages": 0,
+ "wiredtiger_cache_read_into_cache_pages": 108,
+ "wiredtiger_cache_tracked_dirty_in_the_cache_bytes": 456446,
+ "wiredtiger_cache_unmodified_evicted_pages": 0,
+ "wiredtiger_cache_written_from_cache_pages": 3177,
+ "wiredtiger_concurrent_txn_read_available": 128,
+ "wiredtiger_concurrent_txn_read_out": 0,
+ "wiredtiger_concurrent_txn_write_available": 128,
+ "wiredtiger_concurrent_txn_write_out": 0,
+ },
+ },
+ "success on Mongod Replica Set (v6)": {
+ prepare: caseMongodReplicaSet,
+ wantCollected: map[string]int64{
+ "asserts_msg": 0,
+ "asserts_regular": 0,
+ "asserts_rollovers": 0,
+ "asserts_tripwire": 0,
+ "asserts_user": 246,
+ "asserts_warning": 0,
+ "connections_active": 7,
+ "connections_available": 838841,
+ "connections_awaiting_topology_changes": 5,
+ "connections_current": 19,
+ "connections_exhaust_hello": 2,
+ "connections_exhaust_is_master": 1,
+ "connections_threaded": 19,
+ "connections_total_created": 77,
+ "database_admin_collections": 3,
+ "database_admin_data_size": 796,
+ "database_admin_documents": 5,
+ "database_admin_index_size": 81920,
+ "database_admin_indexes": 4,
+ "database_admin_storage_size": 61440,
+ "database_admin_views": 0,
+ "database_config_collections": 3,
+ "database_config_data_size": 796,
+ "database_config_documents": 5,
+ "database_config_index_size": 81920,
+ "database_config_indexes": 4,
+ "database_config_storage_size": 61440,
+ "database_config_views": 0,
+ "database_local_collections": 3,
+ "database_local_data_size": 796,
+ "database_local_documents": 5,
+ "database_local_index_size": 81920,
+ "database_local_indexes": 4,
+ "database_local_storage_size": 61440,
+ "database_local_views": 0,
+ "extra_info_page_faults": 0,
+ "global_lock_active_clients_readers": 0,
+ "global_lock_active_clients_writers": 0,
+ "global_lock_current_queue_readers": 0,
+ "global_lock_current_queue_writers": 0,
+ "locks_collection_acquire_exclusive": 6,
+ "locks_collection_acquire_intent_exclusive": 172523,
+ "locks_collection_acquire_intent_shared": 336370,
+ "locks_collection_acquire_shared": 0,
+ "locks_database_acquire_exclusive": 3,
+ "locks_database_acquire_intent_exclusive": 172539,
+ "locks_database_acquire_intent_shared": 50971,
+ "locks_database_acquire_shared": 0,
+ "locks_global_acquire_exclusive": 6,
+ "locks_global_acquire_intent_exclusive": 174228,
+ "locks_global_acquire_intent_shared": 437905,
+ "locks_global_acquire_shared": 0,
+ "locks_mutex_acquire_exclusive": 0,
+ "locks_mutex_acquire_intent_exclusive": 0,
+ "locks_mutex_acquire_intent_shared": 245077,
+ "locks_mutex_acquire_shared": 0,
+ "locks_oplog_acquire_exclusive": 0,
+ "locks_oplog_acquire_intent_exclusive": 1,
+ "locks_oplog_acquire_intent_shared": 16788,
+ "locks_oplog_acquire_shared": 0,
+ "memory_resident": 193986560,
+ "memory_virtual": 3023044608,
+ "metrics_cursor_lifespan_greater_than_or_equal_10_minutes": 0,
+ "metrics_cursor_lifespan_less_than_10_minutes": 0,
+ "metrics_cursor_lifespan_less_than_15_seconds": 0,
+ "metrics_cursor_lifespan_less_than_1_minute": 0,
+ "metrics_cursor_lifespan_less_than_1_second": 0,
+ "metrics_cursor_lifespan_less_than_30_seconds": 0,
+ "metrics_cursor_lifespan_less_than_5_seconds": 0,
+ "metrics_cursor_open_no_timeout": 0,
+ "metrics_cursor_open_total": 1,
+ "metrics_cursor_timed_out": 0,
+ "metrics_cursor_total_opened": 1,
+ "metrics_document_deleted": 7,
+ "metrics_document_inserted": 0,
+ "metrics_document_returned": 1699,
+ "metrics_document_updated": 52,
+ "metrics_query_executor_scanned": 61,
+ "metrics_query_executor_scanned_objects": 1760,
+ "network_bytes_in": 38851356,
+ "network_bytes_out": 706335836,
+ "network_requests": 130530,
+ "network_slow_dns_operations": 0,
+ "network_slow_ssl_operations": 0,
+ "operations_command": 125531,
+ "operations_delete": 7,
+ "operations_getmore": 5110,
+ "operations_insert": 0,
+ "operations_latencies_commands_latency": 46432082,
+ "operations_latencies_commands_ops": 125412,
+ "operations_latencies_reads_latency": 1009868,
+ "operations_latencies_reads_ops": 5111,
+ "operations_latencies_writes_latency": 0,
+ "operations_latencies_writes_ops": 0,
+ "operations_query": 76,
+ "operations_update": 59,
+ "repl_set_member_mongodb-primary:27017_health_status_down": 0,
+ "repl_set_member_mongodb-primary:27017_health_status_up": 1,
+ "repl_set_member_mongodb-primary:27017_replication_lag": 4572,
+ "repl_set_member_mongodb-primary:27017_state_arbiter": 0,
+ "repl_set_member_mongodb-primary:27017_state_down": 0,
+ "repl_set_member_mongodb-primary:27017_state_primary": 1,
+ "repl_set_member_mongodb-primary:27017_state_recovering": 0,
+ "repl_set_member_mongodb-primary:27017_state_removed": 0,
+ "repl_set_member_mongodb-primary:27017_state_rollback": 0,
+ "repl_set_member_mongodb-primary:27017_state_secondary": 0,
+ "repl_set_member_mongodb-primary:27017_state_startup": 0,
+ "repl_set_member_mongodb-primary:27017_state_startup2": 0,
+ "repl_set_member_mongodb-primary:27017_state_unknown": 0,
+ "repl_set_member_mongodb-secondary:27017_health_status_down": 0,
+ "repl_set_member_mongodb-secondary:27017_health_status_up": 1,
+ "repl_set_member_mongodb-secondary:27017_heartbeat_latency": 1359,
+ "repl_set_member_mongodb-secondary:27017_ping_rtt": 0,
+ "repl_set_member_mongodb-secondary:27017_replication_lag": 4572,
+ "repl_set_member_mongodb-secondary:27017_state_arbiter": 0,
+ "repl_set_member_mongodb-secondary:27017_state_down": 0,
+ "repl_set_member_mongodb-secondary:27017_state_primary": 0,
+ "repl_set_member_mongodb-secondary:27017_state_recovering": 0,
+ "repl_set_member_mongodb-secondary:27017_state_removed": 0,
+ "repl_set_member_mongodb-secondary:27017_state_rollback": 0,
+ "repl_set_member_mongodb-secondary:27017_state_secondary": 1,
+ "repl_set_member_mongodb-secondary:27017_state_startup": 0,
+ "repl_set_member_mongodb-secondary:27017_state_startup2": 0,
+ "repl_set_member_mongodb-secondary:27017_state_unknown": 0,
+ "repl_set_member_mongodb-secondary:27017_uptime": 192370,
+ "tcmalloc_aggressive_memory_decommit": 0,
+ "tcmalloc_central_cache_free_bytes": 406680,
+ "tcmalloc_current_total_thread_cache_bytes": 2490832,
+ "tcmalloc_generic_current_allocated_bytes": 109050648,
+ "tcmalloc_generic_heap_size": 127213568,
+ "tcmalloc_max_total_thread_cache_bytes": 1073741824,
+ "tcmalloc_pageheap_commit_count": 376,
+ "tcmalloc_pageheap_committed_bytes": 127086592,
+ "tcmalloc_pageheap_decommit_count": 122,
+ "tcmalloc_pageheap_free_bytes": 13959168,
+ "tcmalloc_pageheap_reserve_count": 60,
+ "tcmalloc_pageheap_scavenge_bytes": 0,
+ "tcmalloc_pageheap_total_commit_bytes": 229060608,
+ "tcmalloc_pageheap_total_decommit_bytes": 101974016,
+ "tcmalloc_pageheap_total_reserve_bytes": 127213568,
+ "tcmalloc_pageheap_unmapped_bytes": 126976,
+ "tcmalloc_spinlock_total_delay_ns": 33426251,
+ "tcmalloc_thread_cache_free_bytes": 2490832,
+ "tcmalloc_total_free_bytes": 4076776,
+ "tcmalloc_transfer_cache_free_bytes": 1179264,
+ "txn_active": 0,
+ "txn_inactive": 0,
+ "txn_open": 0,
+ "txn_prepared": 0,
+ "txn_total_aborted": 0,
+ "txn_total_committed": 0,
+ "txn_total_prepared": 0,
+ "txn_total_started": 0,
+ "wiredtiger_cache_currently_in_cache_bytes": 814375,
+ "wiredtiger_cache_maximum_configured_bytes": 7854882816,
+ "wiredtiger_cache_modified_evicted_pages": 0,
+ "wiredtiger_cache_read_into_cache_pages": 108,
+ "wiredtiger_cache_tracked_dirty_in_the_cache_bytes": 456446,
+ "wiredtiger_cache_unmodified_evicted_pages": 0,
+ "wiredtiger_cache_written_from_cache_pages": 3177,
+ "wiredtiger_concurrent_txn_read_available": 128,
+ "wiredtiger_concurrent_txn_read_out": 0,
+ "wiredtiger_concurrent_txn_write_available": 128,
+ "wiredtiger_concurrent_txn_write_out": 0,
+ },
+ },
+ "success on Mongos (v6)": {
+ prepare: caseMongos,
+ wantCollected: map[string]int64{
+ "asserts_msg": 0,
+ "asserts_regular": 0,
+ "asserts_rollovers": 0,
+ "asserts_tripwire": 0,
+ "asserts_user": 352,
+ "asserts_warning": 0,
+ "connections_active": 5,
+ "connections_available": 838842,
+ "connections_awaiting_topology_changes": 4,
+ "connections_current": 18,
+ "connections_exhaust_hello": 3,
+ "connections_exhaust_is_master": 0,
+ "connections_threaded": 18,
+ "connections_total_created": 89,
+ "database_admin_collections": 3,
+ "database_admin_data_size": 796,
+ "database_admin_documents": 5,
+ "database_admin_index_size": 81920,
+ "database_admin_indexes": 4,
+ "database_admin_storage_size": 61440,
+ "database_admin_views": 0,
+ "database_config_collections": 3,
+ "database_config_data_size": 796,
+ "database_config_documents": 5,
+ "database_config_index_size": 81920,
+ "database_config_indexes": 4,
+ "database_config_storage_size": 61440,
+ "database_config_views": 0,
+ "database_local_collections": 3,
+ "database_local_data_size": 796,
+ "database_local_documents": 5,
+ "database_local_index_size": 81920,
+ "database_local_indexes": 4,
+ "database_local_storage_size": 61440,
+ "database_local_views": 0,
+ "extra_info_page_faults": 526,
+ "memory_resident": 84934656,
+ "memory_virtual": 2596274176,
+ "metrics_document_deleted": 0,
+ "metrics_document_inserted": 0,
+ "metrics_document_returned": 0,
+ "metrics_document_updated": 0,
+ "metrics_query_executor_scanned": 0,
+ "metrics_query_executor_scanned_objects": 0,
+ "network_bytes_in": 57943348,
+ "network_bytes_out": 247343709,
+ "network_requests": 227310,
+ "network_slow_dns_operations": 0,
+ "network_slow_ssl_operations": 0,
+ "operations_command": 227283,
+ "operations_delete": 0,
+ "operations_getmore": 0,
+ "operations_insert": 0,
+ "operations_query": 10,
+ "operations_update": 0,
+ "shard_collections_partitioned": 1,
+ "shard_collections_unpartitioned": 1,
+ "shard_databases_partitioned": 1,
+ "shard_databases_unpartitioned": 1,
+ "shard_id_shard0_chunks": 1,
+ "shard_id_shard1_chunks": 1,
+ "shard_nodes_aware": 1,
+ "shard_nodes_unaware": 1,
+ "tcmalloc_aggressive_memory_decommit": 0,
+ "tcmalloc_central_cache_free_bytes": 736960,
+ "tcmalloc_current_total_thread_cache_bytes": 1638104,
+ "tcmalloc_generic_current_allocated_bytes": 13519784,
+ "tcmalloc_generic_heap_size": 24576000,
+ "tcmalloc_max_total_thread_cache_bytes": 1042284544,
+ "tcmalloc_pageheap_commit_count": 480,
+ "tcmalloc_pageheap_committed_bytes": 24518656,
+ "tcmalloc_pageheap_decommit_count": 127,
+ "tcmalloc_pageheap_free_bytes": 5697536,
+ "tcmalloc_pageheap_reserve_count": 15,
+ "tcmalloc_pageheap_scavenge_bytes": 0,
+ "tcmalloc_pageheap_total_commit_bytes": 84799488,
+ "tcmalloc_pageheap_total_decommit_bytes": 60280832,
+ "tcmalloc_pageheap_total_reserve_bytes": 24576000,
+ "tcmalloc_pageheap_unmapped_bytes": 57344,
+ "tcmalloc_spinlock_total_delay_ns": 96785212,
+ "tcmalloc_thread_cache_free_bytes": 1638104,
+ "tcmalloc_total_free_bytes": 5301336,
+ "tcmalloc_transfer_cache_free_bytes": 2926272,
+ "txn_active": 0,
+ "txn_commit_types_no_shards_initiated": 0,
+ "txn_commit_types_no_shards_successful": 0,
+ "txn_commit_types_no_shards_successful_duration_micros": 0,
+ "txn_commit_types_no_shards_unsuccessful": 0,
+ "txn_commit_types_read_only_initiated": 0,
+ "txn_commit_types_read_only_successful": 0,
+ "txn_commit_types_read_only_successful_duration_micros": 0,
+ "txn_commit_types_read_only_unsuccessful": 0,
+ "txn_commit_types_recover_with_token_initiated": 0,
+ "txn_commit_types_recover_with_token_successful": 0,
+ "txn_commit_types_recover_with_token_successful_duration_micros": 0,
+ "txn_commit_types_recover_with_token_unsuccessful": 0,
+ "txn_commit_types_single_shard_initiated": 0,
+ "txn_commit_types_single_shard_successful": 0,
+ "txn_commit_types_single_shard_successful_duration_micros": 0,
+ "txn_commit_types_single_shard_unsuccessful": 0,
+ "txn_commit_types_single_write_shard_initiated": 0,
+ "txn_commit_types_single_write_shard_successful": 0,
+ "txn_commit_types_single_write_shard_successful_duration_micros": 0,
+ "txn_commit_types_single_write_shard_unsuccessful": 0,
+ "txn_commit_types_two_phase_commit_initiated": 0,
+ "txn_commit_types_two_phase_commit_successful": 0,
+ "txn_commit_types_two_phase_commit_successful_duration_micros": 0,
+ "txn_commit_types_two_phase_commit_unsuccessful": 0,
+ "txn_inactive": 0,
+ "txn_open": 0,
+ "txn_total_aborted": 0,
+ "txn_total_committed": 0,
+ "txn_total_started": 0,
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ mongo := prepareMongo()
+ defer mongo.Cleanup()
+ mongo.conn = test.prepare()
+
+ require.NoError(t, mongo.Init())
+
+ mx := mongo.Collect()
+
+ assert.Equal(t, test.wantCollected, mx)
+ })
+ }
+}
+
+func prepareMongo() *Mongo {
+ m := New()
+ m.Databases = matcher.SimpleExpr{Includes: []string{"* *"}}
+ return m
+}
+
+func caseMongodReplicaSet() *mockMongoClient {
+ return &mockMongoClient{replicaSet: true}
+}
+
+func caseMongod() *mockMongoClient {
+ return &mockMongoClient{}
+}
+
+func caseMongos() *mockMongoClient {
+ return &mockMongoClient{mongos: true}
+}
+
+type mockMongoClient struct {
+ replicaSet bool
+ mongos bool
+ errOnServerStatus bool
+ errOnListDatabaseNames bool
+ errOnDbStats bool
+ errOnReplSetGetStatus bool
+ errOnShardNodes bool
+ errOnShardDatabasesPartitioning bool
+ errOnShardCollectionsPartitioning bool
+ errOnShardChunks bool
+ errOnInitClient bool
+ clientInited bool
+ closeCalled bool
+}
+
+func (m *mockMongoClient) serverStatus() (*documentServerStatus, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.serverStatus() error: mongo client not inited")
+ }
+ if m.errOnServerStatus {
+ return nil, errors.New("mock.serverStatus() error")
+ }
+
+ data := dataVer6MongodServerStatus
+ if m.mongos {
+ data = dataVer6MongosServerStatus
+ }
+
+ var s documentServerStatus
+ if err := json.Unmarshal(data, &s); err != nil {
+ return nil, err
+ }
+
+ return &s, nil
+}
+
+func (m *mockMongoClient) listDatabaseNames() ([]string, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.listDatabaseNames() error: mongo client not inited")
+ }
+ if m.errOnListDatabaseNames {
+ return nil, errors.New("mock.listDatabaseNames() error")
+ }
+ return []string{"admin", "config", "local"}, nil
+}
+
+func (m *mockMongoClient) dbStats(_ string) (*documentDBStats, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.dbStats() error: mongo client not inited")
+ }
+ if m.errOnDbStats {
+ return nil, errors.New("mock.dbStats() error")
+ }
+
+ var s documentDBStats
+ if err := json.Unmarshal(dataVer6DbStats, &s); err != nil {
+ return nil, err
+ }
+
+ return &s, nil
+}
+
+func (m *mockMongoClient) isReplicaSet() bool {
+ return m.replicaSet
+}
+
+func (m *mockMongoClient) isMongos() bool {
+ return m.mongos
+}
+
+func (m *mockMongoClient) replSetGetStatus() (*documentReplSetStatus, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.replSetGetStatus() error: mongo client not inited")
+ }
+ if m.mongos {
+ return nil, errors.New("mock.replSetGetStatus() error: shouldn't be called for mongos")
+ }
+ if !m.replicaSet {
+ return nil, errors.New("mock.replSetGetStatus() error: should be called for replica set")
+ }
+ if m.errOnReplSetGetStatus {
+ return nil, errors.New("mock.replSetGetStatus() error")
+ }
+
+ var s documentReplSetStatus
+ if err := json.Unmarshal(dataVer6ReplSetGetStatus, &s); err != nil {
+ return nil, err
+ }
+
+ return &s, nil
+}
+
+func (m *mockMongoClient) shardNodes() (*documentShardNodesResult, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.shardNodes() error: mongo client not inited")
+ }
+ if m.replicaSet {
+ return nil, errors.New("mock.replSetGetStatus() error: shouldn't be called for replica set")
+ }
+ if !m.mongos {
+ return nil, errors.New("mock.shardNodes() error: should be called for mongos")
+ }
+ if m.errOnShardNodes {
+ return nil, errors.New("mock.shardNodes() error")
+ }
+
+ return &documentShardNodesResult{
+ ShardAware: 1,
+ ShardUnaware: 1,
+ }, nil
+}
+
+func (m *mockMongoClient) shardDatabasesPartitioning() (*documentPartitionedResult, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.shardDatabasesPartitioning() error: mongo client not inited")
+ }
+ if m.replicaSet {
+ return nil, errors.New("mock.shardDatabasesPartitioning() error: shouldn't be called for replica set")
+ }
+ if !m.mongos {
+ return nil, errors.New("mock.shardDatabasesPartitioning() error: should be called for mongos")
+ }
+ if m.errOnShardDatabasesPartitioning {
+ return nil, errors.New("mock.shardDatabasesPartitioning() error")
+ }
+
+ return &documentPartitionedResult{
+ Partitioned: 1,
+ UnPartitioned: 1,
+ }, nil
+}
+
+func (m *mockMongoClient) shardCollectionsPartitioning() (*documentPartitionedResult, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.shardCollectionsPartitioning() error: mongo client not inited")
+ }
+ if m.replicaSet {
+ return nil, errors.New("mock.shardCollectionsPartitioning() error: shouldn't be called for replica set")
+ }
+ if !m.mongos {
+ return nil, errors.New("mock.shardCollectionsPartitioning() error: should be called for mongos")
+ }
+ if m.errOnShardCollectionsPartitioning {
+ return nil, errors.New("mock.shardCollectionsPartitioning() error")
+ }
+
+ return &documentPartitionedResult{
+ Partitioned: 1,
+ UnPartitioned: 1,
+ }, nil
+}
+
+func (m *mockMongoClient) shardChunks() (map[string]int64, error) {
+ if !m.clientInited {
+ return nil, errors.New("mock.shardChunks() error: mongo client not inited")
+ }
+ if m.replicaSet {
+ return nil, errors.New("mock.shardChunks() error: shouldn't be called for replica set")
+ }
+ if !m.mongos {
+ return nil, errors.New("mock.shardChunks() error: should be called for mongos")
+ }
+ if m.errOnShardChunks {
+ return nil, errors.New("mock.shardChunks() error")
+ }
+
+ return map[string]int64{
+ "shard0": 1,
+ "shard1": 1,
+ }, nil
+}
+
+func (m *mockMongoClient) initClient(_ string, _ time.Duration) error {
+ if m.errOnInitClient {
+ return errors.New("mock.initClient() error")
+ }
+ m.clientInited = true
+ return nil
+}
+
+func (m *mockMongoClient) close() error {
+ if m.clientInited {
+ m.closeCalled = true
+ }
+ return nil
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.json b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.json
new file mode 100644
index 000000000..2c2f63e68
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.json
@@ -0,0 +1,12 @@
+{
+ "uri": "ok",
+ "timeout": 123.123,
+ "databases": {
+ "includes": [
+ "ok"
+ ],
+ "excludes": [
+ "ok"
+ ]
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.yaml b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.yaml
new file mode 100644
index 000000000..53529ea98
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/config.yaml
@@ -0,0 +1,7 @@
+uri: "ok"
+timeout: 123.123
+databases:
+ includes:
+ - "ok"
+ excludes:
+ - "ok"
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/dbStats.json b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/dbStats.json
new file mode 100644
index 000000000..52a513203
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/dbStats.json
@@ -0,0 +1,9 @@
+{
+ "Collections": 3,
+ "Views": 0,
+ "Indexes": 4,
+ "Objects": 5,
+ "DataSize": 796,
+ "IndexSize": 81920,
+ "StorageSize": 61440
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongod-serverStatus.json b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongod-serverStatus.json
new file mode 100644
index 000000000..77f083923
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongod-serverStatus.json
@@ -0,0 +1,497 @@
+{
+ "Process": "mongod",
+ "OpCounters": {
+ "Insert": 0,
+ "Query": 76,
+ "Update": 59,
+ "Delete": 7,
+ "GetMore": 5110,
+ "Command": 125531
+ },
+ "OpLatencies": {
+ "Reads": {
+ "Latency": 1009868,
+ "Ops": 5111
+ },
+ "Writes": {
+ "Latency": 0,
+ "Ops": 0
+ },
+ "Commands": {
+ "Latency": 46432082,
+ "Ops": 125412
+ }
+ },
+ "Connections": {
+ "Current": 19,
+ "Available": 838841,
+ "TotalCreated": 77,
+ "Active": 7,
+ "Threaded": 19,
+ "ExhaustIsMaster": 1,
+ "ExhaustHello": 2,
+ "AwaitingTopologyChanges": 5
+ },
+ "Network": {
+ "BytesIn": 38851356,
+ "BytesOut": 706335836,
+ "NumRequests": 130530,
+ "NumSlowDNSOperations": 0,
+ "NumSlowSSLOperations": 0
+ },
+ "Memory": {
+ "Resident": 185,
+ "Virtual": 2883
+ },
+ "Metrics": {
+ "Cursor": {
+ "TotalOpened": 1,
+ "TimedOut": 0,
+ "Open": {
+ "NoTimeout": 0,
+ "Total": 1
+ },
+ "Lifespan": {
+ "GreaterThanOrEqual10Minutes": 0,
+ "LessThan10Minutes": 0,
+ "LessThan15Seconds": 0,
+ "LessThan1Minute": 0,
+ "LessThan1Second": 0,
+ "LessThan30Seconds": 0,
+ "LessThan5Seconds": 0
+ }
+ },
+ "Document": {
+ "Deleted": 7,
+ "Inserted": 0,
+ "Returned": 1699,
+ "Updated": 52
+ },
+ "QueryExecutor": {
+ "Scanned": 61,
+ "ScannedObjects": 1760
+ }
+ },
+ "ExtraInfo": {
+ "PageFaults": 0
+ },
+ "Asserts": {
+ "Regular": 0,
+ "Warning": 0,
+ "Msg": 0,
+ "User": 246,
+ "Tripwire": 0,
+ "Rollovers": 0
+ },
+ "Transactions": {
+ "CurrentActive": 0,
+ "CurrentInactive": 0,
+ "CurrentOpen": 0,
+ "CurrentPrepared": 0,
+ "TotalAborted": 0,
+ "TotalCommitted": 0,
+ "TotalStarted": 0,
+ "TotalPrepared": 0,
+ "CommitTypes": null
+ },
+ "GlobalLock": {
+ "CurrentQueue": {
+ "Readers": 0,
+ "Writers": 0
+ },
+ "ActiveClients": {
+ "Readers": 0,
+ "Writers": 0
+ }
+ },
+ "Tcmalloc": {
+ "Generic": {
+ "CurrentAllocatedBytes": 109050648,
+ "HeapSize": 127213568
+ },
+ "Tcmalloc": {
+ "PageheapFreeBytes": 13959168,
+ "PageheapUnmappedBytes": 126976,
+ "MaxTotalThreadCacheBytes": 1073741824,
+ "CurrentTotalThreadCacheBytes": 2490832,
+ "TotalFreeBytes": 4076776,
+ "CentralCacheFreeBytes": 406680,
+ "TransferCacheFreeBytes": 1179264,
+ "ThreadCacheFreeBytes": 2490832,
+ "AggressiveMemoryDecommit": 0,
+ "PageheapCommittedBytes": 127086592,
+ "PageheapScavengeBytes": 0,
+ "PageheapCommitCount": 376,
+ "PageheapTotalCommitBytes": 229060608,
+ "PageheapDecommitCount": 122,
+ "PageheapTotalDecommitBytes": 101974016,
+ "PageheapReserveCount": 60,
+ "PageheapTotalReserveBytes": 127213568,
+ "SpinlockTotalDelayNs": 33426251
+ }
+ },
+ "Locks": {
+ "Global": {
+ "AcquireCount": {
+ "Shared": 0,
+ "Exclusive": 6,
+ "IntentShared": 437905,
+ "IntentExclusive": 174228
+ }
+ },
+ "Database": {
+ "AcquireCount": {
+ "Shared": 0,
+ "Exclusive": 3,
+ "IntentShared": 50971,
+ "IntentExclusive": 172539
+ }
+ },
+ "Collection": {
+ "AcquireCount": {
+ "Shared": 0,
+ "Exclusive": 6,
+ "IntentShared": 336370,
+ "IntentExclusive": 172523
+ }
+ },
+ "Mutex": {
+ "AcquireCount": {
+ "Shared": 0,
+ "Exclusive": 0,
+ "IntentShared": 245077,
+ "IntentExclusive": 0
+ }
+ },
+ "Metadata": null,
+ "Oplog": {
+ "AcquireCount": {
+ "Shared": 0,
+ "Exclusive": 0,
+ "IntentShared": 16788,
+ "IntentExclusive": 1
+ }
+ }
+ },
+ "WiredTiger": {
+ "ConcurrentTransaction": {
+ "Write": {
+ "Out": 0,
+ "Available": 128
+ },
+ "Read": {
+ "Out": 0,
+ "Available": 128
+ }
+ },
+ "Cache": {
+ "BytesCurrentlyInCache": 814375,
+ "MaximumBytesConfigured": 7854882816,
+ "TrackedDirtyBytesInCache": 456446,
+ "UnmodifiedPagesEvicted": 0,
+ "ModifiedPagesEvicted": 0,
+ "PagesReadIntoCache": 108,
+ "PagesWrittenFromCache": 3177
+ }
+ },
+ "Repl": [
+ {
+ "Key": "topologyVersion",
+ "Value": [
+ {
+ "Key": "processId",
+ "Value": "63b043be562288304ad3b4fe"
+ },
+ {
+ "Key": "counter",
+ "Value": 7
+ }
+ ]
+ },
+ {
+ "Key": "hosts",
+ "Value": [
+ "mongodb-primary:27017",
+ "mongodb-secondary:27017"
+ ]
+ },
+ {
+ "Key": "setName",
+ "Value": "replicaset"
+ },
+ {
+ "Key": "setVersion",
+ "Value": 4
+ },
+ {
+ "Key": "isWritablePrimary",
+ "Value": true
+ },
+ {
+ "Key": "secondary",
+ "Value": false
+ },
+ {
+ "Key": "primary",
+ "Value": "mongodb-primary:27017"
+ },
+ {
+ "Key": "me",
+ "Value": "mongodb-primary:27017"
+ },
+ {
+ "Key": "electionId",
+ "Value": "7fffffff0000000000000006"
+ },
+ {
+ "Key": "lastWrite",
+ "Value": [
+ {
+ "Key": "opTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "lastWriteDate",
+ "Value": "2022-12-31T20:54:44+02:00"
+ },
+ {
+ "Key": "majorityOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "majorityWriteDate",
+ "Value": "2022-12-31T20:54:44+02:00"
+ }
+ ]
+ },
+ {
+ "Key": "replicationProgress",
+ "Value": [
+ [
+ {
+ "Key": "host",
+ "Value": "mongodb-primary:27017"
+ },
+ {
+ "Key": "optime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "lastAppliedOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "heartbeatAppliedOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 0,
+ "I": 0
+ }
+ },
+ {
+ "Key": "t",
+ "Value": -1
+ }
+ ]
+ },
+ {
+ "Key": "heartbeatDurableOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 0,
+ "I": 0
+ }
+ },
+ {
+ "Key": "t",
+ "Value": -1
+ }
+ ]
+ },
+ {
+ "Key": "memberId",
+ "Value": 0
+ }
+ ],
+ [
+ {
+ "Key": "host",
+ "Value": "mongodb-secondary:27017"
+ },
+ {
+ "Key": "optime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "lastAppliedOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "heartbeatAppliedOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "heartbeatDurableOpTime",
+ "Value": [
+ {
+ "Key": "ts",
+ "Value": {
+ "T": 1672512884,
+ "I": 1
+ }
+ },
+ {
+ "Key": "t",
+ "Value": 6
+ }
+ ]
+ },
+ {
+ "Key": "memberId",
+ "Value": 1
+ }
+ ]
+ ]
+ },
+ {
+ "Key": "primaryOnlyServices",
+ "Value": [
+ {
+ "Key": "ShardSplitDonorService",
+ "Value": [
+ {
+ "Key": "state",
+ "Value": "running"
+ },
+ {
+ "Key": "numInstances",
+ "Value": 0
+ }
+ ]
+ },
+ {
+ "Key": "TenantMigrationRecipientService",
+ "Value": [
+ {
+ "Key": "state",
+ "Value": "running"
+ },
+ {
+ "Key": "numInstances",
+ "Value": 0
+ }
+ ]
+ },
+ {
+ "Key": "TenantMigrationDonorService",
+ "Value": [
+ {
+ "Key": "state",
+ "Value": "running"
+ },
+ {
+ "Key": "numInstances",
+ "Value": 0
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "Key": "rbid",
+ "Value": 2
+ },
+ {
+ "Key": "userWriteBlockMode",
+ "Value": 1
+ }
+ ]
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongos-serverStatus.json b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongos-serverStatus.json
new file mode 100644
index 000000000..ecf766715
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/mongos-serverStatus.json
@@ -0,0 +1,129 @@
+{
+ "Process": "mongos",
+ "OpCounters": {
+ "Insert": 0,
+ "Query": 10,
+ "Update": 0,
+ "Delete": 0,
+ "GetMore": 0,
+ "Command": 227283
+ },
+ "OpLatencies": null,
+ "Connections": {
+ "Current": 18,
+ "Available": 838842,
+ "TotalCreated": 89,
+ "Active": 5,
+ "Threaded": 18,
+ "ExhaustIsMaster": 0,
+ "ExhaustHello": 3,
+ "AwaitingTopologyChanges": 4
+ },
+ "Network": {
+ "BytesIn": 57943348,
+ "BytesOut": 247343709,
+ "NumRequests": 227310,
+ "NumSlowDNSOperations": 0,
+ "NumSlowSSLOperations": 0
+ },
+ "Memory": {
+ "Resident": 81,
+ "Virtual": 2476
+ },
+ "Metrics": {
+ "Cursor": {},
+ "Document": {
+ "Deleted": 0,
+ "Inserted": 0,
+ "Returned": 0,
+ "Updated": 0
+ },
+ "QueryExecutor": {
+ "Scanned": 0,
+ "ScannedObjects": 0
+ }
+ },
+ "ExtraInfo": {
+ "PageFaults": 526
+ },
+ "Asserts": {
+ "Regular": 0,
+ "Warning": 0,
+ "Msg": 0,
+ "User": 352,
+ "Tripwire": 0,
+ "Rollovers": 0
+ },
+ "Transactions": {
+ "CurrentActive": 0,
+ "CurrentInactive": 0,
+ "CurrentOpen": 0,
+ "CurrentPrepared": null,
+ "TotalAborted": 0,
+ "TotalCommitted": 0,
+ "TotalStarted": 0,
+ "TotalPrepared": null,
+ "CommitTypes": {
+ "NoShards": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ },
+ "SingleShard": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ },
+ "SingleWriteShard": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ },
+ "ReadOnly": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ },
+ "TwoPhaseCommit": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ },
+ "RecoverWithToken": {
+ "initiated": 0,
+ "successful": 0,
+ "successfulDurationMicros": 0
+ }
+ }
+ },
+ "GlobalLock": null,
+ "Tcmalloc": {
+ "Generic": {
+ "CurrentAllocatedBytes": 13519784,
+ "HeapSize": 24576000
+ },
+ "Tcmalloc": {
+ "PageheapFreeBytes": 5697536,
+ "PageheapUnmappedBytes": 57344,
+ "MaxTotalThreadCacheBytes": 1042284544,
+ "CurrentTotalThreadCacheBytes": 1638104,
+ "TotalFreeBytes": 5301336,
+ "CentralCacheFreeBytes": 736960,
+ "TransferCacheFreeBytes": 2926272,
+ "ThreadCacheFreeBytes": 1638104,
+ "AggressiveMemoryDecommit": 0,
+ "PageheapCommittedBytes": 24518656,
+ "PageheapScavengeBytes": 0,
+ "PageheapCommitCount": 480,
+ "PageheapTotalCommitBytes": 84799488,
+ "PageheapDecommitCount": 127,
+ "PageheapTotalDecommitBytes": 60280832,
+ "PageheapReserveCount": 15,
+ "PageheapTotalReserveBytes": 24576000,
+ "SpinlockTotalDelayNs": 96785212
+ }
+ },
+ "Locks": null,
+ "WiredTiger": null,
+ "Repl": null
+}
diff --git a/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/replSetGetStatus.json b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/replSetGetStatus.json
new file mode 100644
index 000000000..c97a77f31
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/mongodb/testdata/v6.0.3/replSetGetStatus.json
@@ -0,0 +1,27 @@
+{
+ "Date": "2022-12-30T22:19:29.572Z",
+ "Members": [
+ {
+ "Name": "mongodb-primary:27017",
+ "Self": true,
+ "State": 1,
+ "Health": 1,
+ "OptimeDate": "2022-12-30T22:19:25Z",
+ "LastHeartbeat": null,
+ "LastHeartbeatRecv": null,
+ "PingMs": null,
+ "Uptime": 192588
+ },
+ {
+ "Name": "mongodb-secondary:27017",
+ "Self": null,
+ "State": 2,
+ "Health": 1,
+ "OptimeDate": "2022-12-30T22:19:25Z",
+ "LastHeartbeat": "2022-12-30T22:19:28.214Z",
+ "LastHeartbeatRecv": "2022-12-30T22:19:28.213Z",
+ "PingMs": 0,
+ "Uptime": 192370
+ }
+ ]
+}