diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index c5bef22fcb4..d2c75ff3568 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -63,9 +63,9 @@ https://github.com/elastic/beats/compare/v6.4.0...master[Check the HEAD diff] *Metricbeat* - Add metrics about cache size to memcached module {pull}7740[7740] +- Add `metircs` metricset to MongoDB module. {pull}7611[7611] - Add fields for mermory fragmentation, memory allocator stats, copy on write, master-slave status, and active defragmentation to `info` metricset of Redis module. {pull}7695[7695] - *Packetbeat* *Winlogbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 12e23bfb714..ef246c6dccc 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -10077,6 +10077,1117 @@ type: long format: bytes +-- + +[float] +== metrics fields + +Statistics that reflect the current use and state of a running `mongod` instance for more information, take a look at https://docs.mongodb.com/manual/reference/command/serverStatus/#serverstatus.metrics + + + +[float] +== commands fields + +Reports on the use of database commands. The fields in metrics.commands are the names of database commands and each value is a document that reports the total number of commands executed as well as the number of failed executions. +metrics.commands..failed shows the number of times failed on this mongod. metrics.commands..total shows the number of times executed on this mongod. + + + + +*`mongodb.metrics.commands.is_self.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.is_self.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.aggregate.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.aggregate.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.build_info.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.build_info.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.coll_stats.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.coll_stats.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.connection_pool_stats.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.connection_pool_stats.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.count.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.count.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.db_stats.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.db_stats.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.distinct.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.distinct.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.find.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.find.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.get_cmd_line_opts.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.get_cmd_line_opts.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.get_last_error.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.get_last_error.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.get_log.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.get_log.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.get_more.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.get_more.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.get_parameter.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.get_parameter.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.host_info.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.host_info.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.insert.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.insert.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.is_master.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.is_master.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.last_collections.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.last_collections.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.last_commands.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.last_commands.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.list_databased.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.list_databased.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.list_indexes.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.list_indexes.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.ping.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.ping.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.profile.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.profile.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.replset_get_rbid.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.replset_get_rbid.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.replset_get_status.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.replset_get_status.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.replset_heartbeat.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.replset_heartbeat.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.replset_update_position.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.replset_update_position.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.server_status.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.server_status.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.update.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.update.total`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.commands.whatsmyuri.failed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.commands.whatsmyuri.total`*:: ++ +-- +type: long + +-- + +[float] +== cursor fields + +Contains data regarding cursor state and use. + + + +*`mongodb.metrics.cursor.timed_out`*:: ++ +-- +type: long + +The total number of cursors that have timed out since the server process started. + + +-- + +[float] +== open fields + +Contains data regarding open cursors. + + + +*`mongodb.metrics.cursor.open.no_timeout`*:: ++ +-- +type: long + +The number of open cursors with the option DBQuery.Option.noTimeout set to prevent timeout. + + +-- + +*`mongodb.metrics.cursor.open.pinned`*:: ++ +-- +type: long + +The number of `pinned` open cursors. + + +-- + +*`mongodb.metrics.cursor.open.total`*:: ++ +-- +type: long + +The number of cursors that MongoDB is maintaining for clients. + + +-- + +[float] +== document fields + +Reflects document access and modification patterns. + + + +*`mongodb.metrics.document.deleted`*:: ++ +-- +type: long + +The total number of documents deleted. + + +-- + +*`mongodb.metrics.document.inserted`*:: ++ +-- +type: long + +The total number of documents inserted. + + +-- + +*`mongodb.metrics.document.returned`*:: ++ +-- +type: long + +The total number of documents returned by queries. + + +-- + +*`mongodb.metrics.document.updated`*:: ++ +-- +type: long + +The total number of documents updated. + + +-- + +[float] +== get_last_error fields + +Returns the error status of the preceding write operation on the current connection. + + + +*`mongodb.metrics.get_last_error.write_wait.ms`*:: ++ +-- +type: long + +The total amount of time in milliseconds that the mongod has spent performing getLastError operations with write concern (i.e. w) greater than 1. + + +-- + +*`mongodb.metrics.get_last_error.write_wait.count`*:: ++ +-- +type: long + +The total number of getLastError operations with a specified write concern (i.e. w) greater than 1. + + +-- + +*`mongodb.metrics.get_last_error.write_timeouts`*:: ++ +-- +type: long + +The number of times that write concern operations have timed out as a result of the wtimeout threshold to getLastError. + + +-- + +[float] +== operation fields + +Holds counters for several types of update and query operations that MongoDB handles using special operation types. + + + +*`mongodb.metrics.operation.scan_and_order`*:: ++ +-- +type: long + +The total number of queries that return sorted numbers that cannot perform the sort operation using an index. + + +-- + +*`mongodb.metrics.operation.write_conflicts`*:: ++ +-- +type: long + +The total number of queries that encountered write conflicts. + + +-- + +[float] +== query_executor fields + +Reports data from the query execution system. + + + +*`mongodb.metrics.query_executor.scanned_indexes`*:: ++ +-- +type: long + +The total number of index items scanned during queries and query-plan evaluation. + + +-- + +*`mongodb.metrics.query_executor.scanned_documents`*:: ++ +-- +type: long + +The total number of documents scanned during queries and query-plan evaluation. + + +-- + +[float] +== replication fields + +Reports metrics related to the replication process. metrics.replication appears on all mongod instances, even those that aren't members of replica sets. + + + +[float] +== executor fields + +Reports on various statistics for the replication executor. + + + + +*`mongodb.metrics.replication.executor.counters.event_created`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.event_wait`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.cancels`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.waits`*:: ++ +-- +type: long + +-- + + +*`mongodb.metrics.replication.executor.counters.scheduled.netcmd`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.scheduled.dbwork`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.scheduled.exclusive`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.scheduled.work_at`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.scheduled.work`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.counters.scheduled.failures`*:: ++ +-- +type: long + +-- + + + +*`mongodb.metrics.replication.executor.queues.in_progress.network`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.queues.in_progress.dbwork`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.queues.in_progress.exclusive`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.queues.sleepers`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.queues.ready`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.queues.free`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.unsignaled_events`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.event_waiters`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.executor.shutting_down`*:: ++ +-- +type: boolean + +-- + +*`mongodb.metrics.replication.executor.network_interface`*:: ++ +-- +type: text + +-- + +[float] +== apply fields + +Reports on the application of operations from the replication oplog. + + + +*`mongodb.metrics.replication.apply.attempts_to_become_secondary`*:: ++ +-- +type: long + +-- + +[float] +== batches fields + +Reports on the oplog application process on secondaries members of replica sets. + + + +*`mongodb.metrics.replication.apply.batches.count`*:: ++ +-- +type: long + +The total number of batches applied across all databases. + + +-- + +*`mongodb.metrics.replication.apply.batches.time.ms`*:: ++ +-- +type: long + +The total amount of time in milliseconds the mongod has spent applying operations from the oplog. + + +-- + +*`mongodb.metrics.replication.apply.ops`*:: ++ +-- +type: long + +The total number of oplog operations applied. + + +-- + +[float] +== buffer fields + +MongoDB buffers oplog operations from the replication sync source buffer before applying oplog entries in a batch. metrics.replication.buffer provides a way to track the oplog buffer. + + + +*`mongodb.metrics.replication.buffer.count`*:: ++ +-- +type: long + +The current number of operations in the oplog buffer. + + +-- + +*`mongodb.metrics.replication.buffer.max_size.bytes`*:: ++ +-- +type: long + +The maximum size of the buffer. This value is a constant setting in the mongod, and is not configurable. + + +-- + +*`mongodb.metrics.replication.buffer.size.bytes`*:: ++ +-- +type: long + +The current size of the contents of the oplog buffer. + + +-- + +[float] +== initial_sync fields + +Report initial sync status + + + +*`mongodb.metrics.replication.initial_sync.completed`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.initial_sync.failed_attempts`*:: ++ +-- +type: long + +-- + +*`mongodb.metrics.replication.initial_sync.failures`*:: ++ +-- +type: long + +-- + +[float] +== network fields + +Reports network use by the replication process. + + + +*`mongodb.metrics.replication.network.bytes`*:: ++ +-- +type: long + +The total amount of data read from the replication sync source. + + +-- + +[float] +== getmores fields + +Reports on the getmore operations, which are requests for additional results from the oplog cursor as part of the oplog replication process. + + + +*`mongodb.metrics.replication.network.getmores.count`*:: ++ +-- +type: long + +The total number of getmore operations + + +-- + +*`mongodb.metrics.replication.network.getmores.time.ms`*:: ++ +-- +type: long + +The total amount of time required to collect data from getmore operations. + + +-- + +*`mongodb.metrics.replication.network.ops`*:: ++ +-- +type: long + +The total number of operations read from the replication source. + + +-- + +*`mongodb.metrics.replication.network.reders_created`*:: ++ +-- +type: long + +The total number of oplog query processes created. + + +-- + +[float] +== preload fields + +Reports on the `pre-fetch` stage, where MongoDB loads documents and indexes into RAM to improve replication throughput. + + + +[float] +== docs fields + +Reports on the documents loaded into memory during the pre-fetch stage. + + + +*`mongodb.metrics.replication.preload.docs.count`*:: ++ +-- +type: long + +The total number of documents loaded during the pre-fetch stage of replication. + + +-- + +*`mongodb.metrics.replication.preload.docs.time.ms`*:: ++ +-- +type: long + +-- + +[float] +== indexes fields + +Reports on the index items loaded into memory during the pre-fetch stage of replication. + + + +*`mongodb.metrics.replication.preload.indexes.count`*:: ++ +-- +type: long + +The total number of index entries loaded by members before updating documents as part of the pre-fetch stage of replication. + + +-- + +*`mongodb.metrics.replication.preload.indexes.time.ms`*:: ++ +-- +type: long + +The total amount of time, in milliseconds, spent loading index entries as part of the pre-fetch stage of replication. + + +-- + + +*`mongodb.metrics.storage.free_list.search.bucket_exhausted`*:: ++ +-- +type: long + +The number of times that mongod has checked the free list without finding a suitably large record allocation. + + +-- + +*`mongodb.metrics.storage.free_list.search.requests`*:: ++ +-- +type: long + +The number of times mongod has searched for available record allocations. + + +-- + +*`mongodb.metrics.storage.free_list.search.scanned`*:: ++ +-- +type: long + +The number of available record allocations mongod has searched. + + +-- + +[float] +== ttl fields + +Reports on the operation of the resource use of the ttl index process. + + + +*`mongodb.metrics.ttl.deleted_documents`*:: ++ +-- +type: long + +The total number of documents deleted from collections with a ttl index. + + +-- + +*`mongodb.metrics.ttl.passes`*:: ++ +-- +type: long + +The number of times the background process removes documents from collections with a ttl index. + + -- [float] diff --git a/metricbeat/docs/modules/mongodb.asciidoc b/metricbeat/docs/modules/mongodb.asciidoc index 0b9129ee2ee..7ed549a7f38 100644 --- a/metricbeat/docs/modules/mongodb.asciidoc +++ b/metricbeat/docs/modules/mongodb.asciidoc @@ -66,7 +66,7 @@ in <>. Here is an example configuration: ---- metricbeat.modules: - module: mongodb - metricsets: ["dbstats", "status"] + metricsets: ["dbstats", "status", "collstats", "metrics"] period: 10s enabled: true @@ -110,11 +110,15 @@ The following metricsets are available: * <> +* <> + * <> include::mongodb/collstats.asciidoc[] include::mongodb/dbstats.asciidoc[] +include::mongodb/metrics.asciidoc[] + include::mongodb/status.asciidoc[] diff --git a/metricbeat/docs/modules/mongodb/metrics.asciidoc b/metricbeat/docs/modules/mongodb/metrics.asciidoc new file mode 100644 index 00000000000..764dce91409 --- /dev/null +++ b/metricbeat/docs/modules/mongodb/metrics.asciidoc @@ -0,0 +1,23 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-mongodb-metrics]] +=== MongoDB metrics metricset + +experimental[] + +include::../../../module/mongodb/metrics/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/mongodb/metrics/_meta/data.json[] +---- diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index dcc11eed248..97c939dff8c 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -89,8 +89,9 @@ This file is generated! See scripts/docs_collector.py |<> beta[] |image:./images/icon-no.png[No prebuilt dashboards] | .1+| .1+| |<> beta[] |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | -.3+| .3+| |<> +.4+| .4+| |<> |<> +|<> experimental[] |<> |<> beta[] |image:./images/icon-no.png[No prebuilt dashboards] | .1+| .1+| |<> beta[] diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index 4ce91bdc716..95773e728e5 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -113,6 +113,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/mongodb" _ "github.com/elastic/beats/metricbeat/module/mongodb/collstats" _ "github.com/elastic/beats/metricbeat/module/mongodb/dbstats" + _ "github.com/elastic/beats/metricbeat/module/mongodb/metrics" _ "github.com/elastic/beats/metricbeat/module/mongodb/status" _ "github.com/elastic/beats/metricbeat/module/munin" _ "github.com/elastic/beats/metricbeat/module/munin/node" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index c2661613cc8..825c00e916e 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -444,7 +444,7 @@ metricbeat.modules: #------------------------------- MongoDB Module ------------------------------ - module: mongodb - metricsets: ["dbstats", "status"] + metricsets: ["dbstats", "status", "collstats", "metrics"] period: 10s enabled: true diff --git a/metricbeat/module/mongodb/_meta/config.reference.yml b/metricbeat/module/mongodb/_meta/config.reference.yml index d99d2938b94..2aa1e6322e3 100644 --- a/metricbeat/module/mongodb/_meta/config.reference.yml +++ b/metricbeat/module/mongodb/_meta/config.reference.yml @@ -1,5 +1,5 @@ - module: mongodb - metricsets: ["dbstats", "status"] + metricsets: ["dbstats", "status", "collstats", "metrics"] period: 10s enabled: true diff --git a/metricbeat/module/mongodb/_meta/config.yml b/metricbeat/module/mongodb/_meta/config.yml index e92b3d5f513..5f9c0aac612 100644 --- a/metricbeat/module/mongodb/_meta/config.yml +++ b/metricbeat/module/mongodb/_meta/config.yml @@ -2,6 +2,8 @@ #metricsets: # - dbstats # - status + # - collstats + # - metrics period: 10s # The hosts must be passed as MongoDB URLs in the format: diff --git a/metricbeat/module/mongodb/fields.go b/metricbeat/module/mongodb/fields.go index 92740eaf662..d51ee0dc225 100644 --- a/metricbeat/module/mongodb/fields.go +++ b/metricbeat/module/mongodb/fields.go @@ -31,5 +31,5 @@ func init() { // Asset returns asset data func Asset() string { - return "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" + return "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" } diff --git a/metricbeat/module/mongodb/metrics/_meta/data.json b/metricbeat/module/mongodb/metrics/_meta/data.json new file mode 100644 index 00000000000..949f90492c8 --- /dev/null +++ b/metricbeat/module/mongodb/metrics/_meta/data.json @@ -0,0 +1,252 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"mongodb", + "name":"metrics", + "rtt":44269 + }, + "mongodb":{ + "metrics": { + "get_last_error": { + "write_wait": { + "ms": 0, + "count": 0 + }, + "write_timeouts": 0 + }, + "cursor": { + "open": { + "no_timeout": 0, + "pinned": 0, + "total": 1 + }, + "timed_out": 137 + }, + "replication": { + "apply": { + "batches": { + "count": 66871, + "time": { + "ms": 9981 + } + }, + "ops": 28536, + "attempts_to_become_secondary": 1 + }, + "buffer": { + "count": 0, + "max_size": { + "bytes": 268435456 + }, + "size": {} + }, + "initial_sync": { + "failures": 0, + "completed": 0, + "failed_attempts": 0 + }, + "network": { + "bytes": 17002617, + "getmores": { + "count": 183078, + "time": { + "ms": 515206213 + } + }, + "ops": 78266, + "reders_created": 1 + }, + "preload": { + "docs": { + "count": 0, + "time": { + "ms": 0 + } + }, + "indexes": { + "count": 0, + "time": { + "ms": 0 + } + } + }, + "executor": { + "counters": { + "event_created": 2, + "event_wait": 2, + "cancels": 440622, + "waits": 0, + "scheduled": { + "dbwork": 1, + "exclusive": 0, + "work_at": 1032681, + "work": 0, + "failures": 0, + "netcmd": 515015 + } + }, + "queues": { + "in_progress": { + "network": 0, + "dbwork": 0, + "exclusive": 0 + }, + "sleepers": 4, + "ready": 0, + "free": 5 + }, + "unsignaled_events": 4, + "event_waiters": 0, + "shutting_down": false, + "network_interface": "\nNetworkInterfaceASIO Operations' Diagnostic:\nOperation: Count: \nConnecting 0 \nIn Progress 0 \nSucceeded 515014 \nCanceled 0 \nFailed 1 \nTimed Out 1 \n\n" + } + }, + "operation": { + "scan_and_order": 0, + "write_conflicts": 0 + }, + "ttl": { + "passes": { + "count": 8590 + }, + "deleted_documents": { + "count": 0 + } + }, + "commands": { + "db_stats": { + "total": 3440, + "failed": 0 + }, + "last_collections": { + "failed": 0, + "total": 146 + }, + "aggregate": { + "failed": 0, + "total": 0 + }, + "server_status": { + "total": 123122, + "failed": 0 + }, + "get_last_error": { + "failed": 0, + "total": 15 + }, + "list_indexes": { + "failed": 0, + "total": 216 + }, + "connection_pool_stats": { + "total": 9372, + "failed": 0 + }, + "update": { + "total": 0, + "failed": 0 + }, + "is_self": { + "total": 9372, + "failed": 0 + }, + "insert": { + "total": 0, + "failed": 0 + }, + "replset_get_rbid": { + "failed": 0, + "total": 0 + }, + "get_parameter": { + "failed": 0, + "total": 9372 + }, + "count": { + "failed": 0, + "total": 432 + }, + "replset_update_position": { + "failed": 0, + "total": 0 + }, + "host_info": { + "failed": 0, + "total": 9372 + }, + "replset_heartbeat": { + "total": 360615, + "failed": 0 + }, + "profile": { + "failed": 0, + "total": 0 + }, + "coll_stats": { + "failed": 0, + "total": 112526 + }, + "whatsmyuri": { + "total": 7, + "failed": 0 + }, + "replset_get_status": { + "failed": 0, + "total": 121833 + }, + "ping": { + "failed": 0, + "total": 160781 + }, + "build_info": { + "failed": 0, + "total": 112751 + }, + "find": { + "failed": 0, + "total": 9726 + }, + "get_cmd_line_opts": { + "failed": 0, + "total": 9372 + }, + "list_databased": { + "total": 2612, + "failed": 0 + }, + "get_log": { + "failed": 0, + "total": 9372 + }, + "get_more": { + "failed": 0, + "total": 28359 + }, + "distinct": { + "total": 0, + "failed": 0 + }, + "last_commands": { + "failed": 0, + "total": 0 + }, + "is_master": { + "total": 295988, + "failed": 0 + } + }, + "document": { + "deleted": 0, + "inserted": 0, + "returned": 1615596512, + "updated": 0 + } + } + }, + "type":"metricsets" +} diff --git a/metricbeat/module/mongodb/metrics/_meta/docs.asciidoc b/metricbeat/module/mongodb/metrics/_meta/docs.asciidoc new file mode 100644 index 00000000000..d99f260fff5 --- /dev/null +++ b/metricbeat/module/mongodb/metrics/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the `metrics` metricset of the MongoDB module. \ No newline at end of file diff --git a/metricbeat/module/mongodb/metrics/_meta/fields.yml b/metricbeat/module/mongodb/metrics/_meta/fields.yml new file mode 100644 index 00000000000..952357b33c6 --- /dev/null +++ b/metricbeat/module/mongodb/metrics/_meta/fields.yml @@ -0,0 +1,531 @@ +- name: metrics + type: group + description: > + Statistics that reflect the current use and state of a running `mongod` instance + for more information, take a look at https://docs.mongodb.com/manual/reference/command/serverStatus/#serverstatus.metrics + fields: + - name: commands + type: group + description: > + Reports on the use of database commands. + The fields in metrics.commands are the names of database commands and each value is a document + that reports the total number of commands executed as well as the number of failed executions. + + metrics.commands..failed shows the number of times failed on this mongod. + metrics.commands..total shows the number of times executed on this mongod. + fields: + - name: is_self + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: aggregate + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: build_info + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: coll_stats + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: connection_pool_stats + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: count + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: db_stats + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: distinct + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: find + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: get_cmd_line_opts + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: get_last_error + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: get_log + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: get_more + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: get_parameter + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: host_info + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: insert + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: is_master + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: last_collections + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: last_commands + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: list_databased + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: list_indexes + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: ping + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: profile + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: replset_get_rbid + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: replset_get_status + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: replset_heartbeat + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: replset_update_position + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: server_status + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: update + type: group + fields: + - name: failed + type: long + - name: total + type: long + - name: whatsmyuri + type: group + fields: + - name: failed + type: long + - name: total + type: long + + - name: cursor + type: group + description: > + Contains data regarding cursor state and use. + fields: + - name: timed_out + type: long + description: > + The total number of cursors that have timed out since the server process started. + - name: open + type: group + description: > + Contains data regarding open cursors. + fields: + - name: no_timeout + type: long + description: > + The number of open cursors with the option DBQuery.Option.noTimeout set to prevent timeout. + - name: pinned + type: long + description: > + The number of `pinned` open cursors. + - name: total + type: long + description: > + The number of cursors that MongoDB is maintaining for clients. + + - name: document + type: group + description: > + Reflects document access and modification patterns. + fields: + - name: deleted + type: long + description: > + The total number of documents deleted. + - name: inserted + type: long + description: > + The total number of documents inserted. + - name: returned + type: long + description: > + The total number of documents returned by queries. + - name: updated + type: long + description: > + The total number of documents updated. + + - name: get_last_error + type: group + description: > + Returns the error status of the preceding write operation on the current connection. + fields: + - name: write_wait.ms + type: long + description: > + The total amount of time in milliseconds that the mongod has spent performing getLastError operations + with write concern (i.e. w) greater than 1. + - name: write_wait.count + type: long + description: > + The total number of getLastError operations with a specified write concern (i.e. w) greater than 1. + - name: write_timeouts + type: long + description: > + The number of times that write concern operations have timed out as a result of the wtimeout threshold to getLastError. + + - name: operation + type: group + description: > + Holds counters for several types of update and query operations that MongoDB handles using special operation types. + fields: + - name: scan_and_order + type: long + description: > + The total number of queries that return sorted numbers that cannot perform the sort operation using an index. + - name: write_conflicts + type: long + description: > + The total number of queries that encountered write conflicts. + + - name: query_executor + type: group + description: > + Reports data from the query execution system. + fields: + - name: scanned_indexes + type: long + description: > + The total number of index items scanned during queries and query-plan evaluation. + - name: scanned_documents + type: long + description: > + The total number of documents scanned during queries and query-plan evaluation. + + - name: replication + type: group + description: > + Reports metrics related to the replication process. + metrics.replication appears on all mongod instances, even those that aren't members of replica sets. + fields: + - name: executor + type: group + description: > + Reports on various statistics for the replication executor. + fields: + - name: counters + type: group + fields: + - name: event_created + type: long + - name: event_wait + type: long + - name: cancels + type: long + - name: waits + type: long + - name: scheduled + type: group + fields: + - name: netcmd + type: long + - name: dbwork + type: long + - name: exclusive + type: long + - name: work_at + type: long + - name: work + type: long + - name: failures + type: long + - name: queues + type: group + fields: + - name: in_progress + type: group + fields: + - name: network + type: long + - name: dbwork + type: long + - name: exclusive + type: long + - name: sleepers + type: long + - name: ready + type: long + - name: free + type: long + - name: unsignaled_events + type: long + - name: event_waiters + type: long + - name: shutting_down + type: boolean + - name: network_interface + type: text + - name: apply + type: group + description: > + Reports on the application of operations from the replication oplog. + fields: + - name: attempts_to_become_secondary + type: long + - name: batches + type: group + description: > + Reports on the oplog application process on secondaries members of replica sets. + fields: + - name: count + type: long + description: > + The total number of batches applied across all databases. + - name: time.ms + type: long + description: > + The total amount of time in milliseconds the mongod has spent applying operations from the oplog. + - name: ops + type: long + description: > + The total number of oplog operations applied. + - name: buffer + type: group + description: > + MongoDB buffers oplog operations from the replication sync source buffer before applying oplog entries in a batch. + metrics.replication.buffer provides a way to track the oplog buffer. + fields: + - name: count + type: long + description: > + The current number of operations in the oplog buffer. + - name: max_size.bytes + type: long + description: > + The maximum size of the buffer. This value is a constant setting in the mongod, and is not configurable. + - name: size.bytes + type: long + description: > + The current size of the contents of the oplog buffer. + - name: initial_sync + type: group + description: > + Report initial sync status + fields: + - name: completed + type: long + - name: failed_attempts + type: long + - name: failures + type: long + - name: network + type: group + description: > + Reports network use by the replication process. + fields: + - name: bytes + type: long + description: > + The total amount of data read from the replication sync source. + - name: getmores + type: group + description: > + Reports on the getmore operations, which are requests for additional results from the oplog cursor + as part of the oplog replication process. + fields: + - name: count + type: long + description: > + The total number of getmore operations + - name: time.ms + type: long + description: > + The total amount of time required to collect data from getmore operations. + - name: ops + type: long + description: > + The total number of operations read from the replication source. + - name: reders_created + type: long + description: > + The total number of oplog query processes created. + - name: preload + type: group + description: > + Reports on the `pre-fetch` stage, where MongoDB loads documents and indexes into RAM to improve replication throughput. + fields: + - name: docs + type: group + description: > + Reports on the documents loaded into memory during the pre-fetch stage. + fields: + - name: count + type: long + description: > + The total number of documents loaded during the pre-fetch stage of replication. + - name: time.ms + type: long + decsription: > + The total amount of time spent loading documents as part of the pre-fetch stage of replication. + - name: indexes + type: group + description: > + Reports on the index items loaded into memory during the pre-fetch stage of replication. + fields: + - name: count + type: long + description: > + The total number of index entries loaded by members before updating documents as part of the pre-fetch stage of replication. + - name: time.ms + type: long + description: > + The total amount of time, in milliseconds, spent loading index entries as part of the pre-fetch stage of replication. + + - name: storage.free_list.search + type: group + fields: + - name: bucket_exhausted + type: long + description: > + The number of times that mongod has checked the free list without finding a suitably large record allocation. + - name: requests + type: long + description: > + The number of times mongod has searched for available record allocations. + - name: scanned + type: long + description: > + The number of available record allocations mongod has searched. + + - name: ttl + type: group + description: > + Reports on the operation of the resource use of the ttl index process. + fields: + - name: deleted_documents + type: long + description: > + The total number of documents deleted from collections with a ttl index. + - name: passes + type: long + description: > + The number of times the background process removes documents from collections with a ttl index. diff --git a/metricbeat/module/mongodb/metrics/data.go b/metricbeat/module/mongodb/metrics/data.go new file mode 100644 index 00000000000..8ec730daeb6 --- /dev/null +++ b/metricbeat/module/mongodb/metrics/data.go @@ -0,0 +1,167 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package metrics + +import ( + s "github.com/elastic/beats/libbeat/common/schema" + c "github.com/elastic/beats/libbeat/common/schema/mapstriface" +) + +var schema = s.Schema{ + "commands": c.Dict("metrics.commands", s.Schema{ + "is_self": c.Dict("_isSelf", commandSchema), + "aggregate": c.Dict("aggregate", commandSchema), + "build_info": c.Dict("buildInfo", commandSchema), + "coll_stats": c.Dict("collStats", commandSchema), + "connection_pool_stats": c.Dict("connPoolStats", commandSchema), + "count": c.Dict("count", commandSchema), + "db_stats": c.Dict("dbStats", commandSchema), + "distinct": c.Dict("distinct", commandSchema), + "find": c.Dict("find", commandSchema), + "get_cmd_line_opts": c.Dict("getCmdLineOpts", commandSchema), + "get_last_error": c.Dict("getLastError", commandSchema), + "get_log": c.Dict("getLog", commandSchema), + "get_more": c.Dict("getMore", commandSchema), + "get_parameter": c.Dict("getParameter", commandSchema), + "host_info": c.Dict("hostInfo", commandSchema), + "insert": c.Dict("insert", commandSchema), + "is_master": c.Dict("isMaster", commandSchema), + "last_collections": c.Dict("listCollections", commandSchema), + "last_commands": c.Dict("listCommands", commandSchema), + "list_databased": c.Dict("listDatabases", commandSchema), + "list_indexes": c.Dict("listIndexes", commandSchema), + "ping": c.Dict("ping", commandSchema), + "profile": c.Dict("profile", commandSchema), + "replset_get_rbid": c.Dict("replSetGetRBID", commandSchema), + "replset_get_status": c.Dict("replSetGetStatus", commandSchema), + "replset_heartbeat": c.Dict("replSetHeartbeat", commandSchema), + "replset_update_position": c.Dict("replSetUpdatePosition", commandSchema), + "server_status": c.Dict("serverStatus", commandSchema), + "update": c.Dict("update", commandSchema), + "whatsmyuri": c.Dict("whatsmyuri", commandSchema), + }), + "cursor": c.Dict("metrics.cursor", s.Schema{ + "timed_out": c.Int("timedOut"), + "open": c.Dict("open", s.Schema{ + "no_timeout": c.Int("noTimeout"), + "pinned": c.Int("pinned"), + "total": c.Int("total"), + }), + }), + "document": c.Dict("metrics.document", s.Schema{ + "deleted": c.Int("deleted"), + "inserted": c.Int("inserted"), + "returned": c.Int("returned"), + "updated": c.Int("updated"), + }), + "get_last_error": c.Dict("metrics.getLastError", s.Schema{ + "write_wait": c.Dict("wtime", s.Schema{ + "ms": c.Int("totalMillis"), + "count": c.Int("num"), + }), + "write_timeouts": c.Int("wtimeouts"), + }), + "operation": c.Dict("metrics.operation", s.Schema{ + "scan_and_order": c.Int("scanAndOrder"), + "write_conflicts": c.Int("writeConflicts"), + }), + "query_executor": c.Dict("metrics.queryExecutor", s.Schema{ + "scanned_indexes": s.Object{"count": c.Int("scanned")}, + "scanned_documents": s.Object{"count": c.Int("scannedObjects")}, + }), + "replication": c.Dict("metrics.repl", replicationSchema, c.DictOptional), + "storage": c.Dict("metrics.storage.freelist", s.Schema{ + "search": c.Dict("search", s.Schema{ + "bucket_exhausted": c.Int("bucketExhausted"), + "requests": c.Int("requests"), + "scanned": c.Int("scanned"), + }), + }), + "ttl": c.Dict("metrics.ttl", s.Schema{ + "deleted_documents": s.Object{"count": c.Int("deletedDocuments")}, + "passes": s.Object{"count": c.Int("passes")}, + }), +} + +var commandSchema = s.Schema{ + "failed": c.Int("failed"), + "total": c.Int("total"), +} + +var replicationSchema = s.Schema{ + "executor": c.Dict("executor", s.Schema{ + "counters": c.Dict("counters", s.Schema{ + "event_created": c.Int("eventCreated"), + "event_wait": c.Int("eventWait"), + "cancels": c.Int("cancels"), + "waits": c.Int("waits"), + "scheduled": s.Object{ + "netcmd": c.Int("scheduledNetCmd"), + "dbwork": c.Int("scheduledDBWork"), + "exclusive": c.Int("scheduledXclWork"), + "work_at": c.Int("scheduledWorkAt"), + "work": c.Int("scheduledWork"), + "failures": c.Int("schedulingFailures"), + }, + }), + "queues": c.Dict("queues", s.Schema{ + "in_progress": s.Object{ + "network": c.Int("networkInProgress"), + "dbwork": c.Int("dbWorkInProgress"), + "exclusive": c.Int("exclusiveInProgress"), + }, + "sleepers": c.Int("sleepers"), + "ready": c.Int("ready"), + "free": c.Int("free"), + }), + "unsignaled_events": c.Int("unsignaledEvents"), + "event_waiters": c.Int("eventWaiters"), + "shutting_down": c.Bool("shuttingDown"), + "network_interface": c.Str("networkInterface"), + }), + "apply": c.Dict("apply", s.Schema{ + "attempts_to_become_secondary": c.Int("attemptsToBecomeSecondary"), + "batches": c.Dict("batches", countAndTimeSchema), + "ops": c.Int("ops"), + }), + "buffer": c.Dict("buffer", s.Schema{ + "count": c.Int("count"), + "max_size": s.Object{"bytes": c.Int("maxSizeBytes")}, + "size": s.Object{"bytes": c.Int("sizeBytes")}, + }), + "initial_sync": c.Dict("initialSync", s.Schema{ + "completed": c.Int("completed"), + "failed_attempts": c.Int("failedAttempts"), + "failures": c.Int("failures"), + }), + "network": c.Dict("network", s.Schema{ + "bytes": c.Int("bytes"), + "getmores": c.Dict("getmores", countAndTimeSchema), + "ops": c.Int("ops"), + "reders_created": c.Int("readersCreated"), + }), + "preload": c.Dict("preload", s.Schema{ + "docs": c.Dict("docs", countAndTimeSchema), + "indexes": c.Dict("indexes", countAndTimeSchema), + }), +} + +var countAndTimeSchema = s.Schema{ + "count": c.Int("num"), + "time": s.Object{"ms": c.Int("totalMillis")}, +} diff --git a/metricbeat/module/mongodb/metrics/metrics.go b/metricbeat/module/mongodb/metrics/metrics.go new file mode 100644 index 00000000000..ac6bb54bf6c --- /dev/null +++ b/metricbeat/module/mongodb/metrics/metrics.go @@ -0,0 +1,81 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package metrics + +import ( + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/cfgwarn" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/mb" + "github.com/elastic/beats/metricbeat/module/mongodb" + + "gopkg.in/mgo.v2/bson" +) + +var debugf = logp.MakeDebug("mongodb.metrics") + +func init() { + mb.Registry.MustAddMetricSet("mongodb", "metrics", New, + mb.WithHostParser(mongodb.ParseURL), + mb.DefaultMetricSet(), + ) +} + +// MetricSet type defines all fields of the MetricSet +// As a minimum it must inherit the mb.BaseMetricSet fields, but can be extended with +// additional entries. These variables can be used to persist data or configuration between +// multiple fetch calls. +type MetricSet struct { + *mongodb.MetricSet +} + +// New creates a new instance of the MetricSet +// Part of new is also setting up the configuration by processing additional +// configuration entries if needed. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Experimental("The mongodb metrics metricset is experimental.") + ms, err := mongodb.NewMetricSet(base) + if err != nil { + return nil, err + } + return &MetricSet{ms}, nil +} + +// Fetch methods implements the data gathering and data conversion to the right format +// It returns the event which is then forward to the output. In case of an error, a +// descriptive error must be returned. +func (m *MetricSet) Fetch() (common.MapStr, error) { + + // instantiate direct connections to each of the configured Mongo hosts + mongoSession, err := mongodb.NewDirectSession(m.DialInfo) + if err != nil { + return nil, err + } + defer mongoSession.Close() + + result := map[string]interface{}{} + if err := mongoSession.DB("admin").Run(bson.D{{Name: "serverStatus", Value: 1}}, &result); err != nil { + return nil, err + } + + data, err := schema.Apply(result) + if err != nil { + return nil, err + } + return data, nil +} diff --git a/metricbeat/module/mongodb/metrics/metrics_intergration_test.go b/metricbeat/module/mongodb/metrics/metrics_intergration_test.go new file mode 100644 index 00000000000..1347cd02874 --- /dev/null +++ b/metricbeat/module/mongodb/metrics/metrics_intergration_test.go @@ -0,0 +1,67 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build integration + +package metrics + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/tests/compose" + mbtest "github.com/elastic/beats/metricbeat/mb/testing" + "github.com/elastic/beats/metricbeat/module/mongodb" +) + +func TestFetch(t *testing.T) { + compose.EnsureUp(t, "mongodb") + + f := mbtest.NewEventFetcher(t, getConfig()) + event, err := f.Fetch() + if !assert.NoError(t, err) { + t.FailNow() + } + + // Check a few event Fields + findCount, err := event.GetValue("commands.find.total") + assert.NoError(t, err) + assert.True(t, findCount.(int64) >= 0) + + deletedDocuments, err := event.GetValue("document.deleted") + assert.NoError(t, err) + assert.True(t, deletedDocuments.(int64) >= 0) +} + +func TestData(t *testing.T) { + compose.EnsureUp(t, "mongodb") + + f := mbtest.NewEventFetcher(t, getConfig()) + err := mbtest.WriteEvent(f, t) + if err != nil { + t.Fatal("write", err) + } +} + +func getConfig() map[string]interface{} { + return map[string]interface{}{ + "module": "mongodb", + "metricsets": []string{"metrics"}, + "hosts": []string{mongodb.GetEnvHost() + ":" + mongodb.GetEnvPort()}, + } +} diff --git a/metricbeat/modules.d/mongodb.yml.disabled b/metricbeat/modules.d/mongodb.yml.disabled index 36b4669095c..2b75555984b 100644 --- a/metricbeat/modules.d/mongodb.yml.disabled +++ b/metricbeat/modules.d/mongodb.yml.disabled @@ -5,6 +5,8 @@ #metricsets: # - dbstats # - status + # - collstats + # - metrics period: 10s # The hosts must be passed as MongoDB URLs in the format: