| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | package mongo |
| 4 | |
| 5 | import ( |
| 6 | "context" |
| 7 | "encoding/json" |
| 8 | "errors" |
| 9 | "os" |
| 10 | "testing" |
| 11 | "time" |
| 12 | |
| 13 | "github.com/netdata/netdata/go/plugins/pkg/matcher" |
| 14 | "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest" |
| 15 | |
| 16 | "github.com/stretchr/testify/assert" |
| 17 | "github.com/stretchr/testify/require" |
| 18 | ) |
| 19 | |
| 20 | var ( |
| 21 | dataConfigJSON, _ = os.ReadFile("testdata/config.json") |
| 22 | dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") |
| 23 | |
| 24 | dataVer6MongodServerStatus, _ = os.ReadFile("testdata/v6.0.3/mongod-serverStatus.json") |
| 25 | dataVer6MongosServerStatus, _ = os.ReadFile("testdata/v6.0.3/mongos-serverStatus.json") |
| 26 | dataVer6DbStats, _ = os.ReadFile("testdata/v6.0.3/dbStats.json") |
| 27 | dataVer6ReplSetGetStatus, _ = os.ReadFile("testdata/v6.0.3/replSetGetStatus.json") |
| 28 | ) |
| 29 | |
| 30 | func Test_testDataIsValid(t *testing.T) { |
| 31 | for name, data := range map[string][]byte{ |
| 32 | "dataConfigJSON": dataConfigJSON, |
| 33 | "dataConfigYAML": dataConfigYAML, |
| 34 | "dataVer6MongodServerStatus": dataVer6MongodServerStatus, |
| 35 | "dataVer6MongosServerStatus": dataVer6MongosServerStatus, |
| 36 | "dataVer6DbStats": dataVer6DbStats, |
| 37 | "dataVer6ReplSetGetStatus": dataVer6ReplSetGetStatus, |
| 38 | } { |
| 39 | require.NotNil(t, data, name) |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | func TestCollector_ConfigurationSerialize(t *testing.T) { |
| 44 | collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML) |
| 45 | } |
| 46 | |
| 47 | func TestCollector_Init(t *testing.T) { |
| 48 | tests := map[string]struct { |
| 49 | config Config |
| 50 | wantFail bool |
| 51 | }{ |
| 52 | "success on default config": { |
| 53 | wantFail: false, |
| 54 | config: New().Config, |
| 55 | }, |
| 56 | "fails on unset 'address'": { |
| 57 | wantFail: true, |
| 58 | config: Config{ |
| 59 | URI: "", |
| 60 | }, |
| 61 | }, |
| 62 | "fails on invalid database selector": { |
| 63 | wantFail: true, |
| 64 | config: Config{ |
| 65 | URI: "mongodb://localhost:27017", |
| 66 | Databases: matcher.SimpleExpr{ |
| 67 | Includes: []string{"!@#"}, |
| 68 | }, |
| 69 | }, |
| 70 | }, |
| 71 | } |
| 72 | |
| 73 | for name, test := range tests { |
| 74 | t.Run(name, func(t *testing.T) { |
| 75 | collr := New() |
| 76 | collr.Config = test.config |
| 77 | |
| 78 | if test.wantFail { |
| 79 | assert.Error(t, collr.Init(context.Background())) |
| 80 | } else { |
| 81 | assert.NoError(t, collr.Init(context.Background())) |
| 82 | } |
| 83 | }) |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | func TestCollector_Charts(t *testing.T) { |
| 88 | assert.NotNil(t, New().Charts()) |
| 89 | } |
| 90 | |
| 91 | func TestCollector_Cleanup(t *testing.T) { |
| 92 | tests := map[string]struct { |
| 93 | prepare func(t *testing.T) *Collector |
| 94 | wantClose bool |
| 95 | }{ |
| 96 | "client not initialized": { |
| 97 | wantClose: false, |
| 98 | prepare: func(t *testing.T) *Collector { |
| 99 | return New() |
| 100 | }, |
| 101 | }, |
| 102 | "client initialized": { |
| 103 | wantClose: true, |
| 104 | prepare: func(t *testing.T) *Collector { |
| 105 | collr := New() |
| 106 | collr.conn = caseMongod() |
| 107 | _ = collr.conn.initClient("", 0) |
| 108 | |
| 109 | return collr |
| 110 | }, |
| 111 | }, |
| 112 | } |
| 113 | |
| 114 | for name, test := range tests { |
| 115 | t.Run(name, func(t *testing.T) { |
| 116 | collr := test.prepare(t) |
| 117 | |
| 118 | require.NotPanics(t, func() { collr.Cleanup(context.Background()) }) |
| 119 | if test.wantClose { |
| 120 | collr, ok := collr.conn.(*mockMongoClient) |
| 121 | require.True(t, ok) |
| 122 | assert.True(t, collr.closeCalled) |
| 123 | } |
| 124 | }) |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | func TestCollector_Check(t *testing.T) { |
| 129 | tests := map[string]struct { |
| 130 | prepare func() *mockMongoClient |
| 131 | wantFail bool |
| 132 | }{ |
| 133 | "success on Mongod (v6)": { |
| 134 | wantFail: false, |
| 135 | prepare: caseMongod, |
| 136 | }, |
| 137 | "success on Mongod Replicas Set(v6)": { |
| 138 | wantFail: false, |
| 139 | prepare: caseMongodReplicaSet, |
| 140 | }, |
| 141 | "success on Mongos (v6)": { |
| 142 | wantFail: false, |
| 143 | prepare: caseMongos, |
| 144 | }, |
| 145 | } |
| 146 | |
| 147 | for name, test := range tests { |
| 148 | t.Run(name, func(t *testing.T) { |
| 149 | collr := prepareMongo() |
| 150 | defer collr.Cleanup(context.Background()) |
| 151 | collr.conn = test.prepare() |
| 152 | |
| 153 | require.NoError(t, collr.Init(context.Background())) |
| 154 | |
| 155 | if test.wantFail { |
| 156 | assert.Error(t, collr.Check(context.Background())) |
| 157 | } else { |
| 158 | assert.NoError(t, collr.Check(context.Background())) |
| 159 | } |
| 160 | }) |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | func TestCollector_Collect(t *testing.T) { |
| 165 | tests := map[string]struct { |
| 166 | prepare func() *mockMongoClient |
| 167 | wantCollected map[string]int64 |
| 168 | }{ |
| 169 | "success on Mongod (v6)": { |
| 170 | prepare: caseMongod, |
| 171 | wantCollected: map[string]int64{ |
| 172 | "asserts_msg": 0, |
| 173 | "asserts_regular": 0, |
| 174 | "asserts_rollovers": 0, |
| 175 | "asserts_tripwire": 0, |
| 176 | "asserts_user": 246, |
| 177 | "asserts_warning": 0, |
| 178 | "connections_active": 7, |
| 179 | "connections_available": 838841, |
| 180 | "connections_awaiting_topology_changes": 5, |
| 181 | "connections_current": 19, |
| 182 | "connections_exhaust_hello": 2, |
| 183 | "connections_exhaust_is_master": 1, |
| 184 | "connections_threaded": 19, |
| 185 | "connections_total_created": 77, |
| 186 | "database_admin_collections": 3, |
| 187 | "database_admin_data_size": 796, |
| 188 | "database_admin_documents": 5, |
| 189 | "database_admin_index_size": 81920, |
| 190 | "database_admin_indexes": 4, |
| 191 | "database_admin_storage_size": 61440, |
| 192 | "database_admin_views": 0, |
| 193 | "database_config_collections": 3, |
| 194 | "database_config_data_size": 796, |
| 195 | "database_config_documents": 5, |
| 196 | "database_config_index_size": 81920, |
| 197 | "database_config_indexes": 4, |
| 198 | "database_config_storage_size": 61440, |
| 199 | "database_config_views": 0, |
| 200 | "database_local_collections": 3, |
| 201 | "database_local_data_size": 796, |
| 202 | "database_local_documents": 5, |
| 203 | "database_local_index_size": 81920, |
| 204 | "database_local_indexes": 4, |
| 205 | "database_local_storage_size": 61440, |
| 206 | "database_local_views": 0, |
| 207 | "extra_info_page_faults": 0, |
| 208 | "global_lock_active_clients_readers": 0, |
| 209 | "global_lock_active_clients_writers": 0, |
| 210 | "global_lock_current_queue_readers": 0, |
| 211 | "global_lock_current_queue_writers": 0, |
| 212 | "locks_collection_acquire_exclusive": 6, |
| 213 | "locks_collection_acquire_intent_exclusive": 172523, |
| 214 | "locks_collection_acquire_intent_shared": 336370, |
| 215 | "locks_collection_acquire_shared": 0, |
| 216 | "locks_database_acquire_exclusive": 3, |
| 217 | "locks_database_acquire_intent_exclusive": 172539, |
| 218 | "locks_database_acquire_intent_shared": 50971, |
| 219 | "locks_database_acquire_shared": 0, |
| 220 | "locks_global_acquire_exclusive": 6, |
| 221 | "locks_global_acquire_intent_exclusive": 174228, |
| 222 | "locks_global_acquire_intent_shared": 437905, |
| 223 | "locks_global_acquire_shared": 0, |
| 224 | "locks_mutex_acquire_exclusive": 0, |
| 225 | "locks_mutex_acquire_intent_exclusive": 0, |
| 226 | "locks_mutex_acquire_intent_shared": 245077, |
| 227 | "locks_mutex_acquire_shared": 0, |
| 228 | "locks_oplog_acquire_exclusive": 0, |
| 229 | "locks_oplog_acquire_intent_exclusive": 1, |
| 230 | "locks_oplog_acquire_intent_shared": 16788, |
| 231 | "locks_oplog_acquire_shared": 0, |
| 232 | "memory_resident": 193986560, |
| 233 | "memory_virtual": 3023044608, |
| 234 | "metrics_cursor_lifespan_greater_than_or_equal_10_minutes": 0, |
| 235 | "metrics_cursor_lifespan_less_than_10_minutes": 0, |
| 236 | "metrics_cursor_lifespan_less_than_15_seconds": 0, |
| 237 | "metrics_cursor_lifespan_less_than_1_minute": 0, |
| 238 | "metrics_cursor_lifespan_less_than_1_second": 0, |
| 239 | "metrics_cursor_lifespan_less_than_30_seconds": 0, |
| 240 | "metrics_cursor_lifespan_less_than_5_seconds": 0, |
| 241 | "metrics_cursor_open_no_timeout": 0, |
| 242 | "metrics_cursor_open_total": 1, |
| 243 | "metrics_cursor_timed_out": 0, |
| 244 | "metrics_cursor_total_opened": 1, |
| 245 | "metrics_document_deleted": 7, |
| 246 | "metrics_document_inserted": 0, |
| 247 | "metrics_document_returned": 1699, |
| 248 | "metrics_document_updated": 52, |
| 249 | "metrics_query_executor_scanned": 61, |
| 250 | "metrics_query_executor_scanned_objects": 1760, |
| 251 | "network_bytes_in": 38851356, |
| 252 | "network_bytes_out": 706335836, |
| 253 | "network_requests": 130530, |
| 254 | "network_slow_dns_operations": 0, |
| 255 | "network_slow_ssl_operations": 0, |
| 256 | "operations_command": 125531, |
| 257 | "operations_delete": 7, |
| 258 | "operations_getmore": 5110, |
| 259 | "operations_insert": 0, |
| 260 | "operations_latencies_commands_latency": 46432082, |
| 261 | "operations_latencies_commands_ops": 125412, |
| 262 | "operations_latencies_reads_latency": 1009868, |
| 263 | "operations_latencies_reads_ops": 5111, |
| 264 | "operations_latencies_writes_latency": 0, |
| 265 | "operations_latencies_writes_ops": 0, |
| 266 | "operations_query": 76, |
| 267 | "operations_update": 59, |
| 268 | "tcmalloc_aggressive_memory_decommit": 0, |
| 269 | "tcmalloc_central_cache_free_bytes": 406680, |
| 270 | "tcmalloc_current_total_thread_cache_bytes": 2490832, |
| 271 | "tcmalloc_generic_current_allocated_bytes": 109050648, |
| 272 | "tcmalloc_generic_heap_size": 127213568, |
| 273 | "tcmalloc_max_total_thread_cache_bytes": 1073741824, |
| 274 | "tcmalloc_pageheap_commit_count": 376, |
| 275 | "tcmalloc_pageheap_committed_bytes": 127086592, |
| 276 | "tcmalloc_pageheap_decommit_count": 122, |
| 277 | "tcmalloc_pageheap_free_bytes": 13959168, |
| 278 | "tcmalloc_pageheap_reserve_count": 60, |
| 279 | "tcmalloc_pageheap_scavenge_bytes": 0, |
| 280 | "tcmalloc_pageheap_total_commit_bytes": 229060608, |
| 281 | "tcmalloc_pageheap_total_decommit_bytes": 101974016, |
| 282 | "tcmalloc_pageheap_total_reserve_bytes": 127213568, |
| 283 | "tcmalloc_pageheap_unmapped_bytes": 126976, |
| 284 | "tcmalloc_spinlock_total_delay_ns": 33426251, |
| 285 | "tcmalloc_thread_cache_free_bytes": 2490832, |
| 286 | "tcmalloc_total_free_bytes": 4076776, |
| 287 | "tcmalloc_transfer_cache_free_bytes": 1179264, |
| 288 | "txn_active": 0, |
| 289 | "txn_inactive": 0, |
| 290 | "txn_open": 0, |
| 291 | "txn_prepared": 0, |
| 292 | "txn_total_aborted": 0, |
| 293 | "txn_total_committed": 0, |
| 294 | "txn_total_prepared": 0, |
| 295 | "txn_total_started": 0, |
| 296 | "wiredtiger_cache_currently_in_cache_bytes": 814375, |
| 297 | "wiredtiger_cache_maximum_configured_bytes": 7854882816, |
| 298 | "wiredtiger_cache_modified_evicted_pages": 0, |
| 299 | "wiredtiger_cache_read_into_cache_pages": 108, |
| 300 | "wiredtiger_cache_tracked_dirty_in_the_cache_bytes": 456446, |
| 301 | "wiredtiger_cache_unmodified_evicted_pages": 0, |
| 302 | "wiredtiger_cache_written_from_cache_pages": 3177, |
| 303 | "wiredtiger_concurrent_txn_read_available": 128, |
| 304 | "wiredtiger_concurrent_txn_read_out": 0, |
| 305 | "wiredtiger_concurrent_txn_write_available": 128, |
| 306 | "wiredtiger_concurrent_txn_write_out": 0, |
| 307 | }, |
| 308 | }, |
| 309 | "success on Mongod Replica Set (v6)": { |
| 310 | prepare: caseMongodReplicaSet, |
| 311 | wantCollected: map[string]int64{ |
| 312 | "asserts_msg": 0, |
| 313 | "asserts_regular": 0, |
| 314 | "asserts_rollovers": 0, |
| 315 | "asserts_tripwire": 0, |
| 316 | "asserts_user": 246, |
| 317 | "asserts_warning": 0, |
| 318 | "connections_active": 7, |
| 319 | "connections_available": 838841, |
| 320 | "connections_awaiting_topology_changes": 5, |
| 321 | "connections_current": 19, |
| 322 | "connections_exhaust_hello": 2, |
| 323 | "connections_exhaust_is_master": 1, |
| 324 | "connections_threaded": 19, |
| 325 | "connections_total_created": 77, |
| 326 | "database_admin_collections": 3, |
| 327 | "database_admin_data_size": 796, |
| 328 | "database_admin_documents": 5, |
| 329 | "database_admin_index_size": 81920, |
| 330 | "database_admin_indexes": 4, |
| 331 | "database_admin_storage_size": 61440, |
| 332 | "database_admin_views": 0, |
| 333 | "database_config_collections": 3, |
| 334 | "database_config_data_size": 796, |
| 335 | "database_config_documents": 5, |
| 336 | "database_config_index_size": 81920, |
| 337 | "database_config_indexes": 4, |
| 338 | "database_config_storage_size": 61440, |
| 339 | "database_config_views": 0, |
| 340 | "database_local_collections": 3, |
| 341 | "database_local_data_size": 796, |
| 342 | "database_local_documents": 5, |
| 343 | "database_local_index_size": 81920, |
| 344 | "database_local_indexes": 4, |
| 345 | "database_local_storage_size": 61440, |
| 346 | "database_local_views": 0, |
| 347 | "extra_info_page_faults": 0, |
| 348 | "global_lock_active_clients_readers": 0, |
| 349 | "global_lock_active_clients_writers": 0, |
| 350 | "global_lock_current_queue_readers": 0, |
| 351 | "global_lock_current_queue_writers": 0, |
| 352 | "locks_collection_acquire_exclusive": 6, |
| 353 | "locks_collection_acquire_intent_exclusive": 172523, |
| 354 | "locks_collection_acquire_intent_shared": 336370, |
| 355 | "locks_collection_acquire_shared": 0, |
| 356 | "locks_database_acquire_exclusive": 3, |
| 357 | "locks_database_acquire_intent_exclusive": 172539, |
| 358 | "locks_database_acquire_intent_shared": 50971, |
| 359 | "locks_database_acquire_shared": 0, |
| 360 | "locks_global_acquire_exclusive": 6, |
| 361 | "locks_global_acquire_intent_exclusive": 174228, |
| 362 | "locks_global_acquire_intent_shared": 437905, |
| 363 | "locks_global_acquire_shared": 0, |
| 364 | "locks_mutex_acquire_exclusive": 0, |
| 365 | "locks_mutex_acquire_intent_exclusive": 0, |
| 366 | "locks_mutex_acquire_intent_shared": 245077, |
| 367 | "locks_mutex_acquire_shared": 0, |
| 368 | "locks_oplog_acquire_exclusive": 0, |
| 369 | "locks_oplog_acquire_intent_exclusive": 1, |
| 370 | "locks_oplog_acquire_intent_shared": 16788, |
| 371 | "locks_oplog_acquire_shared": 0, |
| 372 | "memory_resident": 193986560, |
| 373 | "memory_virtual": 3023044608, |
| 374 | "metrics_cursor_lifespan_greater_than_or_equal_10_minutes": 0, |
| 375 | "metrics_cursor_lifespan_less_than_10_minutes": 0, |
| 376 | "metrics_cursor_lifespan_less_than_15_seconds": 0, |
| 377 | "metrics_cursor_lifespan_less_than_1_minute": 0, |
| 378 | "metrics_cursor_lifespan_less_than_1_second": 0, |
| 379 | "metrics_cursor_lifespan_less_than_30_seconds": 0, |
| 380 | "metrics_cursor_lifespan_less_than_5_seconds": 0, |
| 381 | "metrics_cursor_open_no_timeout": 0, |
| 382 | "metrics_cursor_open_total": 1, |
| 383 | "metrics_cursor_timed_out": 0, |
| 384 | "metrics_cursor_total_opened": 1, |
| 385 | "metrics_document_deleted": 7, |
| 386 | "metrics_document_inserted": 0, |
| 387 | "metrics_document_returned": 1699, |
| 388 | "metrics_document_updated": 52, |
| 389 | "metrics_query_executor_scanned": 61, |
| 390 | "metrics_query_executor_scanned_objects": 1760, |
| 391 | "network_bytes_in": 38851356, |
| 392 | "network_bytes_out": 706335836, |
| 393 | "network_requests": 130530, |
| 394 | "network_slow_dns_operations": 0, |
| 395 | "network_slow_ssl_operations": 0, |
| 396 | "operations_command": 125531, |
| 397 | "operations_delete": 7, |
| 398 | "operations_getmore": 5110, |
| 399 | "operations_insert": 0, |
| 400 | "operations_latencies_commands_latency": 46432082, |
| 401 | "operations_latencies_commands_ops": 125412, |
| 402 | "operations_latencies_reads_latency": 1009868, |
| 403 | "operations_latencies_reads_ops": 5111, |
| 404 | "operations_latencies_writes_latency": 0, |
| 405 | "operations_latencies_writes_ops": 0, |
| 406 | "operations_query": 76, |
| 407 | "operations_update": 59, |
| 408 | "repl_set_member_mongodb-primary:27017_health_status_down": 0, |
| 409 | "repl_set_member_mongodb-primary:27017_health_status_up": 1, |
| 410 | "repl_set_member_mongodb-primary:27017_replication_lag": 4572, |
| 411 | "repl_set_member_mongodb-primary:27017_state_arbiter": 0, |
| 412 | "repl_set_member_mongodb-primary:27017_state_down": 0, |
| 413 | "repl_set_member_mongodb-primary:27017_state_primary": 1, |
| 414 | "repl_set_member_mongodb-primary:27017_state_recovering": 0, |
| 415 | "repl_set_member_mongodb-primary:27017_state_removed": 0, |
| 416 | "repl_set_member_mongodb-primary:27017_state_rollback": 0, |
| 417 | "repl_set_member_mongodb-primary:27017_state_secondary": 0, |
| 418 | "repl_set_member_mongodb-primary:27017_state_startup": 0, |
| 419 | "repl_set_member_mongodb-primary:27017_state_startup2": 0, |
| 420 | "repl_set_member_mongodb-primary:27017_state_unknown": 0, |
| 421 | "repl_set_member_mongodb-secondary:27017_health_status_down": 0, |
| 422 | "repl_set_member_mongodb-secondary:27017_health_status_up": 1, |
| 423 | "repl_set_member_mongodb-secondary:27017_heartbeat_latency": 1359, |
| 424 | "repl_set_member_mongodb-secondary:27017_ping_rtt": 0, |
| 425 | "repl_set_member_mongodb-secondary:27017_replication_lag": 4572, |
| 426 | "repl_set_member_mongodb-secondary:27017_state_arbiter": 0, |
| 427 | "repl_set_member_mongodb-secondary:27017_state_down": 0, |
| 428 | "repl_set_member_mongodb-secondary:27017_state_primary": 0, |
| 429 | "repl_set_member_mongodb-secondary:27017_state_recovering": 0, |
| 430 | "repl_set_member_mongodb-secondary:27017_state_removed": 0, |
| 431 | "repl_set_member_mongodb-secondary:27017_state_rollback": 0, |
| 432 | "repl_set_member_mongodb-secondary:27017_state_secondary": 1, |
| 433 | "repl_set_member_mongodb-secondary:27017_state_startup": 0, |
| 434 | "repl_set_member_mongodb-secondary:27017_state_startup2": 0, |
| 435 | "repl_set_member_mongodb-secondary:27017_state_unknown": 0, |
| 436 | "repl_set_member_mongodb-secondary:27017_uptime": 192370, |
| 437 | "tcmalloc_aggressive_memory_decommit": 0, |
| 438 | "tcmalloc_central_cache_free_bytes": 406680, |
| 439 | "tcmalloc_current_total_thread_cache_bytes": 2490832, |
| 440 | "tcmalloc_generic_current_allocated_bytes": 109050648, |
| 441 | "tcmalloc_generic_heap_size": 127213568, |
| 442 | "tcmalloc_max_total_thread_cache_bytes": 1073741824, |
| 443 | "tcmalloc_pageheap_commit_count": 376, |
| 444 | "tcmalloc_pageheap_committed_bytes": 127086592, |
| 445 | "tcmalloc_pageheap_decommit_count": 122, |
| 446 | "tcmalloc_pageheap_free_bytes": 13959168, |
| 447 | "tcmalloc_pageheap_reserve_count": 60, |
| 448 | "tcmalloc_pageheap_scavenge_bytes": 0, |
| 449 | "tcmalloc_pageheap_total_commit_bytes": 229060608, |
| 450 | "tcmalloc_pageheap_total_decommit_bytes": 101974016, |
| 451 | "tcmalloc_pageheap_total_reserve_bytes": 127213568, |
| 452 | "tcmalloc_pageheap_unmapped_bytes": 126976, |
| 453 | "tcmalloc_spinlock_total_delay_ns": 33426251, |
| 454 | "tcmalloc_thread_cache_free_bytes": 2490832, |
| 455 | "tcmalloc_total_free_bytes": 4076776, |
| 456 | "tcmalloc_transfer_cache_free_bytes": 1179264, |
| 457 | "txn_active": 0, |
| 458 | "txn_inactive": 0, |
| 459 | "txn_open": 0, |
| 460 | "txn_prepared": 0, |
| 461 | "txn_total_aborted": 0, |
| 462 | "txn_total_committed": 0, |
| 463 | "txn_total_prepared": 0, |
| 464 | "txn_total_started": 0, |
| 465 | "wiredtiger_cache_currently_in_cache_bytes": 814375, |
| 466 | "wiredtiger_cache_maximum_configured_bytes": 7854882816, |
| 467 | "wiredtiger_cache_modified_evicted_pages": 0, |
| 468 | "wiredtiger_cache_read_into_cache_pages": 108, |
| 469 | "wiredtiger_cache_tracked_dirty_in_the_cache_bytes": 456446, |
| 470 | "wiredtiger_cache_unmodified_evicted_pages": 0, |
| 471 | "wiredtiger_cache_written_from_cache_pages": 3177, |
| 472 | "wiredtiger_concurrent_txn_read_available": 128, |
| 473 | "wiredtiger_concurrent_txn_read_out": 0, |
| 474 | "wiredtiger_concurrent_txn_write_available": 128, |
| 475 | "wiredtiger_concurrent_txn_write_out": 0, |
| 476 | }, |
| 477 | }, |
| 478 | "success on Mongos (v6)": { |
| 479 | prepare: caseMongos, |
| 480 | wantCollected: map[string]int64{ |
| 481 | "asserts_msg": 0, |
| 482 | "asserts_regular": 0, |
| 483 | "asserts_rollovers": 0, |
| 484 | "asserts_tripwire": 0, |
| 485 | "asserts_user": 352, |
| 486 | "asserts_warning": 0, |
| 487 | "connections_active": 5, |
| 488 | "connections_available": 838842, |
| 489 | "connections_awaiting_topology_changes": 4, |
| 490 | "connections_current": 18, |
| 491 | "connections_exhaust_hello": 3, |
| 492 | "connections_exhaust_is_master": 0, |
| 493 | "connections_threaded": 18, |
| 494 | "connections_total_created": 89, |
| 495 | "database_admin_collections": 3, |
| 496 | "database_admin_data_size": 796, |
| 497 | "database_admin_documents": 5, |
| 498 | "database_admin_index_size": 81920, |
| 499 | "database_admin_indexes": 4, |
| 500 | "database_admin_storage_size": 61440, |
| 501 | "database_admin_views": 0, |
| 502 | "database_config_collections": 3, |
| 503 | "database_config_data_size": 796, |
| 504 | "database_config_documents": 5, |
| 505 | "database_config_index_size": 81920, |
| 506 | "database_config_indexes": 4, |
| 507 | "database_config_storage_size": 61440, |
| 508 | "database_config_views": 0, |
| 509 | "database_local_collections": 3, |
| 510 | "database_local_data_size": 796, |
| 511 | "database_local_documents": 5, |
| 512 | "database_local_index_size": 81920, |
| 513 | "database_local_indexes": 4, |
| 514 | "database_local_storage_size": 61440, |
| 515 | "database_local_views": 0, |
| 516 | "extra_info_page_faults": 526, |
| 517 | "memory_resident": 84934656, |
| 518 | "memory_virtual": 2596274176, |
| 519 | "metrics_document_deleted": 0, |
| 520 | "metrics_document_inserted": 0, |
| 521 | "metrics_document_returned": 0, |
| 522 | "metrics_document_updated": 0, |
| 523 | "metrics_query_executor_scanned": 0, |
| 524 | "metrics_query_executor_scanned_objects": 0, |
| 525 | "network_bytes_in": 57943348, |
| 526 | "network_bytes_out": 247343709, |
| 527 | "network_requests": 227310, |
| 528 | "network_slow_dns_operations": 0, |
| 529 | "network_slow_ssl_operations": 0, |
| 530 | "operations_command": 227283, |
| 531 | "operations_delete": 0, |
| 532 | "operations_getmore": 0, |
| 533 | "operations_insert": 0, |
| 534 | "operations_query": 10, |
| 535 | "operations_update": 0, |
| 536 | "shard_collections_partitioned": 1, |
| 537 | "shard_collections_unpartitioned": 1, |
| 538 | "shard_databases_partitioned": 1, |
| 539 | "shard_databases_unpartitioned": 1, |
| 540 | "shard_id_shard0_chunks": 1, |
| 541 | "shard_id_shard1_chunks": 1, |
| 542 | "shard_nodes_aware": 1, |
| 543 | "shard_nodes_unaware": 1, |
| 544 | "tcmalloc_aggressive_memory_decommit": 0, |
| 545 | "tcmalloc_central_cache_free_bytes": 736960, |
| 546 | "tcmalloc_current_total_thread_cache_bytes": 1638104, |
| 547 | "tcmalloc_generic_current_allocated_bytes": 13519784, |
| 548 | "tcmalloc_generic_heap_size": 24576000, |
| 549 | "tcmalloc_max_total_thread_cache_bytes": 1042284544, |
| 550 | "tcmalloc_pageheap_commit_count": 480, |
| 551 | "tcmalloc_pageheap_committed_bytes": 24518656, |
| 552 | "tcmalloc_pageheap_decommit_count": 127, |
| 553 | "tcmalloc_pageheap_free_bytes": 5697536, |
| 554 | "tcmalloc_pageheap_reserve_count": 15, |
| 555 | "tcmalloc_pageheap_scavenge_bytes": 0, |
| 556 | "tcmalloc_pageheap_total_commit_bytes": 84799488, |
| 557 | "tcmalloc_pageheap_total_decommit_bytes": 60280832, |
| 558 | "tcmalloc_pageheap_total_reserve_bytes": 24576000, |
| 559 | "tcmalloc_pageheap_unmapped_bytes": 57344, |
| 560 | "tcmalloc_spinlock_total_delay_ns": 96785212, |
| 561 | "tcmalloc_thread_cache_free_bytes": 1638104, |
| 562 | "tcmalloc_total_free_bytes": 5301336, |
| 563 | "tcmalloc_transfer_cache_free_bytes": 2926272, |
| 564 | "txn_active": 0, |
| 565 | "txn_commit_types_no_shards_initiated": 0, |
| 566 | "txn_commit_types_no_shards_successful": 0, |
| 567 | "txn_commit_types_no_shards_successful_duration_micros": 0, |
| 568 | "txn_commit_types_no_shards_unsuccessful": 0, |
| 569 | "txn_commit_types_read_only_initiated": 0, |
| 570 | "txn_commit_types_read_only_successful": 0, |
| 571 | "txn_commit_types_read_only_successful_duration_micros": 0, |
| 572 | "txn_commit_types_read_only_unsuccessful": 0, |
| 573 | "txn_commit_types_recover_with_token_initiated": 0, |
| 574 | "txn_commit_types_recover_with_token_successful": 0, |
| 575 | "txn_commit_types_recover_with_token_successful_duration_micros": 0, |
| 576 | "txn_commit_types_recover_with_token_unsuccessful": 0, |
| 577 | "txn_commit_types_single_shard_initiated": 0, |
| 578 | "txn_commit_types_single_shard_successful": 0, |
| 579 | "txn_commit_types_single_shard_successful_duration_micros": 0, |
| 580 | "txn_commit_types_single_shard_unsuccessful": 0, |
| 581 | "txn_commit_types_single_write_shard_initiated": 0, |
| 582 | "txn_commit_types_single_write_shard_successful": 0, |
| 583 | "txn_commit_types_single_write_shard_successful_duration_micros": 0, |
| 584 | "txn_commit_types_single_write_shard_unsuccessful": 0, |
| 585 | "txn_commit_types_two_phase_commit_initiated": 0, |
| 586 | "txn_commit_types_two_phase_commit_successful": 0, |
| 587 | "txn_commit_types_two_phase_commit_successful_duration_micros": 0, |
| 588 | "txn_commit_types_two_phase_commit_unsuccessful": 0, |
| 589 | "txn_inactive": 0, |
| 590 | "txn_open": 0, |
| 591 | "txn_total_aborted": 0, |
| 592 | "txn_total_committed": 0, |
| 593 | "txn_total_started": 0, |
| 594 | }, |
| 595 | }, |
| 596 | } |
| 597 | |
| 598 | for name, test := range tests { |
| 599 | t.Run(name, func(t *testing.T) { |
| 600 | collr := prepareMongo() |
| 601 | defer collr.Cleanup(context.Background()) |
| 602 | collr.conn = test.prepare() |
| 603 | |
| 604 | require.NoError(t, collr.Init(context.Background())) |
| 605 | |
| 606 | mx := collr.Collect(context.Background()) |
| 607 | |
| 608 | assert.Equal(t, test.wantCollected, mx) |
| 609 | }) |
| 610 | } |
| 611 | } |
| 612 | |
| 613 | func prepareMongo() *Collector { |
| 614 | collr := New() |
| 615 | collr.Databases = matcher.SimpleExpr{Includes: []string{"* *"}} |
| 616 | return collr |
| 617 | } |
| 618 | |
| 619 | func caseMongodReplicaSet() *mockMongoClient { |
| 620 | return &mockMongoClient{replicaSet: true} |
| 621 | } |
| 622 | |
| 623 | func caseMongod() *mockMongoClient { |
| 624 | return &mockMongoClient{} |
| 625 | } |
| 626 | |
| 627 | func caseMongos() *mockMongoClient { |
| 628 | return &mockMongoClient{mongos: true} |
| 629 | } |
| 630 | |
| 631 | type mockMongoClient struct { |
| 632 | replicaSet bool |
| 633 | mongos bool |
| 634 | errOnServerStatus bool |
| 635 | errOnListDatabaseNames bool |
| 636 | errOnDbStats bool |
| 637 | errOnReplSetGetStatus bool |
| 638 | errOnShardNodes bool |
| 639 | errOnShardDatabasesPartitioning bool |
| 640 | errOnShardCollectionsPartitioning bool |
| 641 | errOnShardChunks bool |
| 642 | errOnInitClient bool |
| 643 | clientInited bool |
| 644 | closeCalled bool |
| 645 | } |
| 646 | |
| 647 | func (m *mockMongoClient) serverStatus() (*documentServerStatus, error) { |
| 648 | if !m.clientInited { |
| 649 | return nil, errors.New("mock.serverStatus() error: mongo client not inited") |
| 650 | } |
| 651 | if m.errOnServerStatus { |
| 652 | return nil, errors.New("mock.serverStatus() error") |
| 653 | } |
| 654 | |
| 655 | data := dataVer6MongodServerStatus |
| 656 | if m.mongos { |
| 657 | data = dataVer6MongosServerStatus |
| 658 | } |
| 659 | |
| 660 | var s documentServerStatus |
| 661 | if err := json.Unmarshal(data, &s); err != nil { |
| 662 | return nil, err |
| 663 | } |
| 664 | |
| 665 | return &s, nil |
| 666 | } |
| 667 | |
| 668 | func (m *mockMongoClient) listDatabaseNames() ([]string, error) { |
| 669 | if !m.clientInited { |
| 670 | return nil, errors.New("mock.listDatabaseNames() error: mongo client not inited") |
| 671 | } |
| 672 | if m.errOnListDatabaseNames { |
| 673 | return nil, errors.New("mock.listDatabaseNames() error") |
| 674 | } |
| 675 | return []string{"admin", "config", "local"}, nil |
| 676 | } |
| 677 | |
| 678 | func (m *mockMongoClient) dbStats(_ string) (*documentDBStats, error) { |
| 679 | if !m.clientInited { |
| 680 | return nil, errors.New("mock.dbStats() error: mongo client not inited") |
| 681 | } |
| 682 | if m.errOnDbStats { |
| 683 | return nil, errors.New("mock.dbStats() error") |
| 684 | } |
| 685 | |
| 686 | var s documentDBStats |
| 687 | if err := json.Unmarshal(dataVer6DbStats, &s); err != nil { |
| 688 | return nil, err |
| 689 | } |
| 690 | |
| 691 | return &s, nil |
| 692 | } |
| 693 | |
| 694 | func (m *mockMongoClient) isReplicaSet() bool { |
| 695 | return m.replicaSet |
| 696 | } |
| 697 | |
| 698 | func (m *mockMongoClient) isMongos() bool { |
| 699 | return m.mongos |
| 700 | } |
| 701 | |
| 702 | func (m *mockMongoClient) replSetGetStatus() (*documentReplSetStatus, error) { |
| 703 | if !m.clientInited { |
| 704 | return nil, errors.New("mock.replSetGetStatus() error: mongo client not inited") |
| 705 | } |
| 706 | if m.mongos { |
| 707 | return nil, errors.New("mock.replSetGetStatus() error: shouldn't be called for mongos") |
| 708 | } |
| 709 | if !m.replicaSet { |
| 710 | return nil, errors.New("mock.replSetGetStatus() error: should be called for replica set") |
| 711 | } |
| 712 | if m.errOnReplSetGetStatus { |
| 713 | return nil, errors.New("mock.replSetGetStatus() error") |
| 714 | } |
| 715 | |
| 716 | var s documentReplSetStatus |
| 717 | if err := json.Unmarshal(dataVer6ReplSetGetStatus, &s); err != nil { |
| 718 | return nil, err |
| 719 | } |
| 720 | |
| 721 | return &s, nil |
| 722 | } |
| 723 | |
| 724 | func (m *mockMongoClient) shardNodes() (*documentShardNodesResult, error) { |
| 725 | if !m.clientInited { |
| 726 | return nil, errors.New("mock.shardNodes() error: mongo client not inited") |
| 727 | } |
| 728 | if m.replicaSet { |
| 729 | return nil, errors.New("mock.replSetGetStatus() error: shouldn't be called for replica set") |
| 730 | } |
| 731 | if !m.mongos { |
| 732 | return nil, errors.New("mock.shardNodes() error: should be called for mongos") |
| 733 | } |
| 734 | if m.errOnShardNodes { |
| 735 | return nil, errors.New("mock.shardNodes() error") |
| 736 | } |
| 737 | |
| 738 | return &documentShardNodesResult{ |
| 739 | ShardAware: 1, |
| 740 | ShardUnaware: 1, |
| 741 | }, nil |
| 742 | } |
| 743 | |
| 744 | func (m *mockMongoClient) shardDatabasesPartitioning() (*documentPartitionedResult, error) { |
| 745 | if !m.clientInited { |
| 746 | return nil, errors.New("mock.shardDatabasesPartitioning() error: mongo client not inited") |
| 747 | } |
| 748 | if m.replicaSet { |
| 749 | return nil, errors.New("mock.shardDatabasesPartitioning() error: shouldn't be called for replica set") |
| 750 | } |
| 751 | if !m.mongos { |
| 752 | return nil, errors.New("mock.shardDatabasesPartitioning() error: should be called for mongos") |
| 753 | } |
| 754 | if m.errOnShardDatabasesPartitioning { |
| 755 | return nil, errors.New("mock.shardDatabasesPartitioning() error") |
| 756 | } |
| 757 | |
| 758 | return &documentPartitionedResult{ |
| 759 | Partitioned: 1, |
| 760 | UnPartitioned: 1, |
| 761 | }, nil |
| 762 | } |
| 763 | |
| 764 | func (m *mockMongoClient) shardCollectionsPartitioning() (*documentPartitionedResult, error) { |
| 765 | if !m.clientInited { |
| 766 | return nil, errors.New("mock.shardCollectionsPartitioning() error: mongo client not inited") |
| 767 | } |
| 768 | if m.replicaSet { |
| 769 | return nil, errors.New("mock.shardCollectionsPartitioning() error: shouldn't be called for replica set") |
| 770 | } |
| 771 | if !m.mongos { |
| 772 | return nil, errors.New("mock.shardCollectionsPartitioning() error: should be called for mongos") |
| 773 | } |
| 774 | if m.errOnShardCollectionsPartitioning { |
| 775 | return nil, errors.New("mock.shardCollectionsPartitioning() error") |
| 776 | } |
| 777 | |
| 778 | return &documentPartitionedResult{ |
| 779 | Partitioned: 1, |
| 780 | UnPartitioned: 1, |
| 781 | }, nil |
| 782 | } |
| 783 | |
| 784 | func (m *mockMongoClient) shardChunks() (map[string]int64, error) { |
| 785 | if !m.clientInited { |
| 786 | return nil, errors.New("mock.shardChunks() error: mongo client not inited") |
| 787 | } |
| 788 | if m.replicaSet { |
| 789 | return nil, errors.New("mock.shardChunks() error: shouldn't be called for replica set") |
| 790 | } |
| 791 | if !m.mongos { |
| 792 | return nil, errors.New("mock.shardChunks() error: should be called for mongos") |
| 793 | } |
| 794 | if m.errOnShardChunks { |
| 795 | return nil, errors.New("mock.shardChunks() error") |
| 796 | } |
| 797 | |
| 798 | return map[string]int64{ |
| 799 | "shard0": 1, |
| 800 | "shard1": 1, |
| 801 | }, nil |
| 802 | } |
| 803 | |
| 804 | func (m *mockMongoClient) initClient(_ string, _ time.Duration) error { |
| 805 | if m.errOnInitClient { |
| 806 | return errors.New("mock.initClient() error") |
| 807 | } |
| 808 | m.clientInited = true |
| 809 | return nil |
| 810 | } |
| 811 | |
| 812 | func (m *mockMongoClient) close() error { |
| 813 | if m.clientInited { |
| 814 | m.closeCalled = true |
| 815 | } |
| 816 | return nil |
| 817 | } |