| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | package mongo |
| 4 | |
| 5 | import ( |
| 6 | "fmt" |
| 7 | "maps" |
| 8 | "reflect" |
| 9 | |
| 10 | "github.com/netdata/netdata/go/plugins/pkg/stm" |
| 11 | "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi" |
| 12 | ) |
| 13 | |
| 14 | // collectServerStatus creates the map[string]int64 for the available dims. |
| 15 | // nil values will be ignored and not added to the map and thus metrics should not appear on the dashboard. |
| 16 | // Because mongo reports a metric only after it first appears,some dims might take a while to appear. |
| 17 | // For example, in order to report number of create commands, a document must be created first. |
| 18 | func (c *Collector) collectServerStatus(mx map[string]int64) error { |
| 19 | s, err := c.conn.serverStatus() |
| 20 | if err != nil { |
| 21 | return fmt.Errorf("serverStatus command failed: %s", err) |
| 22 | } |
| 23 | |
| 24 | c.addOptionalCharts(s) |
| 25 | |
| 26 | maps.Copy(mx, stm.ToMap(s)) |
| 27 | |
| 28 | if s.Transactions != nil && s.Transactions.CommitTypes != nil { |
| 29 | px := "txn_commit_types_" |
| 30 | v := s.Transactions.CommitTypes |
| 31 | mx[px+"no_shards_unsuccessful"] = v.NoShards.Initiated - v.NoShards.Successful |
| 32 | mx[px+"single_shard_unsuccessful"] = v.SingleShard.Initiated - v.SingleShard.Successful |
| 33 | mx[px+"single_write_shard_unsuccessful"] = v.SingleWriteShard.Initiated - v.SingleWriteShard.Successful |
| 34 | mx[px+"read_only_unsuccessful"] = v.ReadOnly.Initiated - v.ReadOnly.Successful |
| 35 | mx[px+"two_phase_commit_unsuccessful"] = v.TwoPhaseCommit.Initiated - v.TwoPhaseCommit.Successful |
| 36 | mx[px+"recover_with_token_unsuccessful"] = v.RecoverWithToken.Initiated - v.RecoverWithToken.Successful |
| 37 | } |
| 38 | |
| 39 | return nil |
| 40 | } |
| 41 | |
| 42 | func (c *Collector) addOptionalCharts(s *documentServerStatus) { |
| 43 | c.addOptionalChart(s.OpLatencies, |
| 44 | &chartOperationsRate, |
| 45 | &chartOperationsLatencyTime, |
| 46 | ) |
| 47 | c.addOptionalChart(s.WiredTiger, |
| 48 | &chartWiredTigerConcurrentReadTransactionsUsage, |
| 49 | &chartWiredTigerConcurrentWriteTransactionsUsage, |
| 50 | &chartWiredTigerCacheUsage, |
| 51 | &chartWiredTigerCacheDirtySpaceSize, |
| 52 | &chartWiredTigerCacheIORate, |
| 53 | &chartWiredTigerCacheEvictionsRate, |
| 54 | ) |
| 55 | c.addOptionalChart(s.Tcmalloc, |
| 56 | &chartMemoryTCMallocStatsChart, |
| 57 | ) |
| 58 | c.addOptionalChart(s.GlobalLock, |
| 59 | &chartGlobalLockActiveClientsCount, |
| 60 | &chartGlobalLockCurrentQueueCount, |
| 61 | ) |
| 62 | c.addOptionalChart(s.Network.NumSlowDNSOperations, |
| 63 | &chartNetworkSlowDNSResolutionsRate, |
| 64 | ) |
| 65 | c.addOptionalChart(s.Network.NumSlowSSLOperations, |
| 66 | &chartNetworkSlowSSLHandshakesRate, |
| 67 | ) |
| 68 | c.addOptionalChart(s.Metrics.Cursor.TotalOpened, |
| 69 | &chartCursorsOpenedRate, |
| 70 | ) |
| 71 | c.addOptionalChart(s.Metrics.Cursor.TimedOut, |
| 72 | &chartCursorsTimedOutRate, |
| 73 | ) |
| 74 | c.addOptionalChart(s.Metrics.Cursor.Open.Total, |
| 75 | &chartCursorsOpenCount, |
| 76 | ) |
| 77 | c.addOptionalChart(s.Metrics.Cursor.Open.NoTimeout, |
| 78 | &chartCursorsOpenNoTimeoutCount, |
| 79 | ) |
| 80 | c.addOptionalChart(s.Metrics.Cursor.Lifespan, |
| 81 | &chartCursorsByLifespanCount, |
| 82 | ) |
| 83 | |
| 84 | if s.Transactions != nil { |
| 85 | c.addOptionalChart(s.Transactions, |
| 86 | &chartTransactionsCount, |
| 87 | &chartTransactionsRate, |
| 88 | ) |
| 89 | c.addOptionalChart(s.Transactions.CommitTypes, |
| 90 | &chartTransactionsNoShardsCommitsRate, |
| 91 | &chartTransactionsNoShardsCommitsDurationTime, |
| 92 | &chartTransactionsSingleShardCommitsRate, |
| 93 | &chartTransactionsSingleShardCommitsDurationTime, |
| 94 | &chartTransactionsSingleWriteShardCommitsRate, |
| 95 | &chartTransactionsSingleWriteShardCommitsDurationTime, |
| 96 | &chartTransactionsReadOnlyCommitsRate, |
| 97 | &chartTransactionsReadOnlyCommitsDurationTime, |
| 98 | &chartTransactionsTwoPhaseCommitCommitsRate, |
| 99 | &chartTransactionsTwoPhaseCommitCommitsDurationTime, |
| 100 | &chartTransactionsRecoverWithTokenCommitsRate, |
| 101 | &chartTransactionsRecoverWithTokenCommitsDurationTime, |
| 102 | ) |
| 103 | } |
| 104 | if s.Locks != nil { |
| 105 | c.addOptionalChart(s.Locks.Global, &chartGlobalLockAcquisitionsRate) |
| 106 | c.addOptionalChart(s.Locks.Database, &chartDatabaseLockAcquisitionsRate) |
| 107 | c.addOptionalChart(s.Locks.Collection, &chartCollectionLockAcquisitionsRate) |
| 108 | c.addOptionalChart(s.Locks.Mutex, &chartMutexLockAcquisitionsRate) |
| 109 | c.addOptionalChart(s.Locks.Metadata, &chartMetadataLockAcquisitionsRate) |
| 110 | c.addOptionalChart(s.Locks.Oplog, &chartOpLogLockAcquisitionsRate) |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | func (c *Collector) addOptionalChart(iface any, charts ...*collectorapi.Chart) { |
| 115 | if reflect.ValueOf(iface).IsNil() { |
| 116 | return |
| 117 | } |
| 118 | for _, chart := range charts { |
| 119 | if c.optionalCharts[chart.ID] { |
| 120 | continue |
| 121 | } |
| 122 | c.optionalCharts[chart.ID] = true |
| 123 | |
| 124 | if err := c.charts.Add(chart.Copy()); err != nil { |
| 125 | c.Warning(err) |
| 126 | } |
| 127 | } |
| 128 | } |