diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/phpfpm/decode.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go b/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go new file mode 100644 index 000000000..021e1fb4c --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package phpfpm + +import ( + "bufio" + "encoding/json" + "errors" + "io" + "strconv" + "strings" +) + +type decoder func(r io.Reader, s *status) error + +func decodeJSON(r io.Reader, s *status) error { + return json.NewDecoder(r).Decode(s) +} + +func decodeText(r io.Reader, s *status) error { + parts := readParts(r) + if len(parts) == 0 { + return errors.New("invalid text format") + } + + part, parts := parts[0], parts[1:] + if err := readStatus(part, s); err != nil { + return err + } + + return readProcesses(parts, s) +} + +func readParts(r io.Reader) [][]string { + sc := bufio.NewScanner(r) + + var parts [][]string + var lines []string + for sc.Scan() { + line := strings.Trim(sc.Text(), "\r\n ") + // Split parts by star border + if strings.HasPrefix(line, "***") { + parts = append(parts, lines) + lines = []string{} + continue + } + // Skip empty lines + if line == "" { + continue + } + lines = append(lines, line) + } + + if len(lines) > 0 { + parts = append(parts, lines) + } + return parts +} + +func readStatus(data []string, s *status) error { + for _, line := range data { + key, val, err := parseLine(line) + if err != nil { + return err + } + + switch key { + case "active processes": + s.Active = parseInt(val) + case "max active processes": + s.MaxActive = parseInt(val) + case "idle processes": + s.Idle = parseInt(val) + case "accepted conn": + s.Requests = parseInt(val) + case "max children reached": + s.Reached = parseInt(val) + case "slow requests": + s.Slow = parseInt(val) + } + } + return nil +} + +func readProcesses(procs [][]string, s *status) error { + for _, part := range procs { + var proc proc + for _, line := range part { + key, val, err := parseLine(line) + if err != nil { + return err + } + + switch key { + case "state": + proc.State = val + case "request duration": + proc.Duration = requestDuration(parseInt(val)) + case "last request cpu": + proc.CPU = parseFloat(val) + case "last request memory": + proc.Memory = parseInt(val) + } + } + s.Processes = append(s.Processes, proc) + } + return nil +} + +func parseLine(s string) (string, string, error) { + kv := strings.SplitN(s, ":", 2) + if len(kv) != 2 { + return "", "", errors.New("invalid text format line") + } + return strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]), nil +} + +func parseInt(s string) int64 { + val, err := strconv.ParseInt(strings.TrimSpace(s), 10, 64) + if err != nil { + return 0 + } + return val +} + +func parseFloat(s string) float64 { + val, err := strconv.ParseFloat(strings.TrimSpace(s), 64) + if err != nil { + return 0 + } + return val +} |