summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/collectors/go.d.plugin/modules/mongodb/collect_replsetgetstatus.go113
1 files changed, 113 insertions, 0 deletions
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()
+ }
+ }
+}