github.com/netdata/go.d.plugin@v0.58.1/modules/mongodb/collect_replsetgetstatus.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package mongo 4 5 import ( 6 "fmt" 7 "strings" 8 9 "github.com/netdata/go.d.plugin/agent/module" 10 ) 11 12 // https://www.mongodb.com/docs/manual/reference/replica-states/#replica-set-member-states 13 var replicaSetMemberStates = map[string]int{ 14 "startup": 0, 15 "primary": 1, 16 "secondary": 2, 17 "recovering": 3, 18 "startup2": 5, 19 "unknown": 6, 20 "arbiter": 7, 21 "down": 8, 22 "rollback": 9, 23 "removed": 10, 24 } 25 26 // TODO: deal with duplicates if we collect metrics from all cluster nodes 27 // should we only collect ReplSetStatus (at least by default) from primary nodes? (db.runCommand( { isMaster: 1 } )) 28 func (m *Mongo) collectReplSetStatus(mx map[string]int64) error { 29 s, err := m.conn.replSetGetStatus() 30 if err != nil { 31 return fmt.Errorf("error get status of the replica set from mongo: %s", err) 32 } 33 34 seen := make(map[string]documentReplSetMember) 35 36 for _, member := range s.Members { 37 seen[member.Name] = member 38 39 px := fmt.Sprintf("repl_set_member_%s_", member.Name) 40 41 mx[px+"replication_lag"] = s.Date.Sub(member.OptimeDate).Milliseconds() 42 43 for k, v := range replicaSetMemberStates { 44 mx[px+"state_"+k] = boolToInt(member.State == v) 45 } 46 47 mx[px+"health_status_up"] = boolToInt(member.Health == 1) 48 mx[px+"health_status_down"] = boolToInt(member.Health == 0) 49 50 if member.Self == nil { 51 mx[px+"uptime"] = member.Uptime 52 if v := member.LastHeartbeatRecv; v != nil && !v.IsZero() { 53 mx[px+"heartbeat_latency"] = s.Date.Sub(*v).Milliseconds() 54 } 55 if v := member.PingMs; v != nil { 56 mx[px+"ping_rtt"] = *v 57 } 58 } 59 } 60 61 for name, member := range seen { 62 if !m.replSetMembers[name] { 63 m.replSetMembers[name] = true 64 m.Debugf("new replica set member '%s': adding charts", name) 65 m.addReplSetMemberCharts(member) 66 } 67 } 68 69 for name := range m.replSetMembers { 70 if _, ok := seen[name]; !ok { 71 delete(m.replSetMembers, name) 72 m.Debugf("stale replica set member '%s': removing charts", name) 73 m.removeReplSetMemberCharts(name) 74 } 75 } 76 77 return nil 78 } 79 80 func (m *Mongo) addReplSetMemberCharts(v documentReplSetMember) { 81 charts := chartsTmplReplSetMember.Copy() 82 83 if v.Self != nil { 84 _ = charts.Remove(chartTmplReplSetMemberHeartbeatLatencyTime.ID) 85 _ = charts.Remove(chartTmplReplSetMemberPingRTTTime.ID) 86 _ = charts.Remove(chartTmplReplSetMemberUptime.ID) 87 } 88 89 for _, chart := range *charts { 90 chart.ID = fmt.Sprintf(chart.ID, v.Name) 91 chart.Labels = []module.Label{ 92 {Key: "repl_set_member", Value: v.Name}, 93 } 94 for _, dim := range chart.Dims { 95 dim.ID = fmt.Sprintf(dim.ID, v.Name) 96 } 97 } 98 99 if err := m.Charts().Add(*charts...); err != nil { 100 m.Warning(err) 101 } 102 } 103 104 func (m *Mongo) removeReplSetMemberCharts(name string) { 105 px := fmt.Sprintf("%s%s_", chartPxReplSetMember, name) 106 107 for _, chart := range *m.Charts() { 108 if strings.HasPrefix(chart.ID, px) { 109 chart.MarkRemove() 110 chart.MarkNotCreated() 111 } 112 } 113 }