diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/supervisord/collect.go | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/supervisord/collect.go b/src/go/collectors/go.d.plugin/modules/supervisord/collect.go new file mode 100644 index 000000000..e04e32131 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/supervisord/collect.go @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package supervisord + +import ( + "fmt" + "strings" + + "github.com/netdata/netdata/go/go.d.plugin/agent/module" +) + +func (s *Supervisord) collect() (map[string]int64, error) { + info, err := s.client.getAllProcessInfo() + if err != nil { + return nil, err + } + + ms := make(map[string]int64) + s.collectAllProcessInfo(ms, info) + + return ms, nil +} + +func (s *Supervisord) collectAllProcessInfo(ms map[string]int64, info []processStatus) { + s.resetCache() + ms["running_processes"] = 0 + ms["non_running_processes"] = 0 + for _, p := range info { + if _, ok := s.cache[p.group]; !ok { + s.cache[p.group] = make(map[string]bool) + s.addProcessGroupCharts(p) + } + if _, ok := s.cache[p.group][p.name]; !ok { + s.addProcessToCharts(p) + } + s.cache[p.group][p.name] = true + + ms["group_"+p.group+"_running_processes"] += 0 + ms["group_"+p.group+"_non_running_processes"] += 0 + if isProcRunning(p) { + ms["running_processes"] += 1 + ms["group_"+p.group+"_running_processes"] += 1 + } else { + ms["non_running_processes"] += 1 + ms["group_"+p.group+"_non_running_processes"] += 1 + } + id := procID(p) + ms[id+"_state_code"] = int64(p.state) + ms[id+"_exit_status"] = int64(p.exitStatus) + ms[id+"_uptime"] = calcProcessUptime(p) + ms[id+"_downtime"] = calcProcessDowntime(p) + } + s.cleanupCache() +} + +func (s *Supervisord) resetCache() { + for _, procs := range s.cache { + for name := range procs { + procs[name] = false + } + } +} + +func (s *Supervisord) cleanupCache() { + for group, procs := range s.cache { + for name, ok := range procs { + if !ok { + s.removeProcessFromCharts(group, name) + delete(s.cache[group], name) + } + } + if len(s.cache[group]) == 0 { + s.removeProcessGroupCharts(group) + delete(s.cache, group) + } + } +} + +func calcProcessUptime(p processStatus) int64 { + if !isProcRunning(p) { + return 0 + } + return int64(p.now - p.start) +} + +func calcProcessDowntime(p processStatus) int64 { + if isProcRunning(p) || p.stop == 0 { + return 0 + } + return int64(p.now - p.stop) +} + +func (s *Supervisord) addProcessGroupCharts(p processStatus) { + charts := newProcGroupCharts(p.group) + if err := s.Charts().Add(*charts...); err != nil { + s.Warning(err) + } +} + +func (s *Supervisord) addProcessToCharts(p processStatus) { + id := procID(p) + for _, c := range *s.Charts() { + var dimID string + switch c.ID { + case fmt.Sprintf(groupProcessesStateCodeChartTmpl.ID, p.group): + dimID = id + "_state_code" + case fmt.Sprintf(groupProcessesExitStatusChartTmpl.ID, p.group): + dimID = id + "_exit_status" + case fmt.Sprintf(groupProcessesUptimeChartTmpl.ID, p.group): + dimID = id + "_uptime" + case fmt.Sprintf(groupProcessesDowntimeChartTmpl.ID, p.group): + dimID = id + "_downtime" + default: + continue + } + dim := &module.Dim{ID: dimID, Name: p.name} + if err := c.AddDim(dim); err != nil { + s.Warning(err) + return + } + c.MarkNotCreated() + } +} + +func (s *Supervisord) removeProcessGroupCharts(group string) { + prefix := "group_" + group + for _, c := range *s.Charts() { + if strings.HasPrefix(c.ID, prefix) { + c.MarkRemove() + c.MarkNotCreated() + } + } +} + +func (s *Supervisord) removeProcessFromCharts(group, name string) { + id := procID(processStatus{name: name, group: group}) + for _, c := range *s.Charts() { + var dimID string + switch c.ID { + case fmt.Sprintf(groupProcessesStateCodeChartTmpl.ID, group): + dimID = id + "_state_code" + case fmt.Sprintf(groupProcessesExitStatusChartTmpl.ID, group): + dimID = id + "_exit_status" + case fmt.Sprintf(groupProcessesUptimeChartTmpl.ID, group): + dimID = id + "_uptime" + case fmt.Sprintf(groupProcessesDowntimeChartTmpl.ID, group): + dimID = id + "_downtime" + default: + continue + } + if err := c.MarkDimRemove(dimID, true); err != nil { + s.Warning(err) + return + } + c.MarkNotCreated() + } +} + +func procID(p processStatus) string { + return fmt.Sprintf("group_%s_process_%s", p.group, p.name) +} + +func isProcRunning(p processStatus) bool { + // http://supervisord.org/subprocess.html#process-states + // STOPPED (0) + // STARTING (10) + // RUNNING (20) + // BACKOFF (30) + // STOPPING (40) + // EXITED (100) + // FATAL (200) + // UNKNOWN (1000) + return p.state == 20 +} |